Compare commits

...
410 Commits
Author SHA1 Message Date
Martin Herkt e6b85c9170 Release 0.21.0 2016-10-19 23:10:13 +02:00
Martin Herkt 5d74fa7dc0 Merge branch 'master' into release/current 2016-10-19 19:09:00 +02:00
wm4 a2fa0d0b68 demux_lavf: don't accidentally enable edit list crap on Libav
You really don't get a break from all the multiple bullshit.
2016-10-18 19:14:15 +02:00
wm4 b86a2316df demux_lavf: "support" mov edit lists and log errors if used
FFmpeg recently got "support" for mov edit lists. This is a terrible
hack that will fail completely at least with some decoders (in
particular wrappers for hardware decoding might be affected). As such it
makes no point to pretend they are supported, even if we assume that the
"intended" functionality works, that there are no implementation bugs
(good luck with all that messy code added to the already huge mov
demuxer), and that it covers enough of the mov edit list feature to be
of value.

So log an error if the FFmpeg code for mov edit lists appears to be
active - AV_PKT_FLAG_DISCARD is used only for "clipping" edit list
segments on non-key frame boundaries.

In the first place, FFmpeg committed this only because Google wanted it
in, and patch review did not even pick up obvious issues. (Just look how
there was no lavc version bump when AV_PKT_FLAG_DISCARD was added.)

We still pass the new packet flag to the decoders (av_common.c change),
which means we "support" FFmpeg's edit list code now. (Until it breaks
due to FFmpeg not caring about all the details.)
2016-10-18 16:57:02 +02:00
Ricardo Constantino 912d668ea8 osc: use the same characters as track list for playlist/chapter
Had only tested with luajit which supports the \xHH syntax added
in Lua 5.2.

The arrow is troublesome to use since the ideal way to use it, as
the OSD code uses it, needs \alpha&H00<arrow>\r to work, which
does not in OSC's way of showing messages.
2016-10-17 19:00:17 +01:00
Ben Boeckel c398ab7520 ISSUE_TEMPLATE: minor grammar update 2016-10-17 19:23:23 +02:00
schnusch 68839e4e77 stream_bluray: check title index/playlist range
Blu-ray title index/playlist must be in the range 0-99999, otherwise
an error will be returned
2016-10-17 19:23:11 +02:00
schnusch 51dbb5607e stream_bluray: select title by playlist
Blu-ray titles can now be selected by playlist number like this:
    bd://mpls/[playlist]
2016-10-17 19:23:07 +02:00
wm4 139f6b5de7 ad_lavc, vd_lavc: fix a recent libavcodec deprecation warning
Both AVFrame.pts and AVFrame.pkt_pts have existed for a long time. Until
now, decoders always returned the pts via the pkt_pts field, while the
pts field was used for encoding and libavfilter only. Recently, pkt_pts
was deprecated, and pts was switched to always carry the pts.

This means we have to be careful not to accidentally use the wrong
field, depending on the libavcodec version. We have to explicitly check
the version numbers. Of course the version numbers are completely
idiotic, because idiotically the pkg-config and library names are the
same for FFmpeg and Libav, so we have to deal with this explicitly as
well.
2016-10-17 19:18:03 +02:00
Ricardo Constantino 118d7a310e man/osc: better explain the values of deadzonesize 2016-10-17 16:01:25 +01:00
Philip Langdale 0a81fe1cf9 vd_lavc: Add hwdec wrapper for crystalhd
This hardware decodes to system memory so it only requires a wrapper.
2016-10-15 17:44:23 +02:00
Ricardo Constantino 8956229ee4 osc: fix chapter/playlist listing if empty 2016-10-15 13:58:52 +01:00
Ricardo Constantino 992bdc9411 osc: show playlist/chapter list on prev/next instead of osd 2016-10-15 12:27:04 +01:00
Ricardo Constantino 5d3657e092 osc: fix listing of chapters and playlist
Fixes regression since 05c398f.

Add helper functions for limiting potentially huge lists of
playlists and chapters and use them.
2016-10-15 12:27:04 +01:00
Ricardo Constantino 06065dc5ef osc: fix display of chapters and playlist scaling
Compensate \fs when using non-default scale(fullscreen|windowed).
2016-10-15 12:27:04 +01:00
Ricardo Constantino 2a99e7ae12 osc: add user-alterable margin for top/bottombar 2016-10-15 12:24:01 +01:00
Ricardo Constantino b99dc17f8e osc: add right-click behavior to playlist and chapter buttons 2016-10-15 12:24:01 +01:00
Ricardo Constantino 8bb57c0387 osc: change default layout to bottombar
Change a few other defaults accordingly:
- seekbarstyle=bar looks better with bottombar.
- Bigger scalewindowed and scalefullscreen make bottom/topbar more readable.
2016-10-15 12:24:01 +01:00
Ricardo Constantino 13259f35c8 ytdl_hook: Add title to playlist items if available 2016-10-15 01:33:27 +01:00
wm4 a049a3240e stream_file: don't use poll() on directories
POSIX leaves poll() behavior on directories unspecified. While on
Linux, it seems to behave the same way as regular files (always
return immediately), this is not guaranteed. At least with OSX
10.12, it seems to wait, which essentially means that opening
directories will "hang".

Fixes #3530 and #3649.
2016-10-14 17:19:47 -06:00
James Ross-Gowan 0af8811b15 terminal-win: support modifier keys in console input
Keyboard input in the console still isn't quite as flexible as it is in
the video window. Ctrl+<letter> and Ctrl+LEFT/RIGHT work, but
Ctrl+Alt+<letter> and Ctrl+<number> do not. Also, in the new Windows 10
console, a bunch of Ctrl keystrokes including Ctrl+UP/DOWN are handled
by the console window and not passed to the application.

Unlike in w32_common.c, we can't really translate keyboaard input
ourselves because the keyboard layout of the console window (in
conhost.exe) doesn't necessarily match the keyboard layout of mpv's
console input thread, however, using ToUnicode as a fallback when the
console doesn't return a unicode value could be a possible future
improvement.

Fixes #3625
2016-10-14 08:44:33 +11:00
James Ross-Gowan 6a8d1cdd49 terminal-win: clean up console input
The original version of this code in getch2-win.c fetched 128 console
events at once. This was probably to maximize the chance of getting a
key event if there were other events in the buffer, because it returned
the value of the first key event it found and ignored all others. Since
that code was written, it has been modified to receive console input in
an event-based way using an input thread, so it is probably not
necessary to fetch so many events at once any more. Also, I'm not sure
what it would have done if there were more than 128 events in the
console input buffer. It's possible that fetching multiple events at a
time also had performance advantages, but I can't find any other
programs that do this. Even libuv just fetches one console event at a
time.

Change read_input() to fetch only one event at a time and to consume all
available events before returning to WaitForMultipleObjects. Also remove
some outdated comments and pass the console handle through to the input
thread instead of calling GetStdHandle multiple times (I think this is
theoretically more correct because it is possible for the handles
returned by GetStdHandle to be changed by other threads.)
2016-10-14 08:44:33 +11:00
wm4 b5357e8ba7 ao_alsa: try to fallback to "hdmi" before "iec958" for spdif
If the "default" device refuses to be opened as spdif device (i.e. it
errors due to the AES0 etc. parameters), we were falling back to the
iec958 device. This is needed on some systems for smooth operation with
PCM vs. spdif.

Now change it to try "hdmi" before "iec958", which supposedly helps in
other situations.

Better suggestions welcome. Apparently kodi does this too, although I
didn't check directly.
2016-10-07 17:21:08 +02:00
Ricardo Constantino 65c75112a7 osc: move tooltip to inside seekbar for top/bottombar
Tooltip border is user-alterable
2016-10-07 00:31:49 +01:00
Ricardo Constantino e41dbc3019 osc: change seekbar background's alpha scaling
This avoids a full transparent seekbar with only boxalpha=115.

No change with default values.
2016-10-07 00:31:48 +01:00
Ricardo Constantino 7022a24542 osc: align text vertically in top/bottombar
Close #2093
2016-10-07 00:24:12 +01:00
rr- 403f489f6c vo_drm: change CLI options + refactors
- Change connector selection to accept human readable names (such as
  eDP-1, HDMI-A-2) rather than arbitrary numbers.
- Change GPU selection to accept GPU number rather than device paths.
- Merge connector and GPU selection into one --drm-connector.
- Add support for --drm-connector=help.
- Add support for --drm-* in EGL backend.
- Refactor KMS; reduce state sharing across drm_common.
2016-10-07 00:22:23 +02:00
Maurycy Skier e9c43258b8 ytdl_hook: add chapters by parsing video's description 2016-10-06 21:18:43 +01:00
Martin Herkt c3ae2ff107 man: fix PDF build
It really doesn’t want to pagebreak that box, so I removed a
useless example.
2016-10-06 21:49:14 +02:00
rr- ea1b183f4c vo_drm: fix segfault when using invalid card 2016-10-06 20:09:37 +02:00
Akemi e543853a7f cocoa: add glFlush() to cocoa backend
The glFlush() call was made optional recently
since it's not needed in most cases. On OSX though
this is needed since we removed kCGLPFADoubleBuffer
from the context creation, so the glFlush() call
was added to the cocoa backend only.
The CGLFlushDrawable() call can be safely removed
since it only does something when a double
buffered context is used. Also fixes a small typo.
Fixes #3627.
2016-10-06 19:50:25 +02:00
wm4 9340f19ba2 TOOLS/stats-conv.py: use different colors for symbols too
Also, not setting pen=None seems to draw horizontal lines for the dots,
which is fine too.
2016-10-06 19:42:18 +02:00
wm4 53798b6465 vo_opengl: apply --opengl-early-flush in dumb mode too
In "dumb mode" (where most features are disabled and which only performs
some basic rendering) we explicitly copy a set of whitelisted options,
and leave all the other options at their default values. Add the new
--opengl-early-flush option to this whitelist. Also remove an option
field accidentally added in the commit adding --opengl-early-flush.
2016-10-05 20:35:00 +02:00
wm4 d7e587acc9 options: handle --audio-device changes like the other options
Don't require special property code for handling updates, and simply use
the UPDATE_AUDIO flag instead. Also make runtime changes to
--audio-client-name take effect.
2016-10-05 16:45:04 +02:00
wm4 6fb12a5fda audio: move some fallback handling to common AO reload function
Now a reload requested by an AO behaves in exactly the same way as
changing an AO-related options (like --audio-channels or
--audio-exclusive). This is good for testing and uniform behavior. (You
could go as far as saying it's a necessity, because the spotty and
obscure AO reload behavior is hard to reproduce and thus hard to test at
all.)
2016-10-05 16:42:43 +02:00
wm4 3825dc63b2 command: flush and uninitialize audio output first on option changes
This affects changing audio configuration options. Explicitly flush and
uninitialize the audio output first before doing the rest. This should
ensure all state attached to the audio output is discarded and not used
during the reconfiguration.

Also add a comment to the reinit_audio_filters() call. It doesn't
necessarily restore the audio chain fully, but makes sure a seek is
issued if the amnount of buffered audio discarded was huge enough to
cause "problems".
2016-10-05 16:06:37 +02:00
wm4 e6291697e3 vo_opengl_cb: don't wait for redrawn frames
This also removes some extra waiting if no video is active, at least in
theory.

Also clarify the vo_frame flag comments for redraw/repeat.
2016-10-05 12:34:47 +02:00
wm4 6789f9b094 vo_opengl: disable glFlush() by default, and add an option to enable it
It seems this can cause issues with certain platforms, so better to
disable it by default. The original reason for this isn't overly
justified, and display-sync mode should get rid of the need for it
anyway.

The new option is meant for testing, and will probably be removed if
nobody comes up and reports that enabling the option actually improves
anything.
2016-10-05 12:21:34 +02:00
Kevin Mitchell 387f501278 audio: make setting audio-exclusive update the audio chain
This is required since exclusive mode requires entirely different
initializaiton.
2016-10-04 12:48:26 -07:00
wm4 39f515cb6a audio/out: prevent underruns with spdif under certain conditions
The player tries to avoid splitting frames with spdif (sample alignment
stuff). This can in certain corner cases with certain drivers lead to
the situation that ao_get_space() returns a number higher than 0 and
lower than the audio frame size. The playloop will round this down to 0
bytes and do nothing, leading to a missed wakeup. This can lead to
underruns or playback completely getting stuck.

It can be reproduced by playing AC3 passthrough with no video and:

    --ao=null --ao-null-buffer=0.256 --ao-null-outburst=6100

This commit attempts to fix it by allowing the playloop to write some
additional data (to get a complete frame), that will be buffered within
the AO ringbuffer even if the audio device doesn't want it.
2016-10-04 19:31:17 +02:00
wm4 13dcf82a96 manpage: fix closing quote 2016-10-04 16:52:36 +02:00
wm4 202f14aa29 vo_opengl: hwdec_rpi: fix NULL pointer deref in certain cases
If a client API user provides the MPGetNativeDisplay callback, but
returns NULL for "MPV_RPI_WINDOW", this would crash.
2016-10-04 16:36:20 +02:00
wm4 75cab315ea command: include deprecated/aliased options in property bridge
If we really want client API users to use mpv_set_property() instead of
mpv_set_option(), then compatibility handling of deprecated options
should be included. Otherwise, there's the danger that client API users
either break too early (and without a warning), or mpv_set_option() will
continue to have a reason to exist.
2016-10-04 13:23:11 +02:00
rr- ba3f6f3779 vo_drm: fix tiny memory leak 2016-10-04 13:23:11 +02:00
rr- 1648ff8a0f vo_drm: refactor getting display fps
Reduces code duplication between OpenGL backend and DRM VO.

(The control() for OpenGL backend isn't sufficiently similar to the
VO's control() to consider merging it as a whole - I extracted only the
FPS code.)
2016-10-04 13:23:11 +02:00
wm4 abbc8fc84a player: fix previous commit
...
2016-10-03 17:16:02 +02:00
Dan Oscarsson 7debdde9b9 options: rename subtitle options
Rename the text subtitle options from --sub-text- to --sub-
and --ass- options to --sub-ass-.
The intention is to common sub options to prefixed --sub-
and special ASS option be seen as a special version of sub options.
The OSD options that work like the --sub- options are still named
--osd-.
Man page updated including a short note about renamed --sub-text-*
and --ass-* options to --sub-* and --sub-ass-*.
2016-10-03 16:57:04 +02:00
wm4 81d125efd8 DOCS/interface-changes.rst: mention seek command change
This is potentially incompatible if a program used negative timestamps
to deal with timestamp resets, which would potentially lead to mpv
producing and using negative timestamps.
2016-10-03 15:49:53 +02:00
Philip Sequeira ff531b71e3 command: allow absolute seeks relative to end of stream
"seek -10 absolute" will seek to 10 seconds before the end. This more or less
matches the --start option and negative seeks were otherwise useless (they just
clipped to 0).
2016-10-02 18:01:52 +02:00
wm4 3a5cbf3907 audio: fix late audio start
Regression since commit bbcd0b6a. This code is just cursed, because it's
a fragile state machine with no proper tests, and which could be done in
a much simpler way. Without doubt this change will cause a regression in
some ridiculous corner case as well.

Fixes #3610 (the cause of it, not the behavior it resulted in).
2016-10-02 13:47:25 +02:00
wm4 6f4d918cb7 audio: dump timestamp difference
Can help to analyze timestamp jitter or seeing completely bogus
timestamps.
2016-10-02 12:55:22 +02:00
Bernhard Frauendienst 8d29d5b5d7 vaapi: support drm devices when running in vaapi-copy mode
When the vaapi decoder is used in copy mode, it creates a dummy
display to render to. In theory, this should support hardware
decoding on on a separate GPU that is not actually connected to
any output (like an iGPU which supports more formats than the
external GPU to which the monitor is connected).

However, before this change, only X11 displays were supported as
dummy displays. This caused some graphics drivers (namely
intel-driver) to core dump when they were not actually used as X11
module.
This change introduces support for drm libav displays, which
allows vaapi-copy to run on such cards which are not actually
rendering the X11 output.
2016-10-02 12:38:33 +02:00
wm4 39fc5e1deb player: make --stop-screensaver runtime-changeable
Move the screensaver enable/disable determination to a central place,
and call it if the stop-screensaver property is changed.

Also, do not stop the screensaver when in idle mode (i.e. no file is
loaded).

Fixes #3615.
2016-10-02 12:33:34 +02:00
wm4 e3a57272a7 stream_libarchive: add some more points at which reading can be stopped 2016-10-01 18:19:57 +02:00
wm4 486b3ce6f8 vo_opengl: minor simplification
The extra gl_transform_trans() has no apparent use.
2016-10-01 16:12:03 +02:00
wm4 82231fd74d vo_opengl: attempt to fix chroma offset under rotation and flipping
Other than being overly convoluted, this seems to make sense to me.
Except that to get the "rot" transform I have to set flip=true, which
makes no sense at all to me.
2016-10-01 16:07:51 +02:00
wm4 052584c9e2 vo_opengl: add debugging options for testing with padded textures 2016-10-01 12:09:18 +02:00
wm4 52fea2f909 vo_opengl: partially fix dumb-mode cropping with rotation
Combining rotation and cropping didn't work. It was just completely
broken.

I'm still not sure if this is correct. Chroma positioning seems to be
broken on rotation. There might also be a problem with non-mod-2 frame
sizes. Still, strictly an improvement for both rotated and non-rotated
rendering modes.

Also, this could probably be written in a more elegant way.
2016-09-30 22:19:01 +02:00
wm4 026cccaddf csputils: add note that mp_invert_cmat() is LGPL too
Commit aa1047a3 originally added this as:

+    // this is from the DarkPlaces engine, reduces to 3x3. Original code
+    // released under GPL2 or any later version.

According to Rudolf Polzer, the original author (a certain LH) was
actually asked whether it would be ok to put this code under LGPL, and
the author gave his agreement. This code is not from id Software either
(on which large parts of DarkPlaces is based on), which is the main
reason why DarkPlaces is under GPL.

So this note is just confusing, and always has been LGPL. Fix it.
2016-09-30 17:08:24 +02:00
wm4 ea50f6fdef msg: flush after every message for --log-file
We'd like to get log messages on the output as soon as possible in the
output. I also feel like using fflush() is nicer than using setvbuf().
Who knows how the latter behaves on win32.
2016-09-30 14:55:59 +02:00
wm4 33c24b07e4 vo_opengl: vaegl: log more debugging infos 2016-09-30 14:36:42 +02:00
wm4 5f547e57e3 vo_opengl: rpi: remove dumb comment
It's not even true anymore.
2016-09-30 14:28:55 +02:00
wm4 51f10c512e vo_opengl: rpi: fix glaring memory leak
This was in previously inactive code (uploading yuv420p), so it did not
matter.
2016-09-30 13:53:12 +02:00
wm4 ab07caf39d vo_opengl: rpi: use overlay for yuv420p too
The video code can deal fine with feeding software image formats to
hwdec interop drivers. In RPI's case, this is preferable for
performance, working around OpenGL bugs (see RPI firmware issue #666),
and because OpenGL rendering doesn't bring too many advantages due to
RPI supporting GLES 2.0 only.

Maybe a way to force the normal video path is needed later. But
currently, this can be tested by just not loading the hwdec interop
driver.

If you run command-line mpv and set --hwdec to something that does
not load the RPI interop layer, you'll even have to use --hwdec-preload
manually to get it enabled.
2016-09-30 13:49:49 +02:00
wm4 2aba6972cf vo_opengl: allow hwdec interops to support multiple image formats 2016-09-30 13:46:27 +02:00
wm4 2f1af04745 vo_opengl: egl: print EGL errors only if not probing
Avoids printing an error when trying to create a GLES 3.x context on a
device which can do GLES 2.0 only.
2016-09-30 13:06:31 +02:00
wm4 d3111ee777 vo_opengl: rpi: raise the video layer
Was intended to put the GL layer above the standard console. (But
actually that was done already, and the oddness I'm seeing seems to
be an unrelated bug.)
2016-09-30 13:05:58 +02:00
wm4 1d385b0dae vd_lavc: log if hw decoding selects a different underlying decoder
Less confusing to see what's going on. I think there were more than one
users who got tricked by this, including myself.
2016-09-30 13:05:39 +02:00
wm4 7e6456f43a rpi: add --hwdec=rpi-copy
This means it can be used with normal video filters.

Might help out with #3604.
2016-09-30 13:05:30 +02:00
wm4 b6920372c2 ipc: log when listening to IPC socket
Fixes #3598.
2016-09-29 16:47:19 +02:00
wm4 86ab4b8a9f path: default ~~ paths to home directory
The code for expanding the ~~ prefix used mp_find_config_file(), which
strictly looks for _existing_ files in any config path (e.g. not just
the user-local one, but also system-wide config). If no such file
exists, it simply returns NULL, which makes the code below just return
the literal, unexpanded path.

Change this so that it'll resolve the path to the user-local config
directory instead.

Requested in #3591.
2016-09-29 16:44:01 +02:00
wm4 b81ae52f50 player: enable reading from stdin after loading input.conf
Someone requested this.
2016-09-29 16:26:54 +02:00
wm4 c245d04c37 mp_image: fix clearing to black with p010 format
Using vf_expand (which uses mp_image_clear()) with p010 cleared chroma
to green instead.
2016-09-29 16:12:58 +02:00
James Ross-Gowan f549cec0ac w32_common: implement VOCTRL_GET_DISPLAY_NAMES
This should make display-names usable on Windows. It returns a list of
GDI monitor names like "\\.\DISPLAY1". Since it may be useful to get the
monitor that Windows considers associated with the window (with
MonitorFromWindow,) this will always be returned as the first argument.
This monitor is the one used for display-fps and icc-profile-auto.
2016-09-29 23:49:36 +10:00
Ricardo Constantino 6487ba4864 ytdl_hook: Set aspect ratio for anamorphic video 2016-09-28 21:16:40 +02:00
Philip Langdale 1557ca6712 cuda: initialize hwframes format
In retrospect, this seems obvious, but ffmpeg didn't complain until
a recent update.
2016-09-28 21:10:15 +02:00
wm4 b344da22ae client API: "priority" option is now runtime settable
So it doesn't have to be in the list of options that can be set before
mpv_initialize() only.
2016-09-28 15:26:24 +02:00
wm4 ef2bbd5a7a msg: make --log-file and --dump-stats accept config path expansion
Seems like a valid use-case. Not sure if I like it calling back into the
config code. Care has to be taken for not letting the config path
resolving code dead-lock (which is why locking details in the msg.c code
are changed).

Fixes #3591.
2016-09-28 15:04:38 +02:00
wm4 73a5bde518 img_format: remove some unneeded format definitions
They're still supported, just that they have no IMGFMT_ alias.
2016-09-28 14:21:32 +02:00
James Ross-Gowan b712095d89 win32: make --priority runtime-settable
I'm not sure if this option affects anything or if it's a placebo,
especially since the VO thread is now registered with MMCSS. Still, I
think --priority=high may have helped back when I used mplayer2 on a
netbook. It's also possible that encoding-mode users would want to set
--priority=idle.

Anyway, it was one of the last M_OPT_FIXED options, so fix that.
2016-09-28 21:47:30 +10:00
James Ross-Gowan 3751065f97 win32: build with -DINITGUID
We always want to use __declspec(selectany) to declare GUIDs, but
manually including <initguid.h> in every file that used GUIDs was
error-prone. Since all <initguid.h> does is define INITGUID and include
<guiddef.h>, we can remove all references to <initguid.h> and just
compile with -DINITGUID to get the same effect.

Also, this partially reverts 622bcb0 by re-adding libuuid.a to the
build, since apparently some GUIDs (such as GUID_NULL) are not declared
in the source file, even when INITGUID is set.
2016-09-28 21:38:52 +10:00
wm4 c239b7de7e vo_opengl: deprecate 'drm-egl' backend and introduce 'drm' instead
Just a name change. Requested.
2016-09-27 16:29:22 +02:00
wm4 45c97aea78 stream_lavf: check seekable flag correctly
AVIOContext.seekable is actually a bitfield. Currently, it has only
AVIO_SEEKABLE_NORMAL defined, but it might be extended with a hint for
non-byte seekability. Thus we should check it correctly.
2016-09-27 15:51:34 +02:00
wm4 b6cbf74518 command: fix inverted condition in sub-reload command
Fixes #3586 (probably). Untested.
2016-09-26 20:12:59 +02:00
rr- 0fe3e9ca5e vo_drm: provide display fps 2016-09-26 19:26:31 +02:00
Akemi 9f30cd8292 cocoa: fix fullscreen regression on 10.11 and newer
Fixes #3364.
2016-09-26 19:25:50 +02:00
Ricardo Constantino f0ab9f05f1 player: allow opts in pseudo-gui set by the user to override user's default
This should still allow user-set default options to override built-in
pseudo-gui while respecting user-set pseudo-gui options.

Pros:
- user option in default profile overrides built-in pseudo-gui's options
  Ex: screenshot-directory overrides built-in pseudo-gui's
- user can "fix" pseudo-gui if some option like "force-window=no" is set
  in default by setting "force-window=yes" in [pseudo-gui]
- `mpv --profile=pseudo-gui` will work as before

Cons:
- --show-profile=pseudo-gui won't display the built-in's options

Original idea from wm4.

Documentation edits mostly by wm4.

Signed-off-by: wm4 <wm4@nowhere>
2016-09-26 19:25:14 +02:00
wm4 dd339b200b video: trust demuxer framerate on invalid timestamps
If the PTS goes backwards (whether it's a timestamp reset or some other
problem) would just use 0 as frame duration. (At least until the logic
for detecting divergence with the timestamps gets active.)

Trust the demuxer framerate in these cases instead, if it's available. I
think this improves behavior slightly with some broken files.
2016-09-26 17:55:00 +02:00
wm4 e6dedbcc23 qthelper: introduce new convenience functions
(Why the heck is the C++ helper not in a separate repository?)
2016-09-26 16:49:35 +02:00
wm4 a314b1013f scripting: don't attempt to load builtin scripts twice
During init it will first call mp_load_builtin_scripts(), and then again
via mp_load_scripts().

This was harmless (a second attempt won't load it again if the first one
was successful), but it's unnecessary, and also looks confusing if the
scripts failed to load the first time.
2016-09-26 16:49:35 +02:00
wm4 0f110ad0e2 stream_lavf: fix determining seekability
demux_lavf.c forces seek to being determined as supported if
STREAM_CTRL_HAS_AVSEEK is returned as success. But it always succeeds
with current FFmpeg versions. (Seems like Libav commit cae448cf broke
this in early 2016.)

Now we can't determine via private API whether the underlying protocol
supports read_seek anymore. The affected protocols (mostly rtmp) also
set seekable=0, meaning they signal they're not seekable, even though
read_seek would work. (My guess is that this can't be fixed because even
though seekable is in theory a combination of elaborate flags [of which
only 1 is defined, AVIO_SEEKABLE_NORMAL], a seekable!=0 always means
it's byte-seekable in some way.)

So the FFmpeg API is being garbage _again_, and all what we can do is
determining this via protocol name and a whitelist.

Should fix the behavior reported in #1701.
2016-09-26 16:49:35 +02:00
Kevin Mitchell 41002c46f5 DOCS/compile-windows.md: update msys2 instructions again
they keep changing things. . .
2016-09-25 17:29:45 -07:00
Ricardo Constantino 29d74ca2f5 osc: Fix scaling issues when toggling fullscreen
Fixes #3429
2016-09-25 16:10:48 +02:00
wm4 077dd27df2 sd_ass: fix top alignment of secondary subtitles
Secondary subtitle streams (to be shown on the top of the screen along
main subtitle stream) were shown with normal alignment. This is because
we tell libass to override the alignment style (a relatively recent
change, see commit 2f1eb49e). This would behave differently with old
libass versions too.

To escape the mess, just set the alignment explicitly with an override
tag instead of modifying the style.
2016-09-25 01:03:59 +02:00
wm4 cad6fb038b lua: complain loudly if Lua state creation fails
This should normally happen only if memory allocation for the state
happens, which should be extremely rare. But with Luajit on OSX, it can
happen if the magic compiler flags required by Luajit were not passed to
mpv compilation. Print an error to reduce confusion.
2016-09-25 01:00:20 +02:00
wm4 733218b233 options: do not mark --profile/--include as M_OPT_FIXED
The intention of M_OPT_FIXED is to make options not runtime-changeable,
so trying to set them at runtime will always error. This is not wanted
for --profile and --include, for which there is no reason to block them
at runtime.

Fixes #3581.
2016-09-24 20:41:07 +02:00
wm4 88f10ec84f player: fix instant subtitle refresh on track switches
When switching a subtitle track, the subtitle wasn't necessarily
updated, especially when playback was paused.

Some awfully subtle and complex interactions here.

First off (and not so subtle), the subtitle decoder will read packets
only on explicit update_subtitles() calls, which, if video is active, is
called only when a new video frame is shown. (A simply video frame
redraw doesn't trigger this.) So call it explicitly. But only if
playback is "initialized", i.e. not when it does initial track selection
and decoder init, during which no packets should be read.

The second issue is that the demuxer thread simply will not read new
packets just because a track was switched, especially if playback is
paused. That's fine, but if a refresh seek is to be done, it really
should do this. So if there's either 1. a refresh seek requested, or 2.
a refresh seek ongoing, then read more packets.

Note that it's entirely possible that we overflow the packet queue with
this in unpredicated weird corner cases, but the queue limit will still
be enforced, so this shouldn't make the situation worse.
2016-09-24 19:57:19 +02:00
wm4 2361ec35aa lua: fix array detection
This was dumb and could return something like "{name=123}" as an array.

Also, fix the error message if a key is not a string. lua_typename()
takes a type directly, not a stack item.
2016-09-24 17:52:36 +02:00
wm4 68d2903cb1 command: some minor corrections to previous commit
The last commit was fine - just making some enhancements.

Rename the function to parse_node_chapters(), since it really has not
much to do with Lua.

Don't use len<0 as check whether it makes sense to set chapters, and
instead check for mpctx->demuxer (that includes the possibility to set
chapters e.g. within a preload hook, but after chapters are initialized
from the demuxer).

Return M_PROPERTY_ERROR instead of M_PROPERTY_OK if the mpv_node has the
wrong type.

It's ok if a chapter has no title, so change the checks accordingly.

Remove a Yoda condition.

Notify that chapter metadata might have changed with mp_notify() (the
chapter list itself is already taken care by generic code).

Fix leaking the metadata allocations of the new chapter list.
2016-09-24 17:51:23 +02:00
Maurycy Skier e2e9a7faa8 command: make it possible to set chapters via lua plugins 2016-09-24 17:17:49 +02:00
Philip Langdale 343da8d73d vo_opengl: hwdec_cuda: get the cuda device from the GL context
Obviously, in the vast majority of cases, there's only one device
in the system, but doing this means we're more likely to get a
usable device in the multi-device case.

cuda would support decoding on one device and displaying on another
but the peer memory handling is not transparent and I have no way
to test it so I can't really write it.
2016-09-24 17:11:09 +02:00
Philip Langdale 441febfcba vo_opengl: hwdec_cuda: directly map GL textures and skip using PBOs
The documentation around this stuff is poor, but I found an nvidia
sample that demonstrates how to use the interop API most efficiently.

(https://github.com/nvpro-samples/gl_cuda_interop_pingpong_st)

Key lessons are:
1) you can register the texture itself and have cuda write to it,
   thereby skipping an additional copy through the PBO.
2) You don't have to be mapped when you do the copy - once you get a
   mapped pointer, it remains valid. Magic!

This lets us throw out the PBOs as well as much of the explicit
alignment and stride handling.

CPU usage is slightly (~3%) lower for 4K content in one test case,
so it makes a detectable difference, and presumably saves memory.
2016-09-24 17:11:06 +02:00
Philip Langdale cb46f73cbb manpage: hwdec_cuda: update docs to say 10bit hevc is supported
Now that ffmpeg bundles working headers, this no longer relies
on a custom ffmpeg build with a hacked up header file.
2016-09-24 17:11:04 +02:00
wm4 1500c84226 player: fix intended pseudo-gui behavior
It's still supposed to be possible to customize the pseudo-gui section.
2016-09-23 22:35:54 +02:00
wm4 9eef41dec1 player: do not let pseudo-gui override user config settings
Seems like this confused users quite often.

Instead of --profile=pseudo-gui, --player-operation-mode=pseudo-gui now
has to be used to invoke pseudo GUI mode. The old way still works, and
still behaves in the old way.
2016-09-23 21:24:50 +02:00
wm4 f0fd663320 m_config, command: remove some minor code duplication
I would have been fine with this, but now I want to add another flag,
and the duplication would become more messy than having a strange
function for deduplication.
2016-09-23 21:04:20 +02:00
wm4 b9153ee177 TOOLS/lua/observe-all: explicitly observe all options 2016-09-23 20:49:23 +02:00
wm4 f4db6b8479 command: make most options observable
The property observation mechanism turns properties into integer IDs for
fast comparison. This means if two properties get the same ID, they will
receive the same notifications. Use this to make properties under
options/ receive notifications. The option-property bridge marks
top-level properties with the same name as the options.

This still might not work in cases the C code sets values on options
structs directly.
2016-09-23 20:49:08 +02:00
wm4 5f2822d502 vo_opengl: hwdec_rpi: remove copy&paste error 2016-09-23 19:45:16 +02:00
wm4 9664bc23d5 vo: log framedrops
Seems useful. (This was possibly added ages ago and then removed.)
2016-09-23 19:44:46 +02:00
wm4 6f6c4a57ec command: fix potential UB
Pointed out by quilloss on github.
2016-09-23 15:21:59 +02:00
wm4 caa14e3d45 x11: fix external fullscreen update
On x11, you can change the fullscreen via the window manager and without
mpv's involvement. In these cases, the internal fullscreen flag has to
be updated.

The hack used for this didn't really work properly. Change it
accordingly. The important thing is that the shadow copy of the option
is updated. This is still not really ideal.

Fixes #3570.
2016-09-23 12:09:48 +02:00
Niklas Haas 3a43682355 aspect: use nominal width instead of actual width for video-unscaled
The documentation claims that --video-unscaled will still perform
anamorphic adjustments, and it rightfully should. The current reality is
that it does not, because the video-unscaled size was based on the wrong
set of variables. (encoded width/height instead of nominal display
width/height)
2016-09-22 21:24:56 +02:00
wm4 075edc6fee player: make audio-channels etc. runtime settable
If one of the audio output format options is set, brually reinit the
audio chain.

Since the audio-channels property is still mapped to the deprecated
read-only property, "options/audio-channels" currently has to be used,
e.g. "cycle-values options/audio-channels 2 7.1".
2016-09-22 20:57:06 +02:00
wm4 2ac74977c5 command: add a load-script command
The intention is to give libmpv users as much flexibility to load
scripts as using mpv from CLI, but without restricting libmpv users from
having to decide everything on creation time, or having to go through
hacks like recreating the libmpv context to update state.
2016-09-22 20:57:06 +02:00
wm4 01e95468f9 player: remove some explicit options accesses when saving resume file
Basically, make use of all the new code.

Unfortunately, the new code and it's "compromise semantics" with the old
behavior before the options/properties merge bites back: this
vid/aid/sid, deinterlace, and video-aspect properties have neutral
default settings (such as "auto"), but return the current value during
playback, so we would unnecessarily force this value when playback is
resumed. So leave those as they are.

Also, the colormatrix options were removed a long time ago.
2016-09-22 20:57:06 +02:00
wm4 efbfc00741 command: fix missing update notifications in some cases 2016-09-22 20:57:06 +02:00
wm4 6fe83fdc33 player: some M_SETOPT_RUNTIME cleanups
Add this flag where needed. You shouldn't be able to set e.g. config-dir
in these situations.

Remove the mpctx->initialized check from the property/option bridge,
since it's in use strictly only after initialization. Likewise, the
apply-profile command doesn't need to check this.
2016-09-22 20:57:05 +02:00
Ricardo Constantino 6ba2bbd090 ytdl_hook: temporarily force disable dash segments formats 2016-09-22 20:34:42 +02:00
wm4 9179e8ed21 vo: add a unique frame_id to vo_frame
We think that this allows simpler logic than using the redraw and repeat
fields. Not used yet.
2016-09-22 20:16:44 +02:00
wm4 c296b6204f vo_opengl: apply 90° rotation to chroma texture size
When we rotate the inmage by 90° or 270°, chroma width and height need
to be swapped.

Fixes #3568.

But is the chroma sub location correct? Who the hell knows...
2016-09-22 15:16:53 +02:00
Philip Langdale e300bfcf3a hwdec/cuda: Document how to activate cuda deinterlacing
The latest changes to the decoder in ffmpeg enable frame doubled
deinterlacing so that it's actually useful. Let's document how to
use it.
2016-09-22 13:46:27 +02:00
Akemi 9df797575f cocoa: fix macOS 10.12 deprecation warnings 2016-09-22 13:46:27 +02:00
David Logie 78b3852f7e player: add --watch-later-directory option
This option allows the user to set the directory where "watch later"
files are stored.

Signed-off-by: wm4 <wm4@nowhere>
2016-09-22 13:46:19 +02:00
wm4 7783f0b7d7 client API: more or less deprecate mpv_set_option()
With the merging of options and properties, the mpv_set_option()
function is close to being useless, and mpv_set_property() can be used
for everything instead. There are certain conflicts remaining, which are
explained in depth in the docs. For now, none of this should affect
existing code using the client API.

Make mpv_set_property() redirect to mpv_set_option() before
initialization.

Remove some options marked as M_OPT_FIXED. The "pause" and "speed"
options cannot be written anymore without the playloop being notified by
it, so the M_OPT_FIXED does nothing. For "vo-mmcss-profile", the problem
was lack of synchronization, which has been added. I'm not sure what the
problem was with "frames" - I think it was only marked as M_OPT_FIXED
because changing it during playback will have no effect. Except for
pause/speed, these changes are needed to make them writable as
properties after mpv_initialize().

Also replace all remaining uses of CONF_GLOBAL with M_OPT_FIXED.
2016-09-21 17:35:00 +02:00
wm4 75d12c174f options: make input options generally runtime-settable 2016-09-21 17:35:00 +02:00
wm4 14c232bdbf client API: fix init/destruction race conditions
mp_new_client() blatantly accessed some mutex-protected state outside of
the mutex.

The destruction code is in theory OK, but with changes in the following
commits it'll be a bit hard to guarantee that it stays this way. Add a
simple flag that makes adding new clients impossible, so that having no
clients after shutdown_clients() remains guaranteed.
2016-09-21 17:34:55 +02:00
wm4 47f3cc7e6b lua: add API for registering idle handlers
This is only a functionality the Lua event dispatcher provides, rather
than the libmpv client API.
2016-09-21 15:47:52 +02:00
wm4 b521f15ae9 lua: run timers only after draining the event queue
Instead of rechecking the timers every time after an event is read, do
it only once the event queue is empty. This is probably slightly more
efficient, and facilitates the next commit.
2016-09-21 15:47:51 +02:00
wm4 33598182a0 manpage: lua: mention recent deprecations
These are listed in interface-changes.rst, but the documentation in the
manpage wasn't updated.
2016-09-21 12:45:27 +02:00
rr- f66f0b34c8 lua: expose subprocess_detached 2016-09-21 12:43:21 +02:00
Josh de Kock af6126adbe ao_openal: enable building on OSX
Signed-off-by: Josh de Kock <josh@itanimul.li>
2016-09-21 12:43:14 +02:00
wm4 d080851a30 command: make bitrate properties observable 2016-09-21 11:49:00 +02:00
wm4 41d9f2f058 client API: revert unintended mpv_wait_event() behavior change
Commit bf385e11 accidentally added some testing changes that were not
intended to be committed.
2016-09-21 11:47:54 +02:00
wm4 89674854ce command: add a video-dec-params property
This is the actual decoder output, with no overrides applied. (Maybe
video-params shouldn't contain the overrides in the first place, but
damage done.)
2016-09-20 15:44:26 +02:00
wm4 23639e5b0e video: handle override video parameters in a better place
This really shouldn't be in vd_lavc.c - move it to dec_video.c, where it
also applies aspect overrides. This makes all overrides in one place.
The previous commit contains some required changes for resetting the
image parameters change detection (i.e. it's not done only on video
aspect override changes).
2016-09-20 15:44:23 +02:00
wm4 e13eb3fede command: change update handling of some video-related properties
Use the new mechanism, instead of wrapped properties. As usual, extend
the update handling to some options that were forgotten/neglected
before. Rename video_reset_aspect() to video_reset_params() to make it
more "general" (and we can amazingly include write access to
video-aspect as well in this).
2016-09-20 15:44:16 +02:00
wm4 bf385e1140 player: kill associated OSD and key bindings when removing a script
The former was done already for Lua scripts, but move it to the generic
code.
2016-09-20 15:44:11 +02:00
wm4 fe872f5688 osd: fix OSD redrawing after removing external overlays 2016-09-20 15:44:06 +02:00
Kranky K. Krackpot 6b5e5b6843 man/options.rst: fix typo and layout
Signed-off-by: wm4 <wm4@nowhere>
2016-09-20 15:20:28 +02:00
Kevin Mitchell 5fca497698 audio: fix segfault when yanking USB DAC
The ao_c pointer was stale after the mpctx entry was freed / NULLed.
This prevented the correct early exit from fill_audio_out_buffers.
2016-09-20 14:46:36 +02:00
wm4 995962291a options: fix window-scale property
A recent change merged the window-scaler option and property, but forgot
that the option is float for some reason, while the property uses
double. This led to undefined behavior. Fix it by changing the option
to double too.
2016-09-20 01:25:50 +02:00
wm4 b6ba87af4b m_option: resort M_OPT_ flag values
Remove the gaps that have been added over time.
2016-09-20 01:25:10 +02:00
wm4 fb67db8b72 player: make --osc/--ytdl settable during playback
Setting the osc or ytdl properties will now load/unload the associated
scripts. (For ytdl this does not mean the currently played URL will be
reloaded.)

Also add a changelog entry for this, which also covers the preceding
work for --terminal.
2016-09-20 01:24:27 +02:00
wm4 bf5c97a6c3 options, command: simplify some option updates
Remove wrapper properties for OSD and video position updates, use the
new mechanism for them. We can mark the options directly. Update
behavior will work for more options (since I've casually marked more
affected options than the old less direct mechanism covered).
2016-09-19 20:16:44 +02:00
wm4 df85c76b7f client API: revert some relaxations about calling mpv_initialize()
My original idea was making mpv_initialize() a no-op, but it seems this
can't happen after all. The problem is especially with subtle
interactions in option parsing (basically all pre-parse options).

Instead, I might go into the opposite direction, and add a new API
function that takes over the role of mpv_create+mpv_initialize, and
which will take a list of options. This list will be for the purpose
of setting options that can be set only at initialization time (such
as config-dir). This would also make it more uniform with the command-
line player initialization.

Maybe.

In any case, for now revert parts of commit 453fea87 to remove the
initialization-related freedoms it added. Fortunately, this wasn't
released yet, so we remove it from the API as if it never happened.

(The rest of that commit is still fine, just not the additional
freedom.)
2016-09-19 20:02:53 +02:00
wm4 44a7cb7f0e player: minor changes in init code
Move the MPV_LEAK_REPORT env query to mp_create(), where it will also be
used by the client API (it might be helpful, so why not). The same
applies to MPV_VERBOSE.

The prepare_playlist() call doesn't need to be in mp_initialize() and
can just be in mp_play_files() to reduce the size of mp_initialize().

Also, remove wakeup_playloop(), which is 100% redundant with
mp_wakeup_core_cb().
2016-09-19 19:57:31 +02:00
wm4 ce65ea3345 player: make --log-file and --dump-stats freely settable at runtime
Same deal as with the previous commit. We use the file paths to decide
when we should attempt to reopen them.
2016-09-19 19:56:40 +02:00
wm4 b62634c051 player: make --terminal freetly settable at runtime
So client API users don't have to care about whether to set this before
or after mpv_initialize().

We still don't enable terminal at any point before mpv_initialize(),
because reasons.

This also subtly changes some behavior how terminal options are applied
while parsing. This essentially reverts the behavior as it was reported
in issue #2588. Originally, I was hoping to get rid of the pre-parse
option pass, but it seems this is absolutely not possible due to the way
config and command line parsing are entangled. Command line options take
priority over configfile options, so they have to be applied later - but
we also want to apply logging and terminal options as specified on the
command-line, but _before_ parsing the config files. It has to be this
way to see config file error messages on the terminal, or to hide them
if --no-terminal is used. libmpv considerations also factor into this.
2016-09-19 19:54:54 +02:00
wm4 75fe626aa6 terminal-unix: don't send quit command on terminal_uninit()
Until now, the terminal thread always sent a quit command if the
terminal thread was torn down (whether it happened via terminal_uninit()
or a quit signal). This is not so good if we want to enable toggling
terminal use at runtime, since disabling the terminal would always make
the player quit. So we want terminal_uninit() not to send quit.

This can be easily fixed by using the "death byte" sent to the pipe used
for thread tear-down to indicate whether it was caused by a signal or
terminal_uninit().
2016-09-19 19:53:08 +02:00
wm4 fe7db61035 options: slightly better option update mechanism
Extend the flag-based notification mechanism that was used via
M_OPT_TERM. Make the vo_opengl update mechanism use this (which, btw.,
also fixes compilation with OpenGL renderers forcibly disabled).

While this adds a 3rd mechanism and just seems to further the chaos, I'd
rather have a very simple mechanism now, than actually furthering the
mess by mixing old and new update mechanisms. In particular, we'll be
able to remove quite some property implementations, and replace them
with much simpler update handling. The new update mechanism can also
more easily refactored once we have a final mechanism that handles
everything in an uniform way.
2016-09-19 19:51:26 +02:00
wm4 32f235bcef options: remove some M_OPT_FIXED flags
--quiet can be always set - the playloop checks it whenever rendering
the status line. Nothing special about it.

The ytdl- options are simply refetched by the Lua script every time a
stream is opened, so it makes sense to be able to change them at runtime
as well.

The VO options don't have a real reason to be marked with it anymore.
2016-09-19 19:50:41 +02:00
Hector Martin a802afb206 command: add audio-pts property to get the audio pts
For audio files, this is identical to time-pos (except read-only).
For audio-video files, this returns the audio position. Unlike
time-pos, this is not quantized to a video frame.
For video-only files, this property is unavailable.
2016-09-19 19:45:24 +02:00
Hector Martin 297f9f1bec af_pan: fix typo
This was in the parser code all along. As far as I can tell, *cp was
intended. There is no need to check cp for NULL (nor does it make any
sense to do so every time around the loop) for AF_CONTROL_COMMAND.

However, s->matrixstr can be NULL, so checking for that separately is in
order.
2016-09-19 19:01:52 +02:00
Hector Martin f504661852 af_rubberband: default to channels=together
For stereo and typical L/R-first channel arrangements, this avoids
undesirable phasing artifacts, especially obvious when speed is changed
and then reset. Without this, there is a very audible change in the
stereo field even when librubberband is no longer actually making any
speed changes.
2016-09-19 18:59:42 +02:00
Hector Martin 57eca14a45 af_rubberband: add af-command and option to change the pitch
This allows both fixed and dynamic control over the audio pitch using
librubberband, which was previously not exposed to the user.
2016-09-19 18:56:14 +02:00
Hector Martin ed8540c38e af_pan: add af-command support to change the matrix
This allows for seamless changes in the downmixing matrix without having
to reinitialize the filter chain.
2016-09-19 14:55:58 +02:00
Hector Martin 0525f5fa93 af_pan: coding style fixes 2016-09-19 14:55:55 +02:00
wm4 08432fcbd1 command: fix "cycle"/"add" not working on most properties
Oops, this is kind of important, isn't it?

Stopped working for properties which don't implement
M_PROPERTY_GET_CONSTRICTED_TYPE directly, as do_action() goes to the
property directly, while m_property_do() does a fallback.
2016-09-18 17:55:27 +02:00
wm4 2415b69572 player: more option/property consistency fixes
Some properties had a different type from their equivalent options (such
as mute, volume, deinterlace, edition). This wasn't really sane, as raw
option values should be always within their bounds. On the other hand,
these properties use a different type to reflect runtime limits (such as
range of available editions), or simply to improve the "UI" (you don't
want to cycle throuhg the completely useless "auto" value when cycling
the "mute" property).

Handle this by making them always return the option type, but also
allowing them to provide a "constricted" type, which is used for UI
purposes. All M_PROPERTY_GET_CONSTRICTED_TYPE changes are related to
this.

One consequence is that you can set the volume property to arbitrary
high values just like with the --volume option, but using the "add"
command it still restricts it to the --volume-max range.

Also deprecate --chapter, as it is grossly incompatible to the chapter
property. We pondered renaming it to --chapters, or introducing a more
powerful --range option, but concluded that --start --end is actually
enough.

These changes appear to take care of the last gross property/option
incompatibilities, although there might still be a few lurking.
2016-09-18 16:08:21 +02:00
wm4 3ecc6d0a79 command: fix window-scale option/property inconsistencies
For some odd reason, value ranges for the window-scale option and
property are different, and the property has a more narrow range. Change
it to the option range.

Also store the window-scale value into the option value when setting the
property, so it will be persistent if the window is closed and reopened.
2016-09-18 16:08:21 +02:00
wm4 9e972ed7d2 options: rename/deprecate --playlist-pos
Conflicts with the "playlist-pos" property. They're really a bit too
different, and since the --playlist-pos option is relatively new and
obscure, just rename it to get this out of the way.
2016-09-18 16:08:21 +02:00
wm4 62d4a3891a command: minor fixes to video-aspect property
Make the option type exactly the same as the underlying option's one. I
think this has no user-visible consequences, but makes more sense for
the option-property bridge.
2016-09-18 16:08:21 +02:00
wm4 79e20ff485 options: actually deprecate --mute=auto
Also, make it internally actually an alias to "no".
2016-09-18 16:08:21 +02:00
wm4 74c342c6d3 command: fix --quiet, --really-quiet options
These are not mapped as property, so the option-property bridge has to
skip them. Do this automatically if a property is not found. I know that
this affects --quiet and --really-quiet, but in theory there could be
more.
2016-09-18 16:08:21 +02:00
James Ross-Gowan f8659d0013 displayconfig: treat a refresh rate of 1 as invalid
Found in Windows 8.1/VirtualBox.
2016-09-18 22:15:25 +10:00
RiCON 554c3a1bda stream/stream_lavf: user-agent option is deprecated
There was both user-agent and user_agent options, the former is deprecated in FFmpeg/FFmpeg@27714b462 master.
Libav uses both forms.

This avoids constant `[ffmpeg] http: the user-agent option is deprecated, please use user_agent option` warnings using ytdl_hook.
2016-09-18 11:31:11 +02:00
wm4 cb604d5412 command: add an apply-profile command
This will actually update all associated options (which is trivial now
with the recent changes).
2016-09-17 21:01:59 +02:00
wm4 a3e8ff624c options: take care of propertly updating options on runtime changes
All option write accesses are now put through the property interface,
which means runtime option value verification and runtime updates are
applied. This is done even for command line arguments and config files.

This has many subtle and not-so-subtle consequences. The potential for
unintended and intended subtle or not-subtle behavior changes is very
large.

Architecturally, this is us literally jumping through hoops. It really
should work the other way around, with options being able to have
callbacks for value verification and applying runtime updates. But this
would require rewriting the entirety of command.c. This change is more
practical, and if anything will at least allow incremental changes.

Some options are too incompatible for this to work - these are excluded
with an explicit blacklist.

This change fixes many issues caused by the mismatch between properties
and options. For example, this fixes #3281.
2016-09-17 20:48:22 +02:00
wm4 2d34171bec options: fix pseudo-options like -v
Some pseudo-options do not have associated storage, which made
m_config_set_option_raw() return failure.

Regression due to commit d1d5e9dd.
2016-09-17 20:34:00 +02:00
wm4 ffc9aa8104 manpage: document some more property/options inconsistencies 2016-09-17 19:08:35 +02:00
wm4 b44d075164 command: make window-scale redirect to option if no window created
For consistency with other properties that mirror options.
2016-09-17 19:08:17 +02:00
RiCON b7d5cbd375 DOCS: vo/ao auto profiles are deprecated
Leftovers from removal of references to ao/vo auto profiles.
2016-09-17 18:31:10 +02:00
wm4 dc48893630 options: simplify M_OPT_EXIT
There were multiple values under M_OPT_EXIT (M_OPT_EXIT-n for n>=0).
Somehow M_OPT_EXIT-n either meant error code n (with n==0 no error?), or
the number of option valus consumed (0 or 1). The latter is MPlayer
legacy, which left it to the option type parsers to determine whether an
option took a value or not. All of this was changed in mpv, by requiring
the user to use explicit syntax ("--opt=val" instead of "-opt val").

In any case, the n value wasn't even used (anymore), so rip this all
out. Now M_OPT_EXIT-1 doesn't mean anything, and could be used by a new
error code.
2016-09-17 18:07:40 +02:00
wm4 d1d5e9dda4 m_config: make option setting always call m_config_set_option_raw()
This makes m_config_set_option_raw() the function that is always called
on the lowest level (as leaf function for all other functions).

To do this, m_config_parse_option() has to do something special to deal
with "impure" options like --vf-add, which work on the previous option
value, instead of fully replacing it. m_config_set_option_raw() itself
always completely replaced the previous value.
2016-09-17 17:47:22 +02:00
wm4 7fa26bfd9c options: kill M_OPT_GLOBAL flag
This meant "cannot be used as per-file option" (wrt. playlist items).
Doesn't make too much sense anymore, especially given how obscure
per-file options are.
2016-09-17 17:04:13 +02:00
wm4 4395a4f837 player: don't enter playloop for client API requests
This _actually_ does what commit 8716c2e8 promised, and gives a slight
performance improvement for client API users which make a lot of
requests (like reading properties).

The main issue was that mp_dispatch_lock() (which client.c uses to get
exclusive access to the core) still called the wakeup callback, which
made mp_dispatch_queue_process() exit. So the playloop got executed
again, and since it does a lot of stuff, performance could be reduced.
2016-09-16 20:24:52 +02:00
wm4 56616b0b01 osd: fix OSD getting stuck with --blend-subtitles=yes
If --blend-subtitles=yes is given, vo_opengl will call osd_draw()
multiple times, once for subtitles, and once for OSD. This meant that
the want_redraw flag was reset before the OSD was rendered, which in
turn meant that update_osd() was never called. It seems like removing
the per-OSD object want_redraw wasn't such a good idea. Fix it by
reintroducing such a flag for OSDTYPE_OSD only.

Also, the want_redraw flag is now unused, so kill it.

Another regression caused by commit 9c9cf125. Fixes #3535.
2016-09-16 17:17:32 +02:00
wm4 17e3e800e1 dispatch: fix a race condition triggering an assert()
If we were waiting, and then exiting due to timeout, we still have to
recheck the condition protected by the condition variable/mutex in order
to get back to a consistent state. In this case, the queue was locked
with mp_dispatch_lock(), and mp_dispatch_queue_process() got to return
without waiting for unlock.

Also caused commit 8716c2e8. Probably an argument for replacing the
dispatch queue by a simple mutex.
2016-09-16 16:11:33 +02:00
wm4 ccf3458f8a player: fix a missed wakeup
ytdl.lua stopped working after commit 8716c2e8, because finishing the
hook did not wakeup the playloop correctly.
2016-09-16 15:51:56 +02:00
wm4 c47ae06ed8 vo_opengl: don't pass negative height to overlay_adjust()
Negative height is used to signal a flipped framebuffer. There's
absolutely no reason to pass this down to overlay_adjust(), and only
requires implementers to deal with an additional special-case.
2016-09-16 14:50:05 +02:00
wm4 8716c2e88f player: use better way to wait for input and dispatching commands
Instead of using input_ctx for waiting, use the dispatch queue directly.
One big change is that the dispatch queue will just process commands
that come in (e.g. from client API) without returning. This should
reduce unnecessary playloop excutions (which is good since the playloop
got a bit fat from rechecking a lot of conditions every iteration).

Since this doesn't force a new playloop iteration on every access, this
has to be enforced manually in some cases.

Normal input (via terminal or VO window) still wakes up the playloop
every time, though that's not too important. It makes testing this
harder, though. If there are missing wakeup calls, it will be noticed
only when using the client API in some form.

At this point we could probably use a normal lock instead of the
dispatch queue stuff.
2016-09-16 14:49:23 +02:00
wm4 15baf2789c client API: declare mpv_suspend/mpv_resume deprecated
They're useless, and I have no idea what they're actually supposed to do
(wrt. pending input processing changes).

Also remove their implicit uses from the IPC handlers.
2016-09-16 14:39:47 +02:00
wm4 03fec24e19 player: litter code with explicit wakeup calls
This does 3 kinds of changes:
- change sleeptime=x to mp_set_timeout()
- change sleeptime=0 to mp_wakeup_core() calls (to be more explicit)
- change commands etc. to call mp_wakeup_core() if they do changes that
  require the playloop to be rerun

This is preparation for the following changes. The goal is to process
client API requests without having to rerun the playloop every time. As
of this commit, the changes should not change behavior. In particular,
the playloop is still implicitly woken up on every command.
2016-09-16 14:39:45 +02:00
wm4 b8ade7c99b player, ao, vo: don't call mp_input_wakeup() directly
Currently, calling mp_input_wakeup() will wake up the core thread (also
called the playloop). This seems odd, but currently the core indeed
calls mp_input_wait() when it has nothing more to do. It's done this way
because MPlayer used input_ctx as central "mainloop".

This is probably going to change. Remove direct calls to this function,
and replace it with mp_wakeup_core() calls. ao and vo are changed to use
opaque callbacks and not use input_ctx for this purpose. Other code
already uses opaque callbacks, or has legitimate reasons to use
input_ctx directly (such as sending actual user input).
2016-09-16 14:37:48 +02:00
wm4 f845f64c2a osd: fix subtitle/overlay update problems
This could in theory lead to missed updates if subtitles were switched
or external OSD overlays (via overlay-add) were updated. While the
change IDs of each of those were consistent, switching between two
separate OSD sources is not, and we have to explicitly trigger a change.

Regression since commit 9c9cf125. The new code is actually better,
because we do exactly what is needed, and don't just mess with the
update ID for libass-based OSD.
2016-09-16 14:26:30 +02:00
Philip Langdale b83bfea05d hwdec_cuda: Rename config variable to be more consistent
'cuda-gl' isn't right - you can turn this on without any GL and
get some non-zero benefit (with the cuda-copy hwaccel). So
'cuda-hwaccel' seems more consistent with everything else.
2016-09-16 14:26:30 +02:00
wm4 cf5c3fc31a vo_opengl: rpi: cosmetic change
I almost feel sorry wasting a commit on this.
2016-09-15 14:50:38 +02:00
wm4 8bfcae748c audio: fix missed wakeup when changing audio output device
When playing audio-only, and changing the audio output device, playback
froze until the next time the playback core happened to wakeup (like
moving the mouse, or OSD redrawing). This is probably because of the
awful statemachine in fill_audio_out_buffers() - just make it recreate
the AO directly instead.
2016-09-15 14:50:38 +02:00
wm4 9c9cf125ad osd: slightly simplify update logic
Remove the per-part force_redraw flags, and instead make the difference
between flagging dirty state and returning it to the player frontend
more explicit. The big issue is that 1. the OSD needs to know the dirty
state, and it should be cleared strictly when it is re-rendered
(force_redraw flag), and 2. the player core needs to be notified once,
and the notification must be reset (want_redraw flag).

The call in loadfile.c is replaced by making osd_set_sub() set the
change flag. Increasing the change flag on dirty state (the force_redraw
check in render_object()) should not be needed, because OSD part
renderers set it correctly (at least now).

Doing this just because someone pointed this out.
2016-09-15 14:50:38 +02:00
wm4 5968a307d5 options: add --hwdec=yes as alias for --hwdec=auto
This also lets you just do "mpv --hwdec file.mkv", with the minor caveat
that the legacy syntax "--hwdec val" or "-hwdec val" (without "=") does
not work as expected anymore.
2016-09-15 14:50:38 +02:00
wm4 d1f5b926ac etc/builtin.conf: minor edits
The previous commit merely copied the profile string to a file (plus
changing how RPI-specific defaults are initialized), now make some
changes on top of it. In particular, remove the --input-lirc option,
which was removed a long time ago, but forgotten from the libmpv
profile.
2016-09-15 14:50:38 +02:00
wm4 2b0c620b22 player: move builtin profiles to a separate file
Move the embedded string with the builtin profiles to a separate
builtin.conf file. This makes it easier to read and edit, and you can
also check it for errors with --include=etc/builtin.conf. (Normally
errors are hidden intentionally, because there's no way to output error
messages this early, and because some options might not be present on
all platforms or with all configurations.)
2016-09-15 14:50:38 +02:00
wm4 98f1b5fb98 player: remove unintended !mingw ifdef for IPC uninit
Just wow. This function is implemented in ipc-win.c, and was surely be
meant to be called. But it wasn't called. This could in theory cause
crashes during exit if IPC clients were active.

Untested whether it really works.
2016-09-15 13:17:07 +02:00
wm4 1b5b23b948 client API: remove SIGPIPE overriding code
This workaround prevented that libmpv users could accidentally crash
when the SIGPIPE signal was triggered by FFmpeg's OpenSSL/GnuTLS usage.
But it also modifies the global signal handler state, so remove it now
that this workaround is not required anymore.
2016-09-15 13:13:23 +02:00
wm4 f143665864 manpage: explain "speed-adjusted" FPS for --interpolation-threshold
Fixes #3528.
2016-09-15 10:11:44 +02:00
wm4 30d147687f vo_opengl: fix OSD with icc-profile after previous commit
This happened to break because the texture unit wasn't reset to 0, which
some code expects. The OSD code in particular set the OSD texture on the
wrong texture unit, with the result that OSD/OSC was not visible.
2016-09-14 22:49:08 +02:00
wm4 88a07c5f53 vo_opengl: dynamically manage texture units
A minor cleanup that makes the code simpler, and guarantees that we
cleanup the GL state properly at any point.

We do this by reusing the uniform caching, and assigning each sampler
uniform its own texture unit by incrementing a counter. This has various
subtle consequences for the GL driver, which hopefully don't matter. For
example, it will bind fewer textures at a time, but also rebind them
more often.

For some reason we keep TEXUNIT_VIDEO_NUM, because it limits the number
of hook passes that can be bound at the same time.

OSD rendering is an exception: we do many passes with the same shader,
and rebinding the texture each pass. For now, this is handled in an
unclean way, and we make the shader cache reserve texture unit 0 for the
OSD texture. At a later point, we should allocate that one dynamically
too, and just pass the texture unit to the OSD rendering code. Right now
I feel like vo_rpi.c (may it rot in hell) is in the way.
2016-09-14 20:46:45 +02:00
wm4 e24ba8fa7f vo_opengl: require explicit reset on shader cache after rendering
The caller now has to call gl_sc_reset(), and _after_ rendering. This
way we can unset OpenGL state that was setup for rendering. This affects
the shader program, for example. The next commit uses this to
automatically manage texture units via the shader cache.

vo_rpi.c changes untested.
2016-09-14 20:24:06 +02:00
wm4 ffbc85cde9 vo_opengl: remove a redundant glActiveTexture() call
This bound video textures to individual texture units - this is how it
used to work long ago, but now is pointless, and maybe even dangerous.
2016-09-14 18:51:32 +02:00
Niklas Haas 8f1a889f75 vo_opengl: make the number of PBOs tunable
Also set the number of PBOs from 2 to 3, which should be better for
pipelining. This makes it easier to add more in the future.
2016-09-14 14:07:21 +02:00
wm4 9b6c93e904 vo_opengl: drm: use new EGL context creation code 2016-09-14 11:00:17 +02:00
wm4 c56f5f0681 vo_opengl: wayland: use new EGL context creation code 2016-09-14 10:46:52 +02:00
wm4 215268ea34 vo_opengl: EGL: dump some version info 2016-09-14 10:38:37 +02:00
wm4 d2e8bc4499 vo_opengl: EGL: better desktop-GL context creation
Stops Mesa from restricting us to OpenGL 3.0. It also tries to create
GLES 3 contexts for drivers which do not just return a higher context
when requesting GLES 2.

I don't know whether this code is a good or bad idea. A not-so-good
aspect is that we don't check for EGL 1.5 (or 1.4 extensions) for some
of the more advanced context attributes. But EGL implementations should
be able to tolerate it and return an error, and then we'd use the
fallback.
2016-09-14 10:19:09 +02:00
wm4 c48bd0ef18 vo_opengl: EGL: silence eglBindAPI() error message
It's not helpful and will be printed with EGL implementations that don't
support OpenGL at all. Just shut it up.
2016-09-13 20:38:05 +02:00
wm4 9def3682d1 vo_rpi, vo_opengl: separate RPI/EGL-specific code for both VOs
This used to be shared, but since vo_rpi is going to be removed,
untangle them. There was barely any actual code shared since the recent
changes anyway.

As a subtle change, we also stop opening libGLESv2.so explicitly in the
vo_opengl backend, and use RTLD_DEFAULT instead.
2016-09-13 20:35:53 +02:00
wm4 5819a4e301 vo_opengl: rpi: use new egl context creation helper function
Only for the "new" vo_opengl backend code.
2016-09-13 20:16:45 +02:00
wm4 060599ac6a vo_x11: fix some ifdeffery
This failed to compile when xext was not available.
2016-09-13 18:26:06 +02:00
wm4 0ccceecdc6 vo_opengl: mali fbdev support
Minimal support just for testing.

Only the window surface creation (including size determination) is
really platform specific, so this could be some generic thing with
platform-specific support as some sort of sub-driver, but on the other
hand I don't see much of a need for such a thing.

While most of the fbdev usage is done by the EGL driver, using this
fbdev ioctl is apparently the only way to get the display resolution.
2016-09-13 18:26:06 +02:00
wm4 6dc9280b58 vo_opengl: factor some EGL context creation code
Add a function to egl_helpers.c for creating an EGL context and make
context_x11egl.c use it. This is meant to be generic, and should work
with other windowing APIs as well. The other EGL-using code in mpv can
be switched to it.
2016-09-13 18:03:43 +02:00
wm4 3905c46f9a DOCS/interface-changes.rst: minor cleanup
Edit the 0.21.0 section: remove the redundant vo_opengl items, move some
up. Move the additions (which are less important and which aren't
documented completely anyway) below the incompatible
changes/deprecations.
2016-09-13 10:02:27 +02:00
wm4 5c0c0e469b manpage: vo_rpi -> vo_opengl 2016-09-13 09:24:17 +02:00
Niklas Haas f7471b7ff4 vo_opengl: fix typo in bt.601 auto-guessing logic
The wrong enum got copied here, so it was essentially using the transfer
characteristics as the primaries (instead of the primaries), which
accidentally worked fine most of the time (since the two usually
coincided), but broke on weird/mistagged files.
2016-09-13 09:23:47 +02:00
Vladimir Panteleev 6a0df47d94 player: Save sub-speed value when resuming playback 2016-09-13 09:23:28 +02:00
Vladimir Panteleev fb8f2a812e player: Improve OSD formatting of sub-speed option 2016-09-13 09:23:26 +02:00
Vladimir Panteleev 00f8ee573b player: Apply new sub-speed values during playback 2016-09-13 09:23:22 +02:00
Vladimir Panteleev 08cbac311d sub: Add SD_CTRL_UPDATE_SPEED 2016-09-13 09:23:19 +02:00
Ricardo Constantino 60a0815b4c ytdl_hook: don't bother adding subtitles if duration isn't known
EDL doesn't work with subtitles with unknown length.
2016-09-13 09:23:00 +02:00
Ricardo Constantino 5edd6a8caa ytdl_hook: Support playlist entries without subtitles
Fixes missing subtitle tracks if the first entry didn't have any.

Previously it just checked for the first entry in the playlist for
requested languages and if that entry happened to not have subtitles
they also wouldn't show up for the other entries.

It will skip languages if the first entry with subs has less or
different languages than the others.

Unrelated to http_dash_segments.
2016-09-13 09:22:55 +02:00
wm4 0e72f64ff4 vo_rpi: deprecate this VO 2016-09-12 20:05:48 +02:00
wm4 876ec446f3 vo: change defines to an enum
(They're flags, so it still doesn't make sense to actually name the enum
and use it as a type.)
2016-09-12 20:05:48 +02:00
wm4 8c39c6903b vo_opengl: fix non-C11 TLS fallback for gcc
The consequence of this was that e.g. hardware decoding with VAAPI-EGL
could sometimes not work if the compiler didn't support C11. (Although I
found this one on RPI, which also uses this mechanism.)
2016-09-12 20:05:48 +02:00
wm4 e8cdc22245 vo_opengl: better behavior in GL error corner cases
If the shader fails to compile, and assertion could trigger in
gl_sc_gen_shader_and_reset() due to the code trying to recreate the
shader every time, and re-appending the uniforms every time. Just reset
the uniform array to fix this.

Some disturbed GL drivers might not return anything for glGetShaderiv()
if the GL state got "lost", so initialize variables just for additional
robustness.
2016-09-12 20:05:43 +02:00
wm4 b261e1e782 vo_opengl: rpi: merge vo_rpi features
Since vo_rpi is going to be deprecated, better port its features to the
vo_opengl backend.

The most tricky part is the fact that recreating dispmanx elements will
conflict with the GL context. Fortunately, RPI's EGL support is
reasonably compliant, and we can transplant the context to newly created
dispmanx elements, making this much easier. This means unlike vo_rpi,
the GL state will actually not be recreated.
2016-09-12 20:03:55 +02:00
wm4 9a873cc53b vo_opengl: redirect window screenshot requests to backend
If the glReadPixels method is not available, let the backend do it.

Useful for the next commit.
2016-09-12 19:58:58 +02:00
wm4 274e71ee8b vo_opengl: add hw overlay support and use it for RPI
This overlay support specifically skips the OpenGL rendering chain, and
uses GL rendering only for OSD/subtitles. This is for devices which
don't have performant GL support.

hwdec_rpi.c contains code ported from vo_rpi.c. vo_rpi.c is going to be
deprecated. I left in the code for uploading sw surfaces (as it might
be slightly more efficient for rendering sw decoded video), although
it's dead code for now.
2016-09-12 19:58:58 +02:00
shinchiro 343f5ca24b man: fix building pdf 2016-09-12 13:15:36 +02:00
wm4 043512045e command: don't log "ignore" command with -v verbosity
It's damn annoying because the mouse move input event is mapped to this
by default.
2016-09-11 19:45:11 +02:00
James Ross-Gowan 6ac0ef78c5 client API: don't miss property changes after updates
When update_prop() successfully fetches a changed property value, it
sets prop->changed to true. mark_property_changed() only sets
prop->need_new_value if prop->changed is false, so this had the effect
of ignoring new property values until prop->changed was set back to
false in the next call to gen_property_change_event(). This meant that
when a property change event was generated for a property that was not
observed with MPV_FORMAT_NONE, it would contain the value associated
with the earliest property change, rather than the most recent, and the
property change event for the most recent change would never be
generated.

To fix this, mark_property_changed() should unconditionally set
prop->changed and prop->need_new_value, which will cause the property
value to be re-fetched and a property change event to be generated for
the most recent value.
2016-09-11 23:58:23 +10:00
Philip Langdale 3f7e43c2e2 hwdec_cuda: Add trivial cuda-copy wrapper
The cuvid decoder already knows how to copy back to system memory
if NV12 frames are requested, and this will happen if the decoder
is used without the hwdec.

For convenience, let's add a wrapper hwdec so people don't have
to explicitly pick the cuvid decoder if they want this behaviour.
2016-09-11 10:46:22 +02:00
wm4 71681e04ee options: fix another minor regression
vf_scale's "h" sub-option was interpreted as "--h".
2016-09-11 00:04:49 +02:00
Philip Langdale 440e0a98ab hwdec_cuda: Implement download_image for screenshots
Data has to be copied to system memory for screenshots.
2016-09-10 23:17:47 +02:00
Philip Sequeira 1e684e3cca build: recompile zsh completion if zsh.pl changes 2016-09-10 21:46:03 +02:00
Philip Sequeira eec7660274 TOOLS/zsh.pl: don't filter files by extension
Closes #2273. See that issue for explanation/discussion.

I'll add examples on how to filter in your own config to the wiki soon:
https://github.com/mpv-player/mpv/wiki/Zsh-completion-customization
2016-09-10 21:46:03 +02:00
Philip Sequeira defcb9047e TOOLS/zsh.pl: die if we can't parse main options
This will catch cases where mpv runs without error, but the
--list-options output isn't what we expect. Otherwise, we'll make a
broken completion file that will result in cryptic errors when pressing
tab, like:

_mpv:18: command not found: *:files:->mfiles

That's been the case for most of the zsh completion issues we've had
reported, that I can remember.

Also make uninitialized variable access fatal so that failures to parse
other options will also make the script die eventually, albeit with a
less nice message.
2016-09-10 21:46:01 +02:00
wm4 fc1c004cd8 options: fix --list-options after previous commit
Fixes #3509.
2016-09-10 20:49:10 +02:00
wm4 484328fe04 options: make --h list options according to a pattern passed to it
Useless feature, but I want it.

Won't work on Windows due to missing fnmatch().
2016-09-10 16:29:24 +02:00
wm4 ebc04333d2 m_config: remove another unused leftover 2016-09-10 16:01:05 +02:00
wm4 5ca654301b stream_cb: don't add "*://" to protocol list
--list-protocol was printing a *:// entry, which looked strange at best.
The "*" protocol was used to always match everything, so stream_cb.c
could hook in custom protocols with a prefix chosen by the API user.

Change it instead so that an empty protocol list means "match all",
which also gets rid of the special-cased "*" entry.
2016-09-10 15:35:22 +02:00
wm4 7383b45682 command: do not call mp_switch_track() before proper initialization
This is an awful corner-case party, because we've started to allow the
user to send track-switching related commands before stream selection is
done in the loading stage. If mp_switch_track() is called before this
stream selection, it can behave inconsistently. So if we're in the
pre-loading phase, we must set the stream selection options to get
streams selected later, instead of calling this function. There seem to
be some annoying circumstances that exclude mp_switch_track() from
handling this logic too, so do it at all call-sites.
2016-09-10 13:51:17 +02:00
bugdone fdc5388f8c man: fix typo 2016-09-10 13:15:44 +02:00
Philip Langdale 76818e3dc7 hwdec_cuda: Use the non-deprecated CUDA-GL interop API
The nvidia examples use the old (as in CUDA 3.x) interop API which
is deprecated, and I think not even functional on recent versions
of CUDA for windows. As I was following the examples, I used this
old API.

So, let's update to the new API, and hopefully, it'll start working
on windows too.
2016-09-10 13:15:27 +02:00
sda89ha9 d054a7181f player: fix average frame duration calculation 2016-09-09 19:18:08 +02:00
wm4 04320d26eb stream, demux, config: remove some dead/unneeded option-related code
This has all been made unnecessary recently. The change not to copy the
global option struct in particular can be made because now nothing
accesses the global options anymore in the demux and stream layers.

Some code that was accidentally added/changed in commit 5e30e7a0 is also
removed, because it was simply committed accidentally, and was never
used.
2016-09-09 17:54:57 +02:00
wm4 c157641019 stream_cdda: remove weird option parsing stuff
Mostly untested.

This is not compatible. It removes the URL fields for track range and
cdrom speed (what did this even do). The device is not not to be
prefixed with an additional "/" if it's put into the URL. I can't be
bothered to keep these things compatible, just rip your damn CDs
instead.
2016-09-09 17:54:35 +02:00
wm4 5324fb731f tv: remove weird option parsing stuff
Mostly untested.
2016-09-09 17:54:35 +02:00
wm4 9213db0d49 stream_dvb: remove weird option parsing stuff
Mostly untested.
2016-09-09 17:54:35 +02:00
Philip Langdale d66f2a679b man/options: Document cuda hwdec. 2016-09-09 17:54:35 +02:00
wm4 27e3f04de7 client API: fix error code string
Said "audio" instead of "video".
2016-09-09 12:28:03 +02:00
wm4 ea94b01e6b client API: make mpv_opengl_cb_uninit_gl() behavior slightly nicer
Instead of deselecting the video stream plainly, use the slightly more
robust error_on_track() function. Also give it an error code (although
I'm not sure if this one is confusing, it's better than the one before).
2016-09-09 12:27:41 +02:00
wm4 5e30e7a041 stream_dvd, stream_dvdnav: remove weird option parsing stuff
Same deal as with stream_bluray.

Untested because I don't give a fuck about your shitty DVDs.
2016-09-08 21:46:48 +02:00
wm4 35e8b6c1e6 options: drop unreferenced --bluray-angle option
Uh, what? It wasn't used at all. It was probably accidentally dropped at
one point, or it was never used at all. Whatever, who cares.
2016-09-08 21:02:31 +02:00
wm4 ca55a32922 stream_bluray: fix a minor memory leak 2016-09-08 20:59:24 +02:00
wm4 c8cc1f401b stream_bluray: remove weird option parsing stuff
Instead, parse manually. This is to get rid of the option API usages,
which seem unnecessary and shoehorned. (Just look at the URL pseudo
parsing and the dumb url_options map. They were pretty much artifacts
from refactoring old mplayer code.)
2016-09-08 20:59:13 +02:00
wm4 7177ef3e1c vo: remove unused VOCTRL_GET_PANSCAN
It was used to determine whether the VO supports VOCTRL_SET_PANSCAN.
With all those changes to property semantics this became unnecessary,
and its only use was dropped at some point.
2016-09-08 18:59:21 +02:00
wm4 a2fce5ba26 vo: don't access global options unsynchronized
And since there's no proper fine-grained option change notification
mechanism yet, intercept updates to "framedrop" manually.
2016-09-08 18:53:20 +02:00
wm4 c3097422f2 vo_opengl: use dedicated image unref function in config case
Just another corner-caseish potential issue. Unlike unreffing the image
manually, unref_current_image() also takes care of properly unmapping
hwdec frames. (The corner-case part of this is that it's probably never
mapped at this point, but it's apparently not entirely guaranteed.)
2016-09-08 16:06:12 +02:00
wm4 8bb9632e27 vo_opengl: simplify a condition
The " || vimg->mpi" part virtually never seems to trigger, but on the
other hand could possibly create unintended corner cases (for example by
trying to upload a NULL image, which would then be marked as an error
and render a blue screen).

I guess it's a leftover from over times, where a NULL image meant
"redraw the current frame". This is now handled by actually passing
along the current frame.
2016-09-08 16:06:12 +02:00
Philip Langdale 2048ad2b8a hwdec/opengl: Add support for CUDA and cuvid/NvDecode
Nvidia's "NvDecode" API (up until recently called "cuvid" is a cross
platform, but nvidia proprietary API that exposes their hardware
video decoding capabilities. It is analogous to their DXVA or VDPAU
support on Windows or Linux but without using platform specific API
calls.

As a rule, you'd rather use DXVA or VDPAU as these are more mature
and well supported APIs, but on Linux, VDPAU is falling behind the
hardware capabilities, and there's no sign that nvidia are making
the investments to update it.

Most concretely, this means that there is no VP8/9 or HEVC Main10
support in VDPAU. On the other hand, NvDecode does export vp8/9 and
partial support for HEVC Main10 (more on that below).

ffmpeg already has support in the form of the "cuvid" family of
decoders. Due to the design of the API, it is best exposed as a full
decoder rather than an hwaccel. As such, there are decoders like
h264_cuvid, hevc_cuvid, etc.

These decoders support two output paths today - in both cases, NV12
frames are returned, either in CUDA device memory or regular system
memory.

In the case of the system memory path, the decoders can be used
as-is in mpv today with a command line like:

mpv --vd=lavc:h264_cuvid foobar.mp4

Doing this will take advantage of hardware decoding, but the cost
of the memcpy to system memory adds up, especially for high
resolution video (4K etc).

To avoid that, we need an hwdec that takes advantage of CUDA's
OpenGL interop to copy from device memory into OpenGL textures.

That is what this change implements.

The process is relatively simple as only basic device context
aquisition needs to be done by us - the CUDA buffer pool is managed
by the decoder - thankfully.

The hwdec looks a bit like the vdpau interop one - the hwdec
maintains a single set of plane textures and each output frame
is repeatedly mapped into these textures to pass on.

The frames are always in NV12 format, at least until 10bit output
supports emerges.

The only slightly interesting part of the copying process is that
CUDA works by associating PBOs, so we need to define these for
each of the textures.

TODO Items:
* I need to add a download_image function for screenshots. This
  would do the same copy to system memory that the decoder's
  system memory output does.
* There are items to investigate on the ffmpeg side. There appears
  to be a problem with timestamps for some content.

Final note: I mentioned HEVC Main10. While there is no 10bit output
support, NvDecode can return dithered 8bit NV12 so you can take
advantage of the hardware acceleration.

This particular mode requires compiling ffmpeg with a modified
header (or possibly the CUDA 8 RC) and is not upstream in ffmpeg
yet.

Usage:

You will need to specify vo=opengl and hwdec=cuda.

Note that hwdec=auto will probably not work as it will try to use
vdpau first.

mpv --hwdec=cuda --vo=opengl foobar.mp4

If you want to use filters that require frames in system memory,
just use the decoder directly without the hwdec, as documented
above.
2016-09-08 16:06:12 +02:00
wm4 622f9cf1aa vo_opengl: fix incorrect video rendering after vdpau preemption recovery
This could also trigger in certain other cases, whenever it falls back
to dumb mode.
2016-09-07 18:48:24 +02:00
wm4 4552ee286b vo_opengl: fix another potential vdpau preemption issue
reinit() will change the image params fields, so give it a copy.

Will fix potential crashes if preemption happens more than once.
2016-09-07 18:23:14 +02:00
wm4 062423381d ao_rsound: fix compilation
Probably fixes #3501.
2016-09-07 18:10:12 +02:00
wm4 2372b0a6f6 sub: fix previous commit with older libass releases 2016-09-07 14:11:56 +02:00
wm4 2f1eb49e9f sub: actually apply text alignment options to non-ASS subtitles
This is a bug fix, and the text alignment functionality probably got
lost sometime along the way.

For ASS subtitles, this could have unintended consequences, so it's hard
to get right - thus it's not applied to ASS subtitles.

For other text subtitles, this should be fine, though. It still works on
ASS subtitles as promised by the manpage if --no-sub-ass is used.
2016-09-07 13:42:55 +02:00
wm4 355361e1e3 manpage: remove more references to deprecated sub-option syntax
Fixes #3497.
2016-09-07 12:55:21 +02:00
wm4 5a7b1ff4c0 ao_pcm: remove some useless messages
The first one is printed even if the user disabled video (or there's no
video), so just remove it. The second one uses deprecated sub-option
syntax, so remove that as well.
2016-09-07 12:54:33 +02:00
wm4 591e21a2eb osdep: rename atomics.h to atomic.h
The standard header is stdatomic.h, so the extra "s" freaks me out every
time I look at it.
2016-09-07 11:26:25 +02:00
wm4 c6b7a4dace atomics: readd some emulation
This time it's emulation that's supposed to work (not just dummied out).
Unlike the previous emulation, no mpv code has to be disabled, and
everything should work (albeit possibly a bit slowly). On the other
hand, it's not possible to implement this kind of emulation without
compiler support. We use GNU statement expressions and __typeof__ in
this case.

This code is inactive if stdatomic.h is available.
2016-09-06 20:15:07 +02:00
wm4 2a4e7dcaad DOCS/interface-changes.rst: list exact sub-option replacements
Actually, only link to a wiki page doing that, because these are too
many options.
2016-09-06 20:10:05 +02:00
wm4 d4d8b3a4fc demux: do not access global options
Don't access MPOpts directly, and always use the new m_config.h
functions for accessing them in a thread-safe way.

The goal is eventually removing the mpv_global.opts field, and the
demuxer/stream-layer specific hack that copies MPOpts to deal with
thread-safety issues.

This moves around a lot of options. For one, we often change the
physical storage location of options to make them more localized,
but these changes are not user-visible (or should not be). For
shared options on the other hand it's better to do messy direct
access, which is worrying as in that somehow renaming an option
or changing its type would break code reading them manually,
without causing a compilation error.
2016-09-06 20:09:56 +02:00
wm4 9f0e7bb998 input, demux_tv: remove some older option access methods 2016-09-06 20:09:44 +02:00
wm4 e66c098228 demux_mkv: don't crash if --ordered-chapters-files fails
It just crashed.
2016-09-06 20:09:18 +02:00
wm4 618d7f59b0 vo_vdpau: rename some sub-options
Since the sub-options have been deprecated very recently, and are
redirected to global options, we don't need to document this change.
2016-09-06 20:08:44 +02:00
wm4 723e3ec8d9 common: use char array for version string
Use a char array instead of a pointer, which allows using the version
variables in a constant context.
2016-09-06 20:08:44 +02:00
wm4 9ab0f60d44 vo_opengl: simplify option handling
Instead of copying the options around... just don't. video.c now has
full control over when options are updated. (It still gets notified from
outside, but it decides when the updated options are copied: when
m_config_cache_update() is called.) So there's no need for tricky
stuff, and it can be simplified a bit.

Also change lcms.c. We could do it like video.c, and get the options
from the global config store. But it seems simpler to just provide a
pointer to an option struct, which is arbitrarily mutated from the
outside (from the perspective of lcms.c).
2016-09-06 11:11:36 +02:00
wm4 e5cefa346d vo_opengl: fix --icc-profile initial behavior
Setting --icc-profile had no effect, until a vo_opengl option was
changed at runtime. We must initialize the renderer for the initial
option state too.

For some reason, the ICC profile gets loaded twice. The next commit
happens to fix this.
2016-09-06 11:11:23 +02:00
pavelxdd c36aaeeb2a wscript: fix typo 2016-09-06 09:43:59 +02:00
wm4 c4e01cc00d m_config: avoid accidentally causing deprecation warnings
It has to copy each option, whether it's deprecated or not. This would
print a warning on every deprecated sub-option, even if it's not used.
Yep, this is very stupid.

At least m_config_get_co() gets actually slightly cleaner, because it
separates the search and the deprecation handling.
2016-09-05 21:26:39 +02:00
wm4 1d9032f011 audio/out: deprecate "exclusive" sub-options
And introduce a global option which does this. Or more precisely, this
deprecates the global wasapi and coreaudio options, and adds a new one
that merges their functionality. (Due to the way the sub-option
deprecation mechanism works, this is simpler.)
2016-09-05 21:26:39 +02:00
wm4 13786dc643 audio/out: deprecate device sub-options
We have --audio-device, which can force the device. Also add something
describing to this extent to the manpage.
2016-09-05 21:26:39 +02:00
wm4 69283bc0f8 options: deprecate suboptions for the remaining AO/VOs 2016-09-05 21:26:39 +02:00
wm4 633eb30cbe options: add automagic hack for handling sub-option deprecations
I decided that it's too much work to convert all the VO/AOs to the new
option system manually at once. So here's a shitty hack instead, which
achieves almost the same thing. (The only user-visible difference is
that e.g. --vo=name:help will list the sub-options normally, instead of
showing them as deprecation placeholders. Also, the sub-option parser
will verify each option normally, instead of deferring to the global
option parser.)

Another advantage is that once we drop the deprecated options,
converting the remaining things will be easier, because we obviously
don't need to add the compatibility hacks.

Using this mechanism is separate in the next commit to keep the diff
noise down.
2016-09-05 21:26:39 +02:00
wm4 327cb2a06c vo_direct3d: deprecate direct3d_shaders alias
And remove the difference between the aliases. This is needed to make
the sub-option changes less painful.
2016-09-05 21:26:39 +02:00
wm4 9e6b9d8a98 vo_image: move to global options
This is a bit "special", because the config tree wants unique
m_sub_options pointers in the whole thing.
2016-09-05 21:04:55 +02:00
wm4 726ef35aa8 ao_jack: move to global options 2016-09-05 21:04:41 +02:00
wm4 4ab860cddc options: add a mechanism to make sub-option replacement slightly easier
Instead of requiring each VO or AO to manually add members to MPOpts and
the global option table, make it possible to register them automatically
via vo_driver/ao_driver.global_opts members. This avoids modifying
options.c/options.h every time, including having to duplicate the exact
ifdeffery used to enable a driver.
2016-09-05 21:04:17 +02:00
wm4 cc813647d5 m_config: move parts of m_config_add_option into its own function
Preparation for the next commit.
2016-09-05 21:03:46 +02:00
wm4 6cd80e972e dispatch: improve recent locking changes slightly
Instead of adding a lock_frame to the list when mp_dispatch_lock() is
called, just set a simple flag. This uses the fact that the lock is not
recursive, and can happen once per mp_dispatch_queue_process(). It
avoids the dynamic allocation, and makes error checking slightly
stricter.

Again, this is actually redundant and exists only for error-checking.
It'd actually need only a counter, because the actual locking is done by
"parking" the target thread in mp_dispatch_queue_process() and then
setting queue->idling=false. Only when mp_dispatch_unlock() sets it to
true again other work can proceed again. Document this too.
2016-09-05 20:58:45 +02:00
wm4 3878a59e2c dispatch: redo locking, and allow reentrant processing
A deadlock bug was reported with the following test program:

	mpv_handle *mpv = mpv_create();
	mpv_set_option_string(mpv, "ytdl", "yes");
	mpv_initialize(mpv);
	mpv_terminate_destroy(mpv);

The cause of this is loading the ytdl.lua script, which triggers a
certain code path that calls mp_dispatch_queue_process() recursively. It
does so to wait until the script is loaded, and we want to keep that.

Reentrancy was not supported by mp_dispatch, which leads to the
deadlock. Rewrite the locking so that it does. We mainly get rid of the
"exclusive_lock" mutex. Instead we use the existing lock/condition
variable to wait until we can grab a logical lock.

Note that the lock_frame business can be replaced with a simple counter.
Instead of checking the lock_frame address, it'd simply increment and
store the counter when entering mp_dispatch_queue_process(), and then
compare the counter to decide whether or not to wait. But I think the
additional error checking done by the lock_frame list is valuable.

Fixes #3489.
2016-09-04 18:05:36 +02:00
wm4 2619d8eff4 client API: implement mpv_suspend/resume slightly differently
Why do these API calls even still exist? I don't know, and maybe they
don't make any sense anymore. But whether they should be removed or not
is not a decision I want to make now. I want to get rid of
mp_dispatch_suspend/resume(), though. So implement the client APIs
slightly differently.
2016-09-04 18:05:36 +02:00
Ricardo Constantino d889d1fbaa travis: trigger website rebuild only on docs changes 2016-09-04 18:05:36 +02:00
Stefano Pigozzi e955ae9000 travis: rebuild website for updated docs on push 2016-09-04 13:29:11 +02:00
wm4 4236321835 client API: more option/property updates 2016-09-03 17:14:04 +02:00
wm4 4f263dce34 sd_lavc: enable teletext
Whitelisting supported codecs is (probably) still better than just
allowing everything, given the weird FFmpeg API. I'm also assuming
Libav doesn't even have the codec ID, but I didn't check.

Also add a --teletext-page option, since otherwise it decodes every
teletext page and shows them in succession.

And yes, we can't use av_opt_set_int() - instead we have to set it as
string. Because FFmpeg's option system is terrible.
2016-09-03 17:12:53 +02:00
wm4 590caeb2bd command: try selecting the next track if track switching fails
This affects the "cycle" command. If we switched to the next track, and
it failed to initialize, we just deselected everything.

Change it so that if initialization fails early (typically decoder
selection), we try to continue with the track after that. (Even if
nothing can be selected, the loop will terminate when trying to select
nothing.

Fixes #3446.
2016-09-03 17:12:29 +02:00
wm4 0c2c059826 player: remove opengl-es=no flag from opengl-hq profile
This was mistakenly added. It was removed from the vo_opengl_hq defaults
at an earlier time, but the documentation was not updated, which is why
it made it back into the profile.

Fixes #3485.
2016-09-03 13:07:58 +02:00
wm4 9bc39b352e manpage: document another option/property inconsistence 2016-09-03 13:05:19 +02:00
wm4 ece86d1061 config: deprecate ao and vo auto-profiles
These never made any sense. They checked the --vo/--ao option, and
applied the profile corresponding to the first entry. So the only way to
get any use of those was to use the --ao or --vo option explicitly. You
can get the same functionality by making a manual profile, making these
force the ao/vo, and then using --profile on command line instead of
--vo/--ao.
2016-09-03 12:46:32 +02:00
wm4 c92450d7fb manpage: mention how to apply/view opengl-hq profile 2016-09-02 21:35:40 +02:00
wm4 a85eecfe40 ao_alsa: change sub-options to global options
Same deal as with vo_opengl.

Also edit the outdated information about multichannel output a little.
2016-09-02 21:21:47 +02:00
wm4 eb14b18a33 config: allow profile forward-references in default profile
This works by first parsing a config file into the default profile, and
applying it once parsing the whole file is finished.

This won't work across config files (not even if you include other
config files via "include=file.conf").
2016-09-02 21:21:47 +02:00
wm4 9770ce6c44 m_config: make sure profile values are never NULL
Apparently this was supposed to be handled - but badly at best. Make
unset values always have the value "" instead of NULL to avoid
special-cases.

In particular, this fixes passing NULL to a %s format specifier to
printf in show_profile(). Glibc prints this as "(null)", but it's
undefined behavior, and other libcs can crash.
2016-09-02 21:21:47 +02:00
wm4 b92d3b6d44 w32_common: initialize playback status as soon as possible
On a VOCTRL_UPDATE_PLAYBACK_STATE store the state, and use it to
initialize the next time the task list becomes available.

This actually fixes #3482. Revert commit f2e25e9e because it's not
needed anymore.
2016-09-02 21:21:47 +02:00
wm4 cd7c7d0841 command: remove vo-cmdline
With the recent vo_opengl changes it doesn't do anything anymore.
I don't think a deprecation period is necessary, because the command
was always marked as experimental.
2016-09-02 21:21:47 +02:00
wm4 b2c84a91b6 options: deprecate --vo-defaults
With the conversion from sub-options to global options, this becomes
useless. This change also comes slightly too soon, because not all VOs
have been changed yet.
2016-09-02 21:21:47 +02:00
wm4 849480d0c9 vo_opengl: deprecate sub-options, add them as global options
vo_opengl sub-option were always rather annoying to handle. It seems
better to make them global options instead. This is simpler and easier
to use. The only disadvantage we are aware of is that it's not clear
that many/all of these new global options work with vo_opengl only.

--vo=opengl-hq is also deprecated.

There is extensive compatibility with the old behavior. One exception is
that --vo-defaults will not apply to opengl-hq (though with opengl it
still works). vo-cmdline is also dysfunctional and will be removed in a
following commit.

These changes also affect opengl-cb.

The update mechanism is still rather inefficient: it requires syncing
with the VO after each option change, rather than batching updates.
There's also no granularity (video.c just updates "everything", and if
auto-ICC profiles are enabled, vo_opengl.c will fetch them on each
update).

Most of the manpage changes were done by Niklas Haas <git@haasn.xyz>.
2016-09-02 21:21:47 +02:00
wm4 a07dae57e3 vo_opengl: rename 3dlut-size to icc-3dlut-size
Not documenting this yet, because a later commit will change all the
options anyway.
2016-09-02 15:58:40 +02:00
wm4 72c6bf1345 m_config: add some convenience functions
To be used by the following commits.
2016-09-02 15:58:15 +02:00
wm4 2c917219cf vo: use new option update mechanism
This is still rather basic.

run_reconfig() and run_control() update the options because it's needed
for panscan (and other video scaling options), and fullscreen, border,
ontop updates. In the old model, these options could be accessed only
while both playback thread and VO threads were locked  (i.e. during
synchronous calls like vo_control()), so this should be sufficient in
order not to miss any updates. In the future, a more fine-grained update
mechanism could be added to handle these updates "exactly".

x11_common.c contains an evil hack, as I see no reasonable way to handle
this properly. The VO thread can't "lock" the main thread, so this is
not simple.
2016-09-02 15:50:54 +02:00
wm4 423e53ba0b m_config: introduce basic mechanism to synchronize global option updates
The way option runtime changes are handled is pretty bad in the current
codebase. There's a big option struct (MPOpts), which contains almost
everything, and for which no synchronization mechanism exists. This was
handled by either making some options read-only after initialization,
duplicating the option struct, using sub-options (in the VO), and so on.

Introduce a mechanism that creates a copy of the global options (or
parts of it), and provides a well-defined way to update them in a
thread-safe way.

Most code can remain the same, just that all the component glue code has
to explicitly make use of it first.

There is still lots of room for improvement. For example, the update
mechanism could be better.
2016-09-02 15:50:40 +02:00
wm4 f2e25e9e1f player: don't send win32 taskbar update before window is created
If the win32 taskbar progress update is sent before the VO window is
created, then w32_common.c will ignore it because the actual taskbar
object was not created yet. (At least this is what I suspect happens.
The window is already created at this point, but not mapped.)

Hopefully fix this is fixed by creating until after the window is
created, i.e. the VO has been configured at least once.

Untested (who wants to boot into Windows just to wait until it has
applied all of its stupid updates).

Also not explicit is whether update_vo_playback_state() will actually be
called soon enough in all cases. It probably is.

Probably fixes #3482.
2016-09-02 15:01:09 +02:00
wm4 b2657814c9 vo_opengl: minor renderer option access refactor
Reduce accesses to the renderer opts in vo_opengl.c, and instead add
accessors for them to video.c.

I suppose gamma and maybe icc-auto could be moved to vo_opengl.c
options. Also, the output colorspace could probably be adjusted to what
is really used, not just the options (although it's possible that this
commit changes this, due to video.c mutating its own copy of the options
according to actual renderer capapbilities).

But don't deal with this now.
2016-09-02 14:50:03 +02:00
wm4 4fa6bcbb90 m_config: add helper function for initializing af/ao/vf/vo suboptions
Normally I'd prefer a bunch of smaller functions with fewer parameters
over a single function with a lot of parameters. But future changes will
require messing with the parameters in a slightly more complex way, so a
combined function will be needed anyway. The now-unused "global"
parameter is required for later as well.
2016-09-02 14:49:34 +02:00
Jeong Woon Choi 875aeb0f5c charset_conv: Use CP949 instead of EUC-KR
iconv distinguishes between euc-kr and cp949, while libguess
and libuchardet doesn't (only returns euc-kr). EILSEQ occurs
when the input encoding of iconv is set to euc-kr and if the subs
contain letters not included in euc-kr. Since cp949 is a extension
of euc-kr, choose cp949 instead.

Signed-off-by: wm4 <wm4@nowhere>
2016-09-02 14:46:11 +02:00
wm4 c72df80460 DOCS: move libmpv stub to manpage
And replace the sort-of duplicated explanations.

(It's a bit funny to use weblinks to the generated web version of itself
instead of proper RST links, but I think I don't care.)
2016-09-02 09:53:11 +02:00
wm4 907bf83297 manpage: mention the client API/interface change logs
Also, I'm seeing that we still have mplayer-changes.rst - add a warning
that it's outdated.
2016-09-02 09:48:35 +02:00
wm4 3659f9e416 command: deprecate "cache" property, replace with "cache-percent"
The --cache option and cache property conflict, so one of them has to be
renamed. The option is probably used frequently, so initiate
deprecation/rename of the property.
2016-09-02 09:42:19 +02:00
Niklas Haas ce05413a87 vo_opengl: remove pre/post/scale-shaders
Deprecated in favor of user-shaders, which are functionally equivalent
but superior. (Except in the case of scaler-shader, which has no direct
replacement, but it turned out to be a very unpopular feature either way
- most custom scalers don't fit into the mpv kernel infrastructure and
are therefore implemented as user shaders either way)

Signed-off-by: wm4 <wm4@nowhere>
2016-09-02 09:29:16 +02:00
wm4 453fea87fa client API: create core thread at an earlier time
Create the core thread right in mpv_create(), and reduce what
mpv_initialize() does further. This is simpler, and allows the API user
to do more before calling mpv_initialize(). The latter is not the real
goal, rather we'd like mpv_intialize() reduced to do almost nothing. It
still does a lot, but nothing truly special anymore that is absolutely
required for basic mpv workings.

One thing we want the user to be able to do is changing properties
before mpv_initialize() to reduce the special status of
mpv_set_option().
2016-09-01 21:55:21 +02:00
wm4 1393d79417 command: fix or document some property/option consistency issues
Make some existing properties behave more like options. This mostly
means they don't deny access if the associated component is not active,
but redirects to the option.

One kind of fishy change is that we apply --brightness etc. only if
they're not set to the default value. This won't necessarily work with
--vo=xv, but affects only cases where 1. the Xv adapter has been changed
to non-defaults, and 2. the user tries to reset them with mpv by passing
e.g. --brightness=0. We don't care about Xv, and the noted use-case is
dumb, so this change is acceptable.
2016-09-01 20:57:33 +02:00
wm4 192a7344d9 command: remove 2 deprecated properties
They were delcared to be removed in mpv 0.20.0, and the next release
will be 0.21.0.
2016-09-01 20:01:29 +02:00
wm4 e4e1dc3c79 command: rename/deprecate some conflicting property names
These conflict with options of the same name, and prevent a "full"
unification. Not addressed is the "cache" property, and possibly a few
properties that behave differently from their equivalent options.
2016-09-01 20:01:02 +02:00
wm4 d32bee5f01 command: add options to property list
Now options are accessible through the property list as well, which
unifies them to a degree.

Not all options support runtime changes (meaning affected components
need to be restarted for the options to take effects). Remove from the
manpage those properties which are cleanly mapped to options anyway.
From the user-perspective they're just options available through the
property interface.
2016-09-01 20:00:43 +02:00
wm4 17dbb39dec m_config: fix "no-" option handling with sub-options
E.g. --vf=scale=no-arnd didn't work, because it didn't recognize no-arnd
as flag option.

The top-level command line parser is not affected by this, because it
uses the result of m_config_option_requires_param() differently and
assumes unknown parameters do not necessarily require a parameter. (The
suboption parser can't do this.)
2016-09-01 14:29:08 +02:00
wm4 6b4f560f3c vo, ao: disable positional parameter suboptions
Positional parameters cause problems because they can be ambiguous with
flag options. If a flag option is removed or turned into a non-flag
option, it'll usually be interpreted as value for the first sub-option
(as positional parameter), resulting in very confusing error messages.
This changes it into a simple "option not found" error.

I don't expect that anyone really used positional parameters with --vo
or --ao. Although the docs for --ao=pulse seem to encourage positional
parameters for the host/sink options, which means it could possibly
annoy some PulseAudio users.

--vf and --af are still mostly used with positional parameters, so this
must be a configurable option in the option parser.
2016-09-01 14:21:32 +02:00
wm4 ec3c428e5f stream_cb: remove broken cast
seek_fn is supposed to return the new file offset, or a negative error
code. Our code doesn't use the offset, and only wants to know if any
errors happened. The int cast is completely broken and might treat a
successful seek as failed depending on whether the sign bit will be set.
2016-08-31 22:25:06 +02:00
wm4 e22ae2cba0 m_config: remove an unused function
Well, almost unused.
2016-08-31 22:22:21 +02:00
quilloss aae47146a7 vo: update w32_common left out by 4d75514 2016-08-31 22:19:55 +02:00
wm4 7539928c1c m_config: remove some aliasing checks
We strictly assume no aliasing (the previous commit removed the last
case), so remove the checks.
2016-08-31 22:17:24 +02:00
wm4 c55d859920 m_option: replace --no-video-aspect alias
Instead, add a hacky OPT_ASPECT option type, which only exists to accept
a "no" parameter, which in combination with the "--no-..." handling code
makes --no-video-aspect work again.

We can also remove the code in m_config.c, which only existed to make
"--no-aspect" (a deprecated alias) to work.
2016-08-31 22:17:21 +02:00
wm4 2057209057 m_config: deprecate top-level suboptions
This is a really old weird MPlayer feature. While the MPlayer requires
you to use the sub-option syntax in these cases, mpv "flattens" them to
normal options. The still-supported alternate sub-option syntax remains
a weird artifact that hopefully nobody uses.

For example you can do "-sub-text font=Foo:color=0.5" instead of using
"--sub-text-font=Foo --sub-text-color=0.5". For --sub-text this is an
accidental feature, but it used to be documented for
--demuxer-rawaudio and some others.

This should just be removed, but for now only print a warning to preempt
complaints from weird users wanting this feature back.
2016-08-31 22:16:43 +02:00
wm4 b10dcecf7d client API: deprecate "no-..." option handling
The client API can do this (and there are apparently some libmpv using
projects which rely on this). But it's just unnecessary bloat as it
requires a separate code path from the option parser. It would be better
to remove this code. Formally deprecate it, including API bump and
warning in the API changes file to make it really clear.
2016-08-31 22:16:43 +02:00
wm4 7dde096d8a m_config: introduce and use OPT_ALIAS for some options
OPT_ALIAS redirects the options at a higher level, instead of
introducing "duplicate" options with different name but same backing
storage. This uses the OPT_REPLACED mechanisms - only the deprecation
warning had to be made conditional. Note that e.g. --no-video still
works, because the "--no-..." redirection and OPT_ALIAS are orthogonal.

The deprecated --sub -> --sub-file alias had to be dropped, because it
essentially conflicts with --no-sub. If anyone complains, this could
probably still be undone by letting m_config_find_negation_opt do a
special mapping for --no-sub. (Which would be dumb, but simple and
effective.)
2016-08-31 22:16:19 +02:00
wm4 e024906408 m_config: handle --no-... options differently
Instead of adding "no-"-prefixed aliases to the internal option list,
which will act like normal options, do it in the parsing stage. This
turns out to be simpler (and cheaper), and avoids adding aliased
options.
2016-08-31 16:45:58 +02:00
wm4 ce8dae3f0d m_property: remove pointless explicitly clamping
This is basically dead code, and even the commit that added this code 4
years ago said that this should be for debugging only.

(Though it is possible that the clamp callback was used for something
else, and then unused again. Also, some of the clamping code remains and
is used for internal checking, e.g. clamp_double().)
2016-08-31 15:31:51 +02:00
wm4 f519887fe7 input: use OPT_REPLACED for an old option alias 2016-08-31 14:46:21 +02:00
wm4 7614f2b3a6 vo_xv: remove an aliased option
Trying to get rid of them, and no-colorkey is an instance of it. Kill
it.
2016-08-31 13:38:14 +02:00
wm4 4d75514321 vo: change messy handling of fullscreen and other flags
Before this commit, all VOs had to toggle the option flag themselves,
now command.c does it.

I can't really comprehend why it required every VO to do this manually.
Maybe it was for rejecting the property/option change if the VO didn't
support a specific capability. But then it could have checked the VOCTRL
result. In any case, I don't care, and successfully changing the
property without doing anything (With some VOs) is fine too. Many things
work this way now, and it's simpler overall.

This change will be useful for cleaning up VO option handling.
2016-08-30 23:52:16 +02:00
wm4 af1379c43d options: make mp_vo_opts options an actual sub-option group
Just a minor refactor along the planned option change. This commit will
make it easier to update (i.e. copy) the VO options without copying
_all_ options. For now, behavior should be equivalent, though.

(The VO options were put into a separate struct quite early - when all
global variables were removed from the source code. It wasn't clear
whether the separate struct would have any actual purpose, but it seems
it will now. Awesome, huh.)
2016-08-30 23:50:57 +02:00
wm4 e65a8d7b61 m_config: pass parent option in m_config_add_option()
Instead of just the parent name. This is a minor refactor as preparation
for other things.
2016-08-30 23:48:42 +02:00
wm4 5f88e6a0db m_config: rename is_generated to is_hidden
More appropriate. Originally it really was for automatically added
options, but now it even needed some stupid comments to indicate that
it was used for simply hiding options.
2016-08-30 23:47:09 +02:00
wm4 3bb134969e m_option: remove M_OPT_TYPE_DYNAMIC flag
It's actually redundant with whether m_option_type.free is set. Some
option types were flagged inconsistently. Its only use was for running
an additional sanity check without any real functionality.
2016-08-30 23:45:58 +02:00
wm4 6f6d2eb770 command: cosmetics: fix some minor whitespace mistakes 2016-08-30 23:45:20 +02:00
wm4 f3b3702025 player: make --force-window work with opengl-cb
No reason not to? This probably avoids surprises if someone really tries
to combine them.
2016-08-30 23:44:28 +02:00
wm4 d223959cda player: slightly adjust framerate guessing heuristic
Some files not only use rounded timestamps, but they also do it
incorrectly. They may jitter between up to 4 specific frame durations.
In this case, I found a file that mostly used 41ms and 42ms, but also
had 40ms and 43ms outliers (often but not always following each other).

This breaks the assumption of the framerate estimation code that the
frame duration can deviate up to 1ms. If it jitters around 4 possible
frame durations, the maximum deviation is 3ms. Increase it accordingly.

The change might make playback of "true VFR" video via display-sync mode
worse, but it's not like it was particularly good in the first place.

Also, the check whether to usen the container FPS needs to be stricter.
In the worst case, num_dur is 1, which doesn't really indicate any
evidence that the framerate is correct. Only if there are "enough"
frames the deviation check will become meaningful. 16 is an arbitrary
value that has been designated "enough" by myself.

Also otuput the frame duration values for --dump-stats.
2016-08-29 17:15:06 +02:00
Rostislav Pehlivanov ae3bbc4f63 Merge pull request #3467 from atomnuker/master
wayland: reject resize events with either dimension being 0
2016-08-29 13:40:55 +01:00
Rostislav Pehlivanov cb2cb540f4 wayland: reject resize events with either dimension being 0
Newer versions of mutter/gnome now ask mpv to resize to 0 by 0 pixels.
2016-08-29 13:21:54 +01:00
wm4 3e0d4de988 vo_opengl: explicitly check for GL errors around framebuffer depth check
It seems like many GL implementations (including Mesa) choke on this,
while others are fine. We still think that this use of the GL API is
allowed by the standard (at least in the Mesa case), so to reduce
confusion, explicitly check the "controversial" calls, and use an
appropriate error message.
2016-08-29 14:02:24 +02:00
wm4 251ecf6e4b sd_lavc: always set decoder timebase
Like it's done for audio and video. Just to be uniform.

I'm sorry for deleting the anti-ffmpeg vitriol. It's still all true, but
since we decided to always set the timebase, the crappiness is isolated
to FFmpeg internals.
2016-08-29 13:15:54 +02:00
wm4 edbb8f6286 vd_lavc: always force milliseconds for MMAL
This libavcodec wrapper should rescale the API timestamps to whatever
it internally needs, but it doesn't yet. So restore this code.
2016-08-29 13:15:44 +02:00
wm4 0110b738d5 vd_lavc, ad_lavc: set pkt_timebase, not time_base
These are different AVCodecContext fields. pkt_timebase is the correct
one for identifying the unit of packet/frame timestamps when decoding,
while time_base is for encoding. Some decoders also overwrite the
time_base field with some unrelated codec metadata.

pkt_timebase does not exist in Libav, so an #if is required.
2016-08-29 12:46:12 +02:00
wm4 bda614bfd8 m_config: profile option values can be NULL
Sigh.
2016-08-29 09:30:39 +02:00
wm4 f42e4374d5 command: export profile list as a property
Targeted at scripts, which can do whatever they want with it. This comes
with the promise that they could get randomly broken any time.

See #977.
2016-08-28 19:46:54 +02:00
wm4 a9a55ea7f2 misc: add some annoying mpv_node helpers
Sigh.

Some parts of mpv essentially duplicate this code (with varrying levels
of triviality) - this can be fixed "later".
2016-08-28 19:39:05 +02:00
wm4 5e56c07417 common: add assert.h include
Because why not.
2016-08-28 19:33:04 +02:00
wm4 5086b2d456 player: add option to disable video OSD
Normally, OSD can be disabled with --osd-level=0. But this also disables
terminal OSD, and some users want _only_ the terminal OSD. Add
--video-osd=no, which essentially disables the video OSD.

Ideally, it should probably be possible to control terminal and video
OSD levels independently, but that would require separate OSD timers
(and other state) for both components, so don't do it. But because the
current situation isn't too ideal, add a threat to the manpage that
might be changed in the future.

Fixes #3387.
2016-08-28 18:26:59 +02:00
wm4 7af6e64db7 command: add property for current subtitle text
Requested by someone. Reuses the code for terminal subtitle display.
2016-08-27 21:14:41 +02:00
James Cowgill eed99d3609 player: fix minor spelling mistake in osc.lua
Lintain (https://lintian.debian.org/) complains about this particular spelling
mistake.
2016-08-27 09:02:11 +02:00
wgmk a05f20ea1e TOOLS/zsh.pl: add m4a to zsh completion filetype list 2016-08-26 21:17:24 +02:00
wm4 ed62f56a40 player: avoid some redundant terminal status updates
Run term_osd_update() just once per update, instead of twice (once for
the status line, and once for the terminal OSD messafe).
2016-08-26 20:38:05 +02:00
wm4 37d6604d70 x11, wayland: always round up wait times
If wait_us is >0 and <500, the wait time gets rounded down 0,
effectively turning this into busy waiting. Round it up instead.
2016-08-26 20:22:33 +02:00
wm4 872b7a2654 vo: remove redundant wakeup
Shouldn't matter. Was pointed out by someone. The change should help
avoiding extra unneeded wakeups on the VO thread.
2016-08-26 20:19:39 +02:00
Martin Herkt c226bc7616 Release 0.20.0 2016-08-26 19:40:58 +02:00
Martin Herkt e60a36bd4e Merge branch 'master' into release/current 2016-08-26 19:15:57 +02:00
wm4 bc97d60542 demux: close underlying stream if it's fully read anyway
This is for text subtitles. libavformat currently always reads text
subtitles completely on init. This means the underlying stream is
useless and will consume resources for various reasons (network
connection, file handles, cache memory).

Take care of this by closing the underlying stream if we think the
demuxer has read everything. Since libavformat doesn't export whether it
did (or whether it may access the stream again in the future), we rely
on a whitelist. Also, instead of setting the stream to NULL or so, set
it to an empty dummy stream. This way we don't have to litter the code
with NULL checks.

demux_lavf.c needs extra changes, because it tries to do clever things
for the sake of subtitle charset conversion.

The main reason we keep the demuxer etc. open is because we fell for
libavformat being so generic, and we tried to remove corresponding
special-cases in the higher-level player code. Some of this is forced
due to ass/srt mkv/mp4 demuxing being very similar to external text
files. In the future it might be better to do this in a more
straight-forward way, such as reading text subtitles into libass and
then discarding the demuxer entirely, but for aforementioned reasons
this could be more of a mess than the solution introduced by this
commit.

Probably fixes #3456.
2016-08-26 13:34:52 +02:00
wm4 4121016689 player: don't directly access demuxer->stream
Cleaner and makes it easier to change the underlying stream.

mp_property_stream_capture() still directly accesses it directly via
demux_run_on_thread(). This is evil, but still somewhat sane and is not
getting into the way here.

Not sure if I got all field accesses.
2016-08-26 13:33:38 +02:00
wm4 b636b19058 cache: don't use a backbuffer if the cache is as large as the file
It's just wasted memory.

One corner case is when a file grows during playback, but this is rare
and usually happens on-disk only. The cache size was generally limited
before this change already, so no reason to care.

As an unrelated change, move the cache size info to the resize_cache()
function. There's really no reason not to do this, and it's slightly
more informative if the user changes the cache size at runtime.
2016-08-26 13:33:38 +02:00
wm4 cb9b60ef19 stream_memory: disable stream cache
Obviously makes no sense and just wastes resources.
2016-08-26 13:33:38 +02:00
James Ross-Gowan 31f28da0f3 w32_common: use hooks to detect parent window resize
Because VOCTRL_CHECK_EVENTS is processed asynchronously (as of 088a007,)
the GUI thread no longer gets regular wakeups, so the old check that
made sure the video window matched the parent window's size in --wid
embedding mode did not run very often. This made --wid embedding not
very usable.

Instead of polling for window size changes, use Windows hooks to react
to them when they happen. When the parent window is owned by the same
process as the video window, use a WH_CALLWNDPROC hook. When the parent
window is not owned by the same process, WinEvents must be used, which
are not as smooth, but still work for this purpose.

Since neither SetWindowsHookEx nor SetWinEventHook take a context
parameter to send data to the hook function, the hook functions must
find the child window by its class instead, so there are a few changes
to ensure this is fast and the class is unique.

This also fixes up the logic to handle window destruction. When a parent
window is destroyed, its children are also destroyed, so this gives us a
way to react to parent window destruction without polling.
2016-08-26 20:02:58 +10:00
Avi Halachmi (:avih) ef0b2e33b1 vo_opengl: angle: new opengl flag to control DirectComposition
On some systems DirectComposition might behave poorly. Add an opengl
suboption flag 'dcomposition' (default=yes) which can disable it.
2016-08-25 23:47:37 +10:00
wm4 2a5b61244f x11: work around mutter fullscreen issue
If the video has the same size as the screen, starting with --fs and
then leaving fullscreen doesn't actually leave fullscreen.

The reason is that mpv tries to restore the previous window size if
necessary (otherwise, you'd end up with a Window of nearly the same size
as the screen with some WMs). It will typically restore with the
rectangle set exactly to the screen if no other position or size is
forced. This triggers pre-EWMH fullscreen mode, which WMs detect using
various heuristics.

Apparently we triggered this with mutter (but strangely no other WMs).
It's possible that pre-EWMH fullscreen mode actually requires removing
decorations, and mutter either ignores this. But this is speculation and
I haven't checked.

Work this around by reducing the requested size by 1 pixel if it
happens.

This was observed with mutter 3.18.2.

Fixes #2072.
2016-08-25 14:16:10 +02:00
wm4 c4ba600832 audio: avoid missed wakeups with ab-loops
Could get "stuck".
2016-08-24 12:14:48 +02:00
wm4 c218d9e960 vd_lavc: minor simplification
The timebase is now always valid.
2016-08-23 12:07:46 +02:00
wm4 a47d849df7 ad_lavc: actually tell decoder about the timebase
Essentially forgotten in commit 05e4df3f.
2016-08-23 12:06:47 +02:00
wm4 6980575e15 ao_alsa: log if retrieving supported channel maps fails
It's a sign that the driver doesn't implement the channel map API.
2016-08-22 20:05:34 +02:00
wm4 724f60bf9a audio: do not apply --audio-channels if spdif passthrough is in use
If spdif is enabled, the channel layout has no meaning other than
setting the number of channels. The number of channels must be fixed to
achieve the exact bitrate required.

Fixes #3445.
2016-08-22 12:12:10 +02:00
wm4 74d4073771 demux: demote packet queue overflow to a warning
It doesn't necessarily have to mean anything bad.

We're still too lazy to provide any more detailed information (e.g.
whether this happened to likely bad interleaving, excessive amount of
packets like with some ASS subs, or that the readahead user option is
limitted by the packet queue size).
2016-08-22 12:10:55 +02:00
wm4 93104142f4 player: log if video is considered an image
It's a heristic that can fail, so better log it.
2016-08-21 12:27:48 +02:00
wm4 9a5e062a04 manpage: fix typo 2016-08-20 18:15:24 +02:00
wm4 6b676d82fd vo: be more trusting to estimated display FPS
This should actually be rather safe - we already check whether the
estimated value jitters less than the (possibly untrustworthy) nominal
one. Remove a "safety" check that disabled this code for small
deviations, and make it trigger sooner into playback. Also lower the log
level of messages about using the estimated display FPS down to verbose.

Normally there's another mechanism for smoothing out minor estimation
differences, but that is not good enough here.

This possibly improves behavior as reported in #3433, which can be
reproduced with --vo=null:fps=48.426 --display-fps=48 (though it doesn't
consider the jitter introduced by a real VO).
2016-08-20 18:15:17 +02:00
wm4 af103aebd7 player: update Windows playback state asynchronously
Doing this required synchronizing with the VO thread, which could lead
to audio dropouts if the VO was frozen (which can happen in practice if
e.g. an opengl_cb user is not doing what the API demands).

Add a way to send asynchronous VOCTRLs, and use that for the playback
state. In theory, it would be better to make this status update a
several function and to "merge" several queued update, but that would be
slightly more effort/code, and the update is so infrequent that the
merging would never happen anyway.

The change to vo_destroy() is to make sure all queued asynchronous
reuqests are finished before making the vo_thread exit.

Even though it's only used on MS Windows, it's run on any platform with
any VO, which makes this worse.
2016-08-20 14:46:38 +02:00
wm4 969c011522 ta: add a helper macro 2016-08-20 14:41:12 +02:00
wm4 1a8af89b7d vo: fix mismatching types in pointer operation
run_control() dereferences an uint32_t as int. Whether this is allowed
depends on what uint32_t is typedefed to (dereferencing an unsigned int
as int should be fine). Fix it by always using int. The uint32_t type
never really made sense.
2016-08-20 14:11:35 +02:00
Paul B Mahol e057629493 af_lavrresample: better swr reinitialization 2016-08-20 11:37:06 +02:00
rr- cb31e72589 manpage: info about --panscan vs. --video-unscaled 2016-08-19 22:53:17 +02:00
rr- ed644b0d33 aspect: add --video-unscaled=downscale-big 2016-08-19 22:51:46 +02:00
wm4 23993e91f3 af_lavrresample: fix error if resampler could not be recreated
There are situations where the resampler is destroyed and recreated
during playback. If recreating the resampler unexpectedly fails, the
filter function is supposed to return an error. This wasn't done
correctly, because get_out_samples() accessed the resampler before the
check. Move the check up to fix this.
2016-08-19 22:27:15 +02:00
James Ross-Gowan 68dc869d6a command: prevent O(n^2) behaviour for playlist property
When fetching the playlist property, playlist_entry_from_index would be
called for each playlist entry, which traversed a linked list to get the
entry corresponding to the specified index. This was very slow for large
playlists. Since get_playlist_entry is called for each index in order,
it can avoid a full traversal of the linked list by using the next
pointer on the previously requested entry.
2016-08-20 00:07:32 +10:00
wm4 e5f61c2bd5 vd_lavc: remove unnecessary initialization
This is already the default value.
2016-08-19 15:00:58 +02:00
wm4 2fbd1d3610 demux: change fps field to double
Because why not.
2016-08-19 15:00:58 +02:00
wm4 05e4df3f0c video/audio: always provide "proper" timestamps to libavcodec
Instead of passing through double float timestamps opaquely, pass real
timestamps. Do so by always setting a valid timebase on the
AVCodecContext for audio and video decoding.

Specifically try not to round timestamps to a too coarse timebase, which
could round off small adjustments to timestamps (such as for start time
rebasing or demux_timeline). If the timebase is considered too coarse,
make it finer.

This gets rid of the need to do this specifically for some hardware
decoding wrapper. The old method of passing through double timestamps
was also a bit questionable. While libavcodec is not supposed to
interpret timestamps at all if no timebase is provided, it was
needlessly tricky. Also, it actually does compare them with
AV_NOPTS_VALUE. This change will probably also reduce confusion in the
future.
2016-08-19 14:59:30 +02:00
wm4 4aaa83339c av_common: improve rounding for float->int timestamp conversions 2016-08-19 14:11:32 +02:00
wm4 5d2dfbdfca player: refresh very low framerate video on filter changes
Limit the max. time the refresh is delayed. Make it refresh at all if
image mode is enabled.

Fixes #3435.
2016-08-19 09:38:45 +02:00
wm4 4e3663a2da vf_rotate: allow arbitrary rotation
vf_rotate selects the correct filter for 90° rotation, but it can be
extended to use lavfi's vf_rotate as fallback.

See #3434.
2016-08-19 09:37:52 +02:00
wm4 e6952c7053 github: fix typo 2016-08-18 21:17:25 +02:00
wm4 0f83caf96a github: encourage bug reports
Word this sentence slightly more positively because we are a positive
project.
2016-08-18 21:05:20 +02:00
wm4 1e53fc3a15 demux_lavf: don't report start time for ogg
Better with ogg shoutcast streams. These have PTS resets on each
playlist item, so the PTS would usually reset to some negative value.
2016-08-18 21:03:01 +02:00
wm4 a1dec6f54a player: make looping slightly more seamless
This affects A-B loops and --loop-file, and audio. Instead of dropping
audio by resetting the AO, try to make it seamless by not sending data
after the loop point, and after the seek send new data without a reset.
2016-08-18 20:40:23 +02:00
wm4 bbcd0b6a03 audio: improve aspects of EOF handling
The code actually kept going out of EOF mode into resync mode back into
EOF mode when the playloop had to wait after an audio EOF caused by the
endpts. This would break seamless looping (as added by the next commit).

Apply endpts earlier, to ensure the filter_audio() function always
returns AD_EOF in this case.

The idiotic ao_buffer makes this an amazing pain in the ass.
2016-08-18 20:38:09 +02:00
wm4 7bba97b301 video: don't discard video frames after endpts
Instead of letting it keep decoding by trying to find a new frame,
"plug" the frame queue by not removing it. (Or actually, by putting
it back instead of discarding it.)

Matters for seamless looping (following commits), and possibly some
other corner cases.

The added function vf_unread_output_frame() is a bit of a sin, but still
reasonable, since its implementation is trivial.
2016-08-18 20:37:25 +02:00
wm4 0a0967f48b build: make avutil-mastering-metadata check slightly more robust
Fixes the specific scenario of compiling against a local Libav build,
while the system has FFmpeg installed.
2016-08-18 14:55:43 +02:00
jaseg e02cb674ce manpage: input: fix define-section syntax
Source says "force", manpage said "forced". Now both say "force".
2016-08-17 23:33:20 +02:00
wm4 f5bbb5aed2 player: add option to control duration of image display
The --image-display-duration option controls how long an image is
displayed. It's also possible to display the image forever (until manual
user interaction stops playback).

With this, the core drops the old method to "drain" video (i.e. waiting
for the last frame duration on end of playback). Instead, we reuse
MPContext.time_frame. The old mechanism was disabled for non-images
anyway.

Fixes #3425.
2016-08-17 22:46:48 +02:00
wm4 07f8b64754 m_option: add mechanism to allow inf/-inf float options
Used by the next commit.
2016-08-17 21:48:56 +02:00
wm4 3a7e86ff6e m_option: simplify float value range handling
Use clamp_double() to handle all value restriction/verification. The
error messages become a bit less nice, but they were kind of incomplete
before.
2016-08-17 21:44:05 +02:00
wm4 12e251c29e demux: fix undefined behavior with ogg metadata update
When an ogg track upodates metadata, we have to perform a complicated
runtime update due to the demux.c architecture. A detail was broken and
an array was allocated with the previous number of streams, which
usually led to invalid memory write accesses at least on the first
update.

See github commit comment on commit b9ba9a89.
2016-08-16 10:48:54 +02:00
wm4 814dacdd7d af_lavrresample: work around libswresample misbehavior
The touched code is for seek resets and such - we simply want to reset
the entire resample state. But I noticed after a seek a tiny bit of
audio is missing (mpv's audio sync code inserted silence to compensate).

It turns out swr_drop_output() either does not reset some internal state
as we expect, or it's designed to drop not only buffered samples, but
also future samples.

On the other hand, libavresample's avresample_read(), does not have this
problem. (It is also pretty explicit in what it does - return/skip
buffered data, nothing else.)

Is the libswresample behavior a bug? Or a feature? Does nobody even
know? Who cares - use the hammer to unfuck the situation. Destroy and
deallocate the libswresample context and recreate it. On every seek.
2016-08-16 00:05:34 +02:00
wm4 86fa1e6129 player: allow passing flags to queue_seek()
Change the last parameter from a bool to an int, which is supposed to
take bit-flags. The at this point only flag is MPSEEK_FLAG_DELAY, which
replaces the previous bool parameter. The old false parameter becomes 0,
the old true parameter becomes MPSEEK_FLAG_DELAY.

Since the old "immediate" parameter is now essentially inverted, two
coalesced immediate and delayed seeks end up as delayed instead of
immediate. This change doesn't matter, since there are no relative
immediate seeks anyway.
2016-08-15 21:07:32 +02:00
Martin Herkt 795b65b2ff DOCS: Update version 2016-08-15 16:16:17 +02:00
233 changed files with 9893 additions and 5501 deletions

No files matched your search

+4 -2
View File
@@ -8,12 +8,14 @@ If you're not using git master or the latest release, update.
### Actual behavior
### Log files
### Log file
Make a log file made with -v or --log-file=output.txt, paste it to
http://sprunge.us or a similar site, and replace this text with a link to it.
Do not bother reporting a bug if you do not provide the required information.
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.
### Sample files
+1
View File
@@ -19,6 +19,7 @@
/demux/ebml_types.h
/sub/osd_font.h
/player/lua/*.inc
/player/builtin_conf.inc
/DOCS/man/mpv.1
/DOCS/man/mpv.aux
/DOCS/man/mpv.log
+3
View File
@@ -12,6 +12,8 @@ env:
global:
# Coverity token
- secure: "H21mSRlMhk4BKS0xHZvCFGJxteCP0hRVUxTuNfM2Z9HBsyutuLEYMtViLO86VtM+Tqla3xXPzUdS4ozLwI72Ax/5ZUDXACROj73yW6QhFB5D6rLut12+FjqC7M33Qv2hl0xwgNBmR5dsm1ToP37+Wn+ecJQNvN8fkTXF+HVzOEw="
# Travis token for mpv.io
- secure: "nlTVLJK6kRhtXvhKCoJ3YdFGHuKaq/eHowfPw25hqRWuBOZd+HjHY5KIYjV7SxuKFDpJE4GpNcvA3Q31nsqomxpkLYgrwjg6TSazN7ZP+x85ZgV1QGFebrPfGm2n5UR5CAPAwFoeF3pZheLi4bajVzwq1fWW+x3grS188P9OZso="
compiler:
- clang
- gcc
@@ -42,6 +44,7 @@ script:
- ./bootstrap.py
- ./waf configure
- ./waf build
after_script: TOOLS/travis-rebuild-website
notifications:
email: false
+20 -1
View File
@@ -32,7 +32,26 @@ API changes
::
--- mpv 0.19.0
--- mpv 0.21.0 ---
1.23 - deprecate setting "no-" options via mpv_set_option*(). For example,
instead of "no-video=" you should set "video=no".
- do not override the SIGPIPE signal handler anymore. This was done as
workaround for the FFmpeg TLS code, which has been fixed long ago.
- deprecate mpv_suspend() and mpv_resume(). They will be stubbed out
in mpv 0.22.0.
- make mpv_set_property() work to some degree before mpv_initialize().
It can now be used instead of mpv_set_option().
- semi-deprecate mpv_set_option()/mpv_set_option_string(). You should
use mpv_set_property() instead. There are some deprecated properties
which conflict with some options (see client.h remarks on
mpv_set_option()), for which mpv_set_option() might still be required.
In future mpv releases, the conflicting deprecated options/properties
will be removed, and mpv_set_option() will internally translate API
calls to mpv_set_property().
- qthelper.hpp: deprecate get_property_variant, set_property_variant,
mpv_set_option, command_variant, and replace them with get_property,
set_property, command.
--- mpv 0.19.0 ---
1.22 - add stream_cb API for custom protocols
--- mpv 0.18.1 ---
---- - remove "status" log level from mpv_request_log_messages() docs. This
+3 -3
View File
@@ -104,10 +104,10 @@ Installing MSYS2
It doesn't matter whether the i686 or the x86_64 version is used. Both can
build 32-bit and 64-bit binaries when running on a 64-bit version of Windows.
2. Start a MinGW-w64 shell (``mingw64_shell.bat``). Note that this is different
2. Start a MinGW-w64 shell (``mingw64.exe``). Note that this is different
from the MSYS2 shell that is started from the final installation dialog.
For a 32-bit build, use ``mingw32_shell.bat``.
For a 32-bit build, use ``mingw32.exe``.
Updating MSYS2
--------------
@@ -118,7 +118,7 @@ separately.
```bash
# Check for core updates. If instructed, close the shell window and reopen it
# before continuing.
update-core
pacman -Syu
# Update everything else
pacman -Su
+80
View File
@@ -19,6 +19,86 @@ Interface changes
::
--- mpv 0.21.0 ---
- setting certain options at runtime will now take care of updating them
property (see for example issue #3281). On the other hand, it will also
do runtime verification and reject option changes that do not work
(example: setting the "vf" option to a filter during playback, which fails
to initialize - the option value will remain at its old value). In general,
"set name value" should be mostly equivalent to "set options/name value"
in cases where the "name" property is not deprecated and "options/name"
exists - deviations from this are either bugs, or documented as caveats
in the "Inconsistencies between options and properties" manpage section.
- deprecate _all_ --vo and --ao suboptions. Generally, all suboptions are
replaced by global options, which do exactly the same. For example,
"--vo=opengl:scale=nearest" turns into "--scale=nearest". In some cases,
the global option is prefixed, e.g. "--vo=opengl:pbo" turns into
"--opengl-pbo".
Most of the exact replacements are documented here:
https://github.com/mpv-player/mpv/wiki/Option-replacement-list
- remove --vo=opengl-hq. Set --profile=opengl-hq instead. Note that this
profile does not force the VO. This means if you use the --vo option to
set another VO, it won't work. But this also means it can be used with
opengl-cb.
- remove the --vo=opengl "pre-shaders", "post-shaders" and "scale-shader"
sub-options: they were deprecated in favor of "user-shaders"
- deprecate --vo-defaults (no replacement)
- remove the vo-cmdline command. You can set OpenGL renderer options
directly via properties instead.
- deprecate the device/sink options on all AOs. Use --audio-device instead.
- deprecate "--ao=wasapi:exclusive" and "--ao=coreaudio:exclusive",
use --audio-exclusive instead.
- subtle changes in how "--no-..." options are treated mean that they are
not accessible under "options/..." anymore (instead, these are resolved
at parsing time). This does not affect options which start with "--no-",
but do not use the mechanism for negation options.
(Also see client API change for API version 1.23.)
- rename the following properties
- "demuxer" -> "current-demuxer"
- "fps" -> "container-fps"
- "idle" -> "idle-active"
- "cache" -> "cache-percent"
the old names are deprecated and will change behavior in mpv 0.22.0.
- remove deprecated "hwdec-active" and "hwdec-detected" properties
- deprecate the ao and vo auto-profiles (they never made any sense)
- deprecate "--vo=direct3d_shaders" - use "--vo=direct3d" instead.
Change "--vo=direct3d" to always use shaders by default.
- deprecate --playlist-pos option, renamed to --playlist-start
- deprecate the --chapter option, as it is redundant with --start/--end,
and conflicts with the semantics of the "chapter" property
- rename --sub-text-* to --sub-* and --ass-* to --sub-ass-* (old options
deprecated)
- incompatible change to cdda:// protocol options: the part after cdda://
now always sets the device, not the span or speed to be played. No
separating extra "/" is needed. The hidden --cdda-device options is also
deleted (it was redundant with the documented --cdrom-device).
- deprecate --vo=rpi. It will be removed in mpv 0.22.0. Its functionality
was folded into --vo=opengl, which now uses RPI hardware decoding by
treating it as a hardware overlay (without applying GL filtering). Also
to be changed in 0.22.0: the --fs flag will be reset to "no" by default
(like on the other platforms).
- deprecate --mute=auto (informally has been since 0.18.1)
- deprecate "resume" and "suspend" IPC commands. They will be completely
removed in 0.22.0.
- deprecate mp.suspend(), mp.resume(), mp.resume_all() Lua scripting
commands, as well as setting mp.use_suspend. They will be completely
removed in 0.22.0.
- the "seek" command's absolute seek mode will now interpret negative
seek times as relative from the end of the file (and clamps seeks that
still go before 0)
- add almost all options to the property list, meaning you can change
options without adding "options/" to the property name (a new section
has been added to the manpage describing some conflicting behavior
between options and properties)
- implement changing sub-speed during playback
- make many previously fixed options changeable at runtime (for example
--terminal, --osc, --ytdl, can all be enable/disabled after
mpv_initialize() - this can be extended to other still fixed options
on user requests)
--- mpv 0.20.0 ---
- add --image-display-duration option - this also means that image duration
is not influenced by --mf-fps anymore in the general case (this is an
incompatible change)
--- mpv 0.19.0 ---
- deprecate "balance" option/property (no replacement)
--- mpv 0.18.1 ---
-14
View File
@@ -1,14 +0,0 @@
Client API (libmpv) documentation and examples
==============================================
libmpv lets you embed mpv as a library. It is meant to enable development of
GUI frontends.
Since libmpv merely allows access to underlying mechanisms that can control
mpv, documentation is spread over a few places:
- https://github.com/mpv-player/mpv/blob/master/libmpv/client.h
- http://mpv.io/manual/master/#options
- http://mpv.io/manual/master/#list-of-input-commands
- http://mpv.io/manual/master/#properties
- https://github.com/mpv-player/mpv-examples/tree/master/libmpv
+20 -6
View File
@@ -312,6 +312,13 @@ Available filters are:
``mpv '--af=format=channels=5.1' '--audio-channels=5.1'`` would always force
remixing audio to 5.1 and output it like this.
This filter supports the following ``af-command`` commands:
``set-matrix``
Set the ``<matrix>`` argument dynamically. This can be used to change
the mixing matrix at runtime, without reinitializing the entire filter
chain.
``drc[=method:target]``
Applies dynamic range compression. This maximizes the volume by compressing
the audio signal's dynamic range. (Formerly called ``volnorm``.)
@@ -394,10 +401,6 @@ Available filters are:
``mpv --af=scaletempo=stride=30:overlap=.50:search=10 media.ogg``
Would tweak the quality and performance parameters.
``mpv --af=format=float,scaletempo media.ogg``
Would make scaletempo use float code. Maybe faster on some
platforms.
``mpv --af=scaletempo=scale=1.2:speed=pitch audio.ogg``
Would play media at 1.2x normal speed, with audio at normal pitch.
Changing playback speed would change pitch, leaving audio tempo at
@@ -406,9 +409,13 @@ Available filters are:
``rubberband``
High quality pitch correction with librubberband. This can be used in place
of ``scaletempo``, and will be used to adjust audio pitch when playing
at speed different from normal.
at speed different from normal. It can also be used to adjust audio pitch
without changing playback speed.
This filter has a number of sub-options. You can list them with
``<pitch-scale>``
Sets the pitch scaling factor. Frequencies are multiplied by this value.
This filter has a number of additional sub-options. You can list them with
``mpv --af=rubberband=help``. This will also show the default values
for each option. The options are not documented here, because they are
merely passed to librubberband. Look at the librubberband documentation
@@ -417,6 +424,13 @@ Available filters are:
(The mapping of the mpv rubberband filter sub-option names and values to
those of librubberband follows a simple pattern: ``"Option" + Name + Value``.)
This filter supports the following ``af-command`` commands:
``set-pitch``
Set the ``<pitch-scale>`` argument dynamically. This can be used to
change the playback pitch at runtime. Note that speed is controlled
using the standard ``speed`` property, not ``af-command``.
``lavfi=graph``
Filter audio using FFmpeg's libavfilter.
+74 -117
View File
@@ -4,18 +4,17 @@ AUDIO OUTPUT DRIVERS
Audio output drivers are interfaces to different audio output facilities. The
syntax is:
``--ao=<driver1[:suboption1[=value]:...],driver2,...[,]>``
``--ao=<driver1,driver2,...[,]>``
Specify a priority list of audio output drivers to be used.
If the list has a trailing ',', mpv will fall back on drivers not contained
in the list. Suboptions are optional and can mostly be omitted.
You can also set defaults for each driver. The defaults are applied before the
normal driver parameters.
in the list.
``--ao-defaults=<driver1[:parameter1:parameter2:...],driver2,...>``
Set defaults for each driver.
Deprecated. No replacement.
.. note::
See ``--ao=help`` for a list of compiled-in audio output drivers. The
@@ -23,87 +22,19 @@ normal driver parameters.
where PulseAudio is used. On BSD systems, ``--ao=oss`` or ``--ao=sndio``
may work (the latter being experimental).
.. admonition:: Examples
- ``--ao=alsa,oss,`` Try the ALSA driver, then the OSS driver, then others.
- ``--ao=alsa:resample=yes:device=[plughw:0,3]`` Lets ALSA resample and
sets the device-name as first card, fourth device.
Available audio output drivers are:
``alsa`` (Linux only)
ALSA audio output driver
``device=<device>``
Sets the device name. For ac3 output via S/PDIF, use an "iec958" or
"spdif" device, unless you really know how to set it correctly.
``resample=yes``
Enable ALSA resampling plugin. (This is disabled by default, because
some drivers report incorrect audio delay in some cases.)
``mixer-device=<device>``
Set the mixer device used with ``--no-softvol`` (default: ``default``).
``mixer-name=<name>``
Set the name of the mixer element (default: ``Master``). This is for
example ``PCM`` or ``Master``.
``mixer-index=<number>``
Set the index of the mixer channel (default: 0). Consider the output of
"``amixer scontrols``", then the index is the number that follows the
name of the element.
``non-interleaved``
Allow output of non-interleaved formats (if the audio decoder uses
this format). Currently disabled by default, because some popular
ALSA plugins are utterly broken with non-interleaved formats.
``ignore-chmap``
Don't read or set the channel map of the ALSA device - only request the
required number of channels, and then pass the audio as-is to it. This
option most likely should not be used. It can be useful for debugging,
or for static setups with a specially engineered ALSA configuration (in
this case you should always force the same layout with ``--audio-channels``,
or it will work only for files which use the layout implicit to your
ALSA device).
.. note::
MPlayer and mplayer2 required you to replace any ',' with '.' and
any ':' with '=' in the ALSA device name. mpv does not do this anymore.
Instead, quote the device name:
``--ao=alsa:device=[plug:surround50]``
Note that the ``[`` and ``]`` simply quote the device name. With some
shells (like zsh), you have to quote the option string to prevent the
shell from interpreting the brackets instead of passing them to mpv.
Actually, you should use the ``--audio-device`` option, instead of
setting the device directly.
See `ALSA audio output options`_ for options specific to this AO.
.. warning::
Handling of multichannel/surround audio changed in mpv 0.8.0 from the
behavior in MPlayer/mplayer2 and older versions of mpv.
The old behavior is that the player always downmixed to stereo by
default. The ``--audio-channels`` (or ``--channels`` before that) option
had to be set to get multichannel audio. Then playing stereo would
use the ``default`` device (which typically allows multiple programs
to play audio at the same time via dmix), while playing anything with
more channels would open one of the hardware devices, e.g. via the
``surround51`` alias (typically with exclusive access). Whether the
player would use exclusive access or not would depend on the file
being played.
The new behavior since mpv 0.8.0 always enables multichannel audio,
i.e. ``--audio-channels=auto`` is the default. However, since ALSA
provides no good way to play multichannel audio in a non-exclusive
way (without blocking other applications from using audio), the player
is restricted to the capabilities of the ``default`` device by default,
which means it supports only stereo and mono (at least with current
typical ALSA configurations). But if a hardware device is selected,
then multichannel audio will typically work.
The short story is: if you want multichannel audio with ALSA, use
``--audio-device`` to select the device (use ``--audio-device=help``
to get a list of all devices and their mpv name).
To get multichannel/surround audio, use ``--audio-channels=auto``. The
default for this option is ``auto-safe``, which makes this audio otuput
explicitly reject multichannel output, as there is no way to detect
whether a certain channel layout is actually supported.
You can also try `using the upmix plugin <http://git.io/vfuAy>`_.
This setup enables multichannel audio on the ``default`` device
@@ -113,31 +44,36 @@ Available audio output drivers are:
``oss``
OSS audio output driver
``<dsp-device>``
The following global options are supported by this audio output:
``--oss-device``
Sets the audio output device (default: ``/dev/dsp``).
``<mixer-device>``
Deprecated, use ``--audio-device``.
``--oss-mixer-device``
Sets the audio mixer device (default: ``/dev/mixer``).
``<mixer-channel>``
``--oss-mixer-channel``
Sets the audio mixer channel (default: ``pcm``). Other valid values
include **vol, pcm, line**. For a complete list of options look for
``SOUND_DEVICE_NAMES`` in ``/usr/include/linux/soundcard.h``.
``jack``
JACK (Jack Audio Connection Kit) audio output driver
JACK (Jack Audio Connection Kit) audio output driver.
``port=<name>``
The following global options are supported by this audio output:
``--jack-port=<name>``
Connects to the ports with the given name (default: physical ports).
``name=<client>``
``--jack-name=<client>``
Client name that is passed to JACK (default: ``mpv``). Useful
if you want to have certain connections established automatically.
``(no-)autostart``
``--jack-autostart=<yes|no>``
Automatically start jackd if necessary (default: disabled). Note that
this tends to be unreliable and will flood stdout with server messages.
``(no-)connect``
``--jack-connect=<yes|no>``
Automatically create connections to output ports (default: enabled).
When enabled, the maximum number of output channels will be limited to
the number of available output ports.
``std-channel-layout=waveext|any``
``--jack-std-channel-layout=<waveext|any>``
Select the standard channel layout (default: waveext). JACK itself has no
notion of channel layouts (i.e. assigning which speaker a given
channel is supposed to map to) - it just takes whatever the application
@@ -157,7 +93,9 @@ Available audio output drivers are:
Automatically redirects to ``coreaudio_exclusive`` when playing compressed
formats.
``change-physical-format=<yes|no>``
The following global options are supported by this audio output:
``--coreaudio-change-physical-format=<yes|no>``
Change the physical format to one similar to the requested audio format
(default: no). This has the advantage that multichannel audio output
will actually work. The disadvantage is that it will change the
@@ -165,11 +103,13 @@ Available audio output drivers are:
setting in the ``Audio Devices`` dialog in the ``Audio MIDI Setup``
utility. Note that this does not affect the selected speaker setup.
``exclusive``
``--coreaudio-exclusive``
Deprecated, use ``--audio-exclusive``.
Use exclusive mode access. This merely redirects to
``coreaudio_exclusive``, but should be preferred over using that AO
directly.
``coreaudio_exclusive`` (Mac OS X only)
Native Mac OS X audio output driver using direct device access and
exclusive mode (bypasses the sound server).
@@ -183,18 +123,21 @@ Available audio output drivers are:
``pulse``
PulseAudio audio output driver
``[<host>][:<output sink>]``
The following global options are supported by this audio output:
``--pulse-host=<host>``, ``--pulse-sink=<sink>``
Specify the host and optionally output sink to use. An empty <host>
string uses a local connection, "localhost" uses network transfer
(most likely not what you want).
Deprecated, use ``--audio-device``.
``buffer=<1-2000|native>``
``--pulse-buffer=<1-2000|native>``
Set the audio buffer size in milliseconds. A higher value buffers
more data, and has a lower probability of buffer underruns. A smaller
value makes the audio stream react faster, e.g. to playback speed
changes. Default: 250.
``latency-hacks=<yes|no>``
``--pulse-latency-hacks=<yes|no>``
Enable hacks to workaround PulseAudio timing bugs (default: no). If
enabled, mpv will do elaborate latency calculations on its own. If
disabled, it will use PulseAudio automatically updated timing
@@ -214,61 +157,67 @@ Available audio output drivers are:
environments, such as systems where none of the other drivers
are available.
``buflen=<length>``
The following global options are supported by this audio output:
``--sdl-buflen=<length>``
Sets the audio buffer length in seconds. Is used only as a hint by the
sound system. Playing a file with ``-v`` will show the requested and
obtained exact buffer size. A value of 0 selects the sound system
default.
``bufcnt=<count>``
``--sdl-bufcnt=<count>``
Sets the number of extra audio buffers in mpv. Usually needs not be
changed.
``null``
Produces no audio output but maintains video playback speed. Use
``--ao=null:untimed`` for benchmarking.
Produces no audio output but maintains video playback speed. You can use
``--ao=null --ao-null-untimed`` for benchmarking.
``untimed``
The following global options are supported by this audio output:
``--ao-null-untimed``
Do not simulate timing of a perfect audio device. This means audio
decoding will go as fast as possible, instead of timing it to the
system clock.
``buffer``
``--ao-null-buffer``
Simulated buffer length in seconds.
``outburst``
``--ao-null-outburst``
Simulated chunk size in samples.
``speed``
``--ao-null-speed``
Simulated audio playback speed as a multiplier. Usually, a real audio
device will not go exactly as fast as the system clock. It will deviate
just a little, and this option helps to simulate this.
``latency``
``--ao-null-latency``
Simulated device latency. This is additional to EOF.
``broken-eof``
``--ao-null-broken-eof``
Simulate broken audio drivers, which always add the fixed device
latency to the reported audio playback position.
``broken-delay``
``--ao-null-broken-delay``
Simulate broken audio drivers, which don't report latency correctly.
``channel-layouts``
``--ao-null-channel-layouts``
If not empty, this is a ``,`` separated list of channel layouts the
AO allows. This can be used to test channel layout selection.
``pcm``
Raw PCM/WAVE file writer audio output
``(no-)waveheader``
The following global options are supported by this audio output:
``--ao-pcm-waveheader=<yes|no>``
Include or do not include the WAVE header (default: included). When
not included, raw PCM will be generated.
``file=<filename>``
``--ao-pcm-file=<filename>``
Write the sound to ``<filename>`` instead of the default
``audiodump.wav``. If ``no-waveheader`` is specified, the default is
``audiodump.pcm``.
``(no-)append``
``--ao-pcm-append=<yes|no>``
Append to the file, instead of overwriting it. Always use this with the
``no-waveheader`` option - with ``waveheader`` it's broken, because
it will write a WAVE header every time the file is opened.
@@ -280,14 +229,19 @@ Available audio output drivers are:
confused with RoarAudio, which is something completely
different.
``host=<name/path>``
The following global options are supported by this audio output:
``--rsound-host=<name/path>``
Set the address of the server (default: localhost). Can be either a
network hostname for TCP connections or a Unix domain socket path
starting with '/'.
``port=<number>``
``--rsound-port=<number>``
Set the TCP port used for connecting to the server (default: 12345).
Not used if connecting to a Unix domain socket.
These options are deprecated. If anyone cares enough, their functionality
can be added back using ``--audio-device``.
``sndio``
Audio output to the OpenBSD sndio sound system
@@ -296,16 +250,24 @@ Available audio output drivers are:
(Note: only supports mono, stereo, 4.0, 5.1 and 7.1 channel
layouts.)
``device=<device>``
The following global options are supported by this audio output:
``--ao-sndio-device=<device>``
sndio device to use (default: ``$AUDIODEVICE``, resp. ``snd0``).
Deprecated, use ``--audio-device``.
``wasapi``
Audio output to the Windows Audio Session API.
``exclusive``
The following global options are supported by this audio output:
``--ao-wasapi-exclusive``
Deprecated, use ``--audio-exclusive``.
Requests exclusive, direct hardware access. By definition prevents
sound playback of any other program until mpv exits.
``device=<id>``
``--ao-wasapi-device=<id>``
Deprecated, use ``--audio-device``.
Uses the requested endpoint instead of the system's default audio
endpoint. Both an ordinal number (0,1,2,...) and the GUID
String are valid; the GUID string is guaranteed to not change
@@ -313,8 +275,3 @@ Available audio output drivers are:
Also supports searching active devices by human-readable name. If more
than one device matches the name, refuses loading it.
This option is mostly deprecated in favour of the more general
``--audio-device`` option. That said, ``--audio-device=help`` will give
a list of valid device GUIDs (prefixed with ``wasapi/``), as well as
their human readable names, which should work here.
+6 -1
View File
@@ -8,6 +8,11 @@ There is no real changelog, but you can look at the following things:
https://github.com/mpv-player/mpv/releases
* The git log, which is the "real" changelog
* The files ``client-api-changes.rst`` and ``interface-changes.rst`` in the
``DOCS`` sub directoryon the git repository, which document API and user
interface changes (the latter usually documents breaking changes only, rather
than additions).
* The file ``mplayer-changes.rst`` in the ``DOCS`` sub directory on the git
repository, which used to be in place of this section. It documents some
changes that happened since mplayer2 forked off MPlayer.
changes that happened since mplayer2 forked off MPlayer. (Not updated
anymore.)
+138 -191
View File
@@ -95,7 +95,7 @@ List of Input Commands
relative (default)
Seek relative to current position (a negative value seeks backwards).
absolute
Seek to a given time.
Seek to a given time (a negative value starts from the end of the file).
absolute-percent
Seek to a given percent position.
relative-percent
@@ -526,7 +526,7 @@ Input Commands that are Possibly Subject to Change
``disable-section "<section>"``
Disable the named input section. Undoes ``enable-section``.
``define-section "<section>" "<contents>" [default|forced]``
``define-section "<section>" "<contents>" [default|force]``
Create a named input section, or replace the contents of an already existing
input section. The ``contents`` parameter uses the same syntax as the
``input.conf`` file (except that using the section syntax in it is not
@@ -544,7 +544,7 @@ Input Commands that are Possibly Subject to Change
<default> (also used if parameter omitted)
Use a key binding defined by this section only if the user hasn't
already bound this key to a command.
<forced>
<force>
Always bind a key. (The input section that was made active most recently
wins if there are ambiguities.)
@@ -665,13 +665,6 @@ Input Commands that are Possibly Subject to Change
(the ``ab-loop-a`` property); the second the ``B`` point, and the third
will clear both points.
``vo-cmdline "<args>"``
Reset the sub-option of the current VO. Currently works with ``opengl``
(including ``opengl-hq``). The argument is the sub-option string usually
passed to the VO on the command line. Not all sub-options can be set, but
those which can will be reset even if they don't appear in the argument.
This command might be changed or removed in the future.
``drop-buffers``
Drop audio/video/demuxer buffers, and restart from fresh. Might help with
unseekable streams that are going out of sync.
@@ -698,6 +691,17 @@ Input Commands that are Possibly Subject to Change
``af-command "<label>" "<cmd>" "<args>"``
Same as ``vf-command``, but for audio filters.
``apply-profile "<name>"``
Apply the contents of a named profile. This is like using ``profile=name``
in a config file, except you can map it to a key binding to change it at
runtime.
There is no such thing as "unapplying" a profile - applying a profile
merely sets all option values listed within the profile.
``load-script "<path>"``
Load a script, similar to the ``--script`` option.
Undocumented commands: ``tv-last-channel`` (TV/DVB only),
``ao-reload`` (experimental/internal).
@@ -838,20 +842,12 @@ an option at runtime.
Property list
-------------
``osd-level`` (RW)
See ``--osd-level``.
.. note::
``osd-scale`` (RW)
OSD font size multiplier, see ``--osd-scale``.
``loop`` (RW)
See ``--loop``.
``loop-file`` (RW)
See ``--loop-file`` (uses ``yes``/``no``).
``speed`` (RW)
See ``--speed``.
Most options can be set as runtime via properties as well. Just remove the
leading ``--`` from the option name. These are not documented. Only
properties which do not exist as option with the same name, or which have
very different behavior from the options are documented below.
``audio-speed-correction``, ``video-speed-correction``
Factor multiplied with ``speed`` at which the player attempts to play the
@@ -911,9 +907,11 @@ Property list
list of format names, e.g. mp4 is ``mov,mp4,m4a,3gp,3g2,mj2`` (the list
may grow in the future for any format).
``demuxer``
``current-demuxer``
Name of the current demuxer. (This is useless.)
(Renamed from ``demuxer``.)
``stream-path``
Filename (full path) of the stream layer filename. (This is probably
useless. It looks like this can be different from ``path`` only when
@@ -989,6 +987,12 @@ Property list
Remaining length of the file in seconds. Note that the file duration is not
always exactly known, so this is an estimate.
``audio-pts`` (R)
Current audio playback position in current file in seconds. Unlike time-pos,
this updates more often than once per frame. For audio-only files, it is
mostly equivalent to time-pos, while for video-only files this property is
not available.
``playtime-remaining``
``time-remaining`` scaled by the current ``speed``.
@@ -1078,10 +1082,6 @@ Property list
"title" MPV_FORMAT_STRING
"default" MPV_FORMAT_FLAG
``ab-loop-a``, ``ab-loop-b`` (RW)
Set/get A-B loop points. See corresponding options and ``ab-loop`` command
for details.
``angle`` (RW)
Current DVD angle.
@@ -1154,13 +1154,12 @@ Property list
``af-metadata/<filter-label>``
Equivalent to ``vf-metadata/<filter-label>``, but for audio filters.
``pause`` (RW)
Pause status. This is usually ``yes`` or ``no``. See ``--pause``.
``idle``
``idle-active``
Return ``yes`` if no file is loaded, but the player is staying around
because of the ``--idle`` option.
(Renamed from ``idle``.)
``core-idle``
Return ``yes`` if the playback core is paused, otherwise ``no``. This can
be different ``pause`` in special situations, such as when the player
@@ -1236,25 +1235,12 @@ Property list
is loaded, or when switching ordered chapter segments. This is because
the same underlying code is used for seeking and resyncing.)
``hr-seek`` (RW)
See ``--hr-seek``.
``mixer-active``
Return ``yes`` if the audio mixer is active, ``no`` otherwise.
This option is relatively useless. Before mpv 0.18.1, it could be used to
infer behavior of the ``volume`` property.
``volume`` (RW)
Current volume (see ``--volume`` for details).
``volume-max`` (RW)
Current maximum value the volume property can be set to. (Equivalent to the
``--volume-max`` option.)
``mute`` (RW)
Current mute status (``yes``/``no``).
``ao-volume`` (RW)
System volume. This property is available only if mpv audio output is
currently active, and only if the underlying implementation supports volume
@@ -1266,9 +1252,6 @@ Property list
Similar to ``ao-volume``, but controls the mute state. May be unimplemented
even if ``ao-volume`` works.
``audio-delay`` (RW)
See ``--audio-delay``.
``audio-codec``
Audio codec selected for decoding.
@@ -1316,28 +1299,6 @@ Property list
Same as ``audio-params``, but the format of the data written to the audio
API.
``aid`` (RW)
Current audio track (similar to ``--aid``).
``audio`` (RW)
Alias for ``aid``.
``balance`` (RW)
Audio channel balance. (The implementation of this feature is rather odd.
It doesn't change the volumes of each channel, but instead sets up a pan
matrix to mix the left and right channels.)
Deprecated.
``fullscreen`` (RW)
See ``--fullscreen``.
``deinterlace`` (RW)
See ``--deinterlace``.
``field-dominance`` (RW)
See ``--field-dominance``
``colormatrix`` (R)
Redirects to ``video-params/colormatrix``. This parameter (as well as
similar ones) can be overridden with the ``format`` video filter.
@@ -1345,42 +1306,9 @@ Property list
``colormatrix-input-range`` (R)
See ``colormatrix``.
``video-output-levels`` (RW)
See ``--video-output-levels``,
``colormatrix-primaries`` (R)
See ``colormatrix``.
``taskbar-progress`` (RW)
See ``--taskbar-progress``.
``ontop`` (RW)
See ``--ontop``.
``border`` (RW)
See ``--border``.
``on-all-workspaces`` (RW)
See ``--on-all-workspaces``. Unsetting may not work on all WMs.
``framedrop`` (RW)
See ``--framedrop``.
``gamma`` (RW)
See ``--gamma``.
``brightness`` (RW)
See ``--brightness``.
``contrast`` (RW)
See ``--contrast``.
``saturation`` (RW)
See ``--saturation``.
``hue`` (RW)
See ``--hue``.
``hwdec`` (RW)
Reflects the ``--hwdec`` option.
@@ -1413,27 +1341,6 @@ Property list
multiple interop drivers for the same hardware decoder, depending on
platform and VO.
``hwdec-active``
Deprecated. To be removed in mpv 0.20.0. Use ``hwdec-current`` instead.
Return ``yes`` or ``no``, depending on whether any type of hardware decoding
is actually in use.
``hwdec-detected``
Deprecated. To be removed in mpv 0.20.0.
If hardware decoding is active, this returns the hardware decoder in use.
Otherwise, it returns either ``no``, or if applicable, the currently loaded
hardware decoding API. This is known only once the VO has opened (and
possibly later). With some VOs (like ``opengl``), this is never known in
advance, but only when the decoder attempted to create the hw decoder
successfully. Also, hw decoders with ``-copy`` suffix will return ``no``
while no video is being decoded. All this reflects how detecting hw decoders
are detected and used internally in mpv.
``panscan`` (RW)
See ``--panscan``.
``video-format``
Video format as string.
@@ -1534,6 +1441,9 @@ Property list
These have the same values as ``video-out-params/dw`` and
``video-out-params/dh``.
``video-dec-params``
Exactly like ``video-params``, but no overrides applied.
``video-out-params``
Same as ``video-params``, but after video filters have been applied. If
there are no video filters in use, this will contain the same values as
@@ -1556,10 +1466,12 @@ Property list
``video-frame-info/tff``
``video-frame-info/repeat``
``fps``
``container-fps``
Container FPS. This can easily contain bogus values. For videos that use
modern container formats or video codecs, this will often be incorrect.
(Renamed from ``fps``.)
``estimated-vf-fps``
Estimated/measured FPS of the video filter chain output. (If no filters
are used, this corresponds to decoder output.) This uses the average of
@@ -1580,7 +1492,10 @@ Property list
``display-names``
Names of the displays that the mpv window covers. On X11, these
are the xrandr names (LVDS1, HDMI1, DP1, VGA1, etc.).
are the xrandr names (LVDS1, HDMI1, DP1, VGA1, etc.). On Windows, these
are the GDI names (\\.\DISPLAY1, \\.\DISPLAY2, etc.) and the first display
in the list will be the one that Windows considers associated with the
window (as determined by the MonitorFromWindow API.)
``display-fps`` (RW)
The refresh rate of the current display. Currently, this is the lowest FPS
@@ -1600,6 +1515,9 @@ Property list
``video-aspect`` (RW)
Video aspect, see ``--video-aspect``.
If video is active, this reports the effective aspect value, instead of
the value of the ``--video-aspect`` option.
``osd-width``, ``osd-height``
Last known OSD width (can be 0). This is needed if you want to use the
``overlay-add`` command. It gives you the actual OSD size, which can be
@@ -1608,71 +1526,24 @@ Property list
``osd-par``
Last known OSD display pixel aspect (can be 0).
``vid`` (RW)
Current video track (similar to ``--vid``).
``video`` (RW)
Alias for ``vid``.
``video-align-x``, ``video-align-y`` (RW)
See ``--video-align-x`` and ``--video-align-y``.
``video-pan-x``, ``video-pan-y`` (RW)
See ``--video-pan-x`` and ``--video-pan-y``.
``video-zoom`` (RW)
See ``--video-zoom``.
``video-unscaled`` (W)
See ``--video-unscaled``.
``program`` (W)
Switch TS program (write-only).
``dvb-channel`` (W)
Pair of integers: card,channel of current DVB stream.
Can be switched to switch to another channel on the same card.
Can be switched to switch to another channel on the same card.
``dvb-channel-name`` (RW)
Name of current DVB program.
On write, a channel-switch to the named channel on the same
card is performed. Can also be used for channel switching.
card is performed. Can also be used for channel switching.
``sid`` (RW)
Current subtitle track (similar to ``--sid``).
``sub-text``
Return the current subtitle text. Formatting is stripped. If a subtitle
is selected, but no text is currently visible, or the subtitle is not
text-based (i.e. DVD/BD subtitles), an empty string is returned.
``secondary-sid`` (RW)
Secondary subtitle track (see ``--secondary-sid``).
``sub`` (RW)
Alias for ``sid``.
``sub-delay`` (RW)
See ``--sub-delay``.
``sub-pos`` (RW)
See ``--sub-pos``.
``sub-visibility`` (RW)
See ``--sub-visibility``.
``sub-forced-only`` (RW)
See ``--sub-forced-only``.
``sub-scale`` (RW)
Subtitle font size multiplier.
``ass-force-margins`` (RW)
See ``--ass-force-margins``.
``sub-use-margins`` (RW)
See ``--sub-use-margins``.
``ass-vsfilter-aspect-compat`` (RW)
See ``--ass-vsfilter-aspect-compat``.
``ass-style-override`` (RW)
See ``--ass-style-override``.
This property is experimental and might be removed in the future.
``stream-capture`` (RW)
A filename, see ``--stream-capture``. Setting this will start capture using
@@ -1884,11 +1755,8 @@ Property list
"title" MPV_FORMAT_STRING
"time" MPV_FORMAT_DOUBLE
``af`` (RW)
See ``--af`` and the ``af`` command.
``vf`` (RW)
See ``--vf`` and the ``vf`` command.
``af``, ``vf`` (RW)
See ``--vf``/``--af`` and the ``vf``/``af`` command.
When querying the property with the client API using ``MPV_FORMAT_NODE``,
or with Lua ``mp.get_property_native``, this will return a mpv_node with
@@ -1906,12 +1774,6 @@ Property list
It's also possible to write the property using this format.
``video-rotate`` (RW)
See ``--video-rotate`` option.
``video-stereo-mode`` (RW)
See ``--video-stereo-mode`` option.
``seekable``
Return whether it's generally possible to seek in the current file.
@@ -2151,6 +2013,10 @@ Property list
require reloading the file for changes to take effect. If there is an
equivalent property, prefer setting the property instead.
There shouldn't be any reason to access ``options/<name>`` instead of
``<name>``, except in situations in which the properties have different
behavior or conflicting semantics.
``file-local-options/<name>``
Similar to ``options/<name>``, but when setting an option through this
property, the option is reset to its old value once the current file has
@@ -2204,6 +2070,87 @@ Property list
``property-list``
Return the list of top-level properties.
``profile-list``
Return the list of profiles and their contents. This is highly
implementation-specific, and may change any time. Currently, it returns
an array of options for each profile. Each option has a name and a value,
with the value currently always being a string. Note that the options array
is not a map, as order matters and duplicate entries are possible. Recursive
profiles are not expanded, and show up as special ``profile`` options.
Inconsistencies between options and properties
----------------------------------------------
You can access (almost) all options as properties, though there are some
caveats with some properties (due to historical reasons):
``vid``, ``aid``, ``sid``
While playback is active, you can set existing tracks only. (The option
allows setting any track ID, and which tracks to enable is chosen at
loading time.)
Option changes at runtime are affected by this as well.
``deinterlace``
While video is active, this behaves differently from the option. It will
never return the ``auto`` value (but the state as observed by the video
chain). If you set ``auto``, the property will set this as the option value,
and will return the actual video chain state as observed instead of auto.
``video-aspect``
While video is active, always returns the effective aspect ratio. Setting
a special value (like ``no``, values ``<= 0``) will make the property
set this as option, and return whatever actual aspect was derived from the
option setting.
``brightness`` (and other color options)
If ``--vo=xv`` is used, these properties may return the adapter's current
values instead of the option values.
``display-fps``
If a VO is created, this will return either the actual display FPS, or
an invalid value, instead of the option value.
``vf``, ``af``
If you set the properties during playback, and the filter chain fails to
reinitialize, the new value will be rejected. Setting the option or
setting the property outside of playback will always succeed/fail in the
same way. Also, there are no ``vf-add`` etc. properties, but you can use
the ``vf``/``af`` group of commands to achieve the same.
Option changes at runtime are affected by this as well.
``edition``
While a file is loaded, the property will always return the effective
edition, and setting the ``auto`` value will show somewhat strange behavior
(the property eventually switching to whatever is the default edition).
``playlist``
The property is read-only and returns the current internal playlist. The
option is for loading playlist during command line parsing. For client API
uses, you should use the ``loadlist`` command instead.
``window-scale``
Might verify the set value when setting while a window is created.
``audio-file``, ``sub-file``, ``external-file``
These options/properties are actually lists of filenames. To make the
command-line interface easier, each ``--audio-file=...`` option appends
the full string to the internal list. However, when used as properties,
every time you set the property as a string the internal list will be
replaced with a single entry containing the string you set. ``,`` or other
separators are never used. You have to use ``MPV_FORMAT_NODE_ARRAY`` (or
corresponding API, e.g. ``mp.set_property_native()`` with a table in Lua)
to set multiple entries.
Strictly speaking, option access via API (e.g. ``mpv_set_option_string()``)
has the same problem, and it's only a difference between CLI/API.
``demuxer``, ``idle``, ``length``, ``audio-samplerate``, ``audio-channels``, ``audio-format``, ``fps``, ``cache``, ``playlist-pos``, ``chapter``
These behave completely different as property, but are deprecated (newer
aliases which don't conflict have been added). After the deprecation period
they will be changed to the proper option behavior.
Property Expansion
------------------
+4
View File
@@ -242,12 +242,16 @@ extra commands can also be used as part of the protocol:
command.
``suspend``
Deprecated, will be removed completely in 0.21.0.
Suspend the mpv main loop. There is a long-winded explanation of this in
the C API function ``mpv_suspend()``. In short, this prevents the player
from displaying the next video frame, so that you don't get blocked when
trying to access the player.
``resume``
Deprecated, will be removed completely in 0.21.0.
Undo one ``suspend`` call. ``suspend`` increments an internal counter, and
``resume`` decrements it. When 0 is reached, the player is actually resumed.
+16
View File
@@ -0,0 +1,16 @@
EMBEDDING INTO OTHER PROGRAMS (LIBMPV)
======================================
mpv can be embedded into other programs as video/audio playback backend. The
recommended way to do so is using libmpv. See ``libmpv/client.h`` in the mpv
source code repository. This provides a C API. Bindings for other languages
might be available (see wiki).
Since libmpv merely allows access to underlying mechanisms that can control
mpv, further documentation is spread over a few places:
- https://github.com/mpv-player/mpv/blob/master/libmpv/client.h
- http://mpv.io/manual/master/#options
- http://mpv.io/manual/master/#list-of-input-commands
- http://mpv.io/manual/master/#properties
- https://github.com/mpv-player/mpv-examples/tree/master/libmpv
+23 -1
View File
@@ -412,6 +412,8 @@ These also live in the ``mp`` module, but are documented separately as they
are useful only in special situations.
``mp.suspend()``
This function has been deprecated in mpv 0.21.0 (no replacement).
Suspend the mpv main loop. There is a long-winded explanation of this in
the C API function ``mpv_suspend()``. In short, this prevents the player
from displaying the next video frame, so that you don't get blocked when
@@ -420,11 +422,15 @@ are useful only in special situations.
Before mpv 0.17.0, this was automatically called by the event handler.
``mp.resume()``
This function has been deprecated in mpv 0.21.0 (no replacement).
Undo one ``mp.suspend()`` call. ``mp.suspend()`` increments an internal
counter, and ``mp.resume()`` decrements it. When 0 is reached, the player
is actually resumed.
``mp.resume_all()``
This function has been deprecated in mpv 0.21.0 (no replacement).
This resets the internal suspend counter and resumes the player. (It's
like calling ``mp.resume()`` until the player is actually resumed.)
@@ -450,6 +456,13 @@ are useful only in special situations.
``mp.get_wakeup_pipe()`` if you're interested in properly working
notification of new events and working timers.
``mp.register_idle(fn)``
Register an event loop idle handler. Idle handlers are called before the
script goes to sleep after handling all new events. This can be used for
example to delay processing of property change events: if you're observing
multiple properties at once, you might not want to act on each property
change, but only when all change notifications have been received.
``mp.enable_messages(level)``
Set the minimum log level of which mpv message output to receive. These
messages are normally printed to the terminal. By calling this function,
@@ -633,7 +646,16 @@ strictly part of the guaranteed API.
Set to ``true`` if the process has been killed by mpv as a result
of ``cancellable`` being set to ``true``.
In all cases, ``mp.resume_all()`` is implicitly called.
``utils.subprocess_detached(t)``
Runs an external process and detaches it from mpv's control.
The parameter ``t`` is a table. The function reads the following entries:
``args``
Array of strings of the same semantics as the ``args`` used in the
``subprocess`` function.
The function returns ``nil``.
``utils.parse_json(str [, trail])``
Parses the given string argument as JSON, and returns it as a Lua table. On
+33 -39
View File
@@ -143,11 +143,11 @@ Ctrl + and Ctrl -
u
Switch between applying no style overrides to SSA/ASS subtitles, and
overriding them almost completely with the normal subtitle style. See
``--ass-style-override`` for more info.
``--sub-ass-style-override`` for more info.
V
Toggle subtitle VSFilter aspect compatibility mode. See
``--ass-vsfilter-aspect-compat`` for more info.
``--sub-ass-vsfilter-aspect-compat`` for more info.
r and t
Move subtitles up/down.
@@ -268,15 +268,16 @@ command line.
The suboption parser can quote strings with ``"`` and ``[...]``.
Additionally, there is a special form of quoting with ``%n%`` described below.
For example, the ``opengl`` VO can take multiple options:
For example, assume the hypothetical ``foo`` filter can take multiple options:
``mpv test.mkv --vo=opengl:scale=lanczos:icc-profile=file.icc,xv``
``mpv test.mkv --vf=foo:option1=value1:option2:option3=value3,bar``
This passes ``scale=lanczos`` and ``icc-profile=file.icc`` to ``opengl``,
and also specifies ``xv`` as fallback VO. If the icc-profile path contains
spaces or characters like ``,`` or ``:``, you need to quote them:
This passes ``option1`` and ``option3`` to the ``foo`` filter, with ``option2``
as flag (implicitly ``option2=yes``), and adds a ``bar`` filter after that. If
an option contains spaces or characters like ``,`` or ``:``, you need to quote
them:
``mpv '--vo=opengl:icc-profile="file with spaces.icc",xv'``
``mpv '--vf=foo:option1="option value with spaces",bar'``
Shells may actually strip some quotes from the string passed to the commandline,
so the example quotes the string twice, ensuring that mpv receives the ``"``
@@ -297,11 +298,11 @@ It is started with ``%`` and has the following format::
.. admonition:: Examples
``mpv --ao=pcm:file=%10%C:test.wav test.avi``
``mpv '--vf=foo:option1=%11%quoted text' test.avi``
Or in a script:
``mpv --ao=pcm:file=%`expr length "$NAME"`%"$NAME" test.avi``
``mpv --vf=foo:option1=%`expr length "$NAME"`%"$NAME" test.avi``
Suboptions passed to the client API are also subject to escaping. Using
``mpv_set_option_string()`` is exactly like passing ``--name=data`` to the
@@ -309,8 +310,7 @@ command line (but without shell processing of the string). Some options
support passing values in a more structured way instead of flat strings, and
can avoid the suboption parsing mess. For example, ``--vf`` supports
``MPV_FORMAT_NODE``, which lets you pass suboptions as a nested data structure
of maps and arrays. (``--vo`` supports this in the same way, although this
fact is undocumented.)
of maps and arrays.
Paths
-----
@@ -528,7 +528,8 @@ profile name ``default`` to continue with normal options.
[slow]
profile-desc="some profile name"
vo=opengl:scale=ewa_lanczos:scale-radius=16
# reference a builtin profile
profile=opengl-hq
[fast]
vo=vdpau
@@ -549,10 +550,6 @@ Some profiles are loaded automatically. The following example demonstrates this:
::
[vo.vdpau]
# Use hardware decoding
hwdec=vdpau
[protocol.dvd]
profile-desc="profile for dvd:// streams"
alang=en
@@ -561,11 +558,7 @@ Some profiles are loaded automatically. The following example demonstrates this:
profile-desc="profile for .flv files"
vf=flip
[ao.alsa]
device=spdif
The profile name follows the schema ``type.name``, where type can be ``vo``
to match the value the ``--vo`` option is set to, ``ao`` for ``--ao``,
The profile name follows the schema ``type.name``, where type can be
``protocol`` for the input/output protocol in use (see ``--list-protocols``),
and ``extension`` for the extension of the path of the currently played file
(*not* the file format).
@@ -688,7 +681,7 @@ PROTOCOLS
``mf://[filemask|@listfile]`` ``--mf-...``
Play a series of images as video.
``cdda://track[-endtrack][:speed][/device]`` ``--cdrom-device=PATH`` ``--cdda-...``
``cdda://[device]`` ``--cdrom-device=PATH`` ``--cdda-...``
Play CD.
``lavf://...``
@@ -743,24 +736,32 @@ Currently this happens only in the following cases:
or file associations provided by desktop environments)
- if started from explorer.exe on Windows (technically, if it was started on
Windows, and all of the stdout/stderr/stdin handles are unset)
- manually adding ``--profile=pseudo-gui`` to the command line
- started out of the bundle on OSX
- if you manually use ``--player-operation-mode=pseudo-gui`` on the command line
This mode implicitly adds ``--profile=pseudo-gui`` to the command line, with
the ``pseudo-gui`` profile being predefined with the following contents:
This mode applies options from the builtin profile ``builtin-pseudo-gui``, but
only if these haven't been set in the user's config file or on the command line.
Also, for compatibility with the old pseudo-gui behavior, the options in the
``pseudo-gui`` profile are applied unconditionally. In addition, the profile
makes sure to enable the pseudo-GUI mode, so that ``--profile=pseudo-gui``
works like in older mpv releases. The profiles are currently defined as follows:
::
[pseudo-gui]
[builtin-pseudo-gui]
terminal=no
force-window=yes
idle=once
screenshot-directory=~~desktop/
[pseudo-gui]
player-operation-mode=pseudo-gui
This follows the mpv config file format. To customize pseudo-GUI mode, you can
put your own ``pseudo-gui`` profile into your ``mpv.conf``. This profile will
enhance the default profile, rather than overwrite it.
.. warning::
The profile always overrides other settings in ``mpv.conf``.
Currently, you can extend the ``pseudo-gui`` profile in the config file the
normal way. This is deprecated. In future mpv releases, the behavior might
change, and not apply your additional settings, and/or use a different
profile name.
.. include:: options.rst
@@ -785,14 +786,7 @@ The profile always overrides other settings in ``mpv.conf``.
.. include:: changes.rst
EMBEDDING INTO OTHER PROGRAMS (LIBMPV)
======================================
mpv can be embedded into other programs as video/audio playback backend. The
recommended way to do so is using libmpv. See ``libmpv/client.h`` in the mpv
source code repository. This provides a C API. Bindings for other languages
might be available (see wiki).
.. include:: libmpv.rst
ENVIRONMENT VARIABLES
=====================
+1219 -175
View File
File diff suppressed because it is too large. Load diff
+53 -63
View File
@@ -20,22 +20,25 @@ The Interface
::
+------------------+-----------+--------------------+
| playlist prev | title | playlist next |
+-------+------+---+--+------+-+----+------+--------+
| audio | skip | seek | | seek | skip | full |
+-------+ back | back | play | frwd | frwd | screen |
| sub | | | | | | |
+-------+------+------+------+------+------+--------+
| seekbar |
+----------------+--------------+-------------------+
| time passed | cache status | time remaining |
+----------------+--------------+-------------------+
+---------+----------+----------------------------+-------------+
| pl prev | pl next | title | cache |
+------+--+---+------+---------+-----------+------+-------+-----+
| play | skip | skip | time | seekbar | time | audio | sub |
| | back | frwd | elapsed | | left | | |
+------+------+------+---------+-----------+------+-------+-----+
playlist prev
pl prev
============= ================================================
left-click play previous file in playlist
right-click show playlist
shift+L-click show playlist
============= ================================================
pl next
============= ================================================
left-click play next file in playlist
right-click show playlist
shift+L-click show playlist
============= ================================================
@@ -47,55 +50,33 @@ title
right-click show filename
============= ================================================
playlist next
============= ================================================
left-click play next file in playlist
shift+L-click show playlist
============= ================================================
audio and sub
| Displays selected track and amount of available tracks
============= ================================================
left-click cycle audio/sub tracks forward
right-click cycle audio/sub tracks backwards
shift+L-click show available audio/sub tracks
============= ================================================
skip back
============= ================================================
left-click go to beginning of chapter / previous chapter
shift+L-click show chapters
============= ================================================
seek back
============= ================================================
left-click skip back 5 seconds
right-click skip back 30 seconds
shift-L-click skip back 1 frame
============= ================================================
cache
| Shows current cache fill status
play
============= ================================================
left-click toggle play/pause
============= ================================================
seek frwd
skip back
============= ================================================
left-click skip forward 10 seconds
right-click skip forward 60 seconds
shift-L-click skip forward 1 frame
left-click go to beginning of chapter / previous chapter
right-click show chapters
shift+L-click show chapters
============= ================================================
skip frwd
============= ================================================
left-click go to next chapter
right-click show chapters
shift+L-click show chapters
============= ================================================
fullscreen
time elapsed
| Shows current playback position timestamp
============= ================================================
left-click toggle fullscreen
left-click toggle displaying timecodes with milliseconds
============= ================================================
seekbar
@@ -105,23 +86,22 @@ seekbar
left-click seek to position
============= ================================================
time passed
| Shows current playback position timestamp
============= ================================================
left-click toggle displaying timecodes with milliseconds
============= ================================================
cache status
| Shows current cache fill status (only visible when below 45%)
time remaining
time left
| Shows remaining playback time timestamp
============= ================================================
left-click toggle between total and remaining time
============= ================================================
audio and sub
| Displays selected track and amount of available tracks
============= ================================================
left-click cycle audio/sub tracks forward
right-click cycle audio/sub tracks backwards
shift+L-click show available audio/sub tracks
============= ================================================
Key Bindings
~~~~~~~~~~~~
@@ -176,11 +156,11 @@ Configurable Options
| Enable the OSC when fullscreen
``scalewindowed``
| Default: 1.0
| Default: 1.5
| Scale factor of the OSC when windowed
``scalefullscreen``
| Default: 1.0
| Default: 1.5
| Scale factor of the OSC when fullscreen
``scaleforcedwindow``
@@ -200,6 +180,10 @@ Configurable Options
| Default: 0.0
| Horizontal alignment, -1 (left) to 1 (right)
``barmargin``
| Default: 0
| Margin from bottom (bottombar) or top (topbar), in pixels
``boxalpha``
| Default: 80
| Alpha of the background box, 0 (opaque) to 255 (fully transparent)
@@ -214,27 +198,33 @@ Configurable Options
| Duration of fade out in ms, 0 = no fade
``deadzonesize``
| Default: 0
| Default: 1
| Size of the deadzone. The deadzone is an area that makes the mouse act
like leaving the window. Movement there won't make the OSC show up and
it will hide immediately if the mouse enters it. The deadzone starts
at the window border opposite to the OSC and the size controls how much
of the window it will span. Values between 0 and 1.
of the window it will span. Values between 0 and 1, where 0 means the
OSC will always popup with mouse movement in the window, and 1 means the
OSC will only show up when the mouse hovers it.
``minmousemove``
| Default: 3
| Default: 0
| Minimum amount of pixels the mouse has to move between ticks to make
the OSC show up
``layout``
| Default: box
| Default: bottombar
| The layout for the OSC. Currently available are: box, slimbox,
bottombar and topbar.
``seekbarstyle``
| Default: slider
| Default: bar
| Sets the style of the seekbar, slider (diamond marker) or bar (fill)
``tooltipborder``
| Default: 1
| Size of the tooltip outline when using bottombar or topbar layouts
``timetotal``
| Default: no
| Show total time instead of time remaining
+117 -953
View File
File diff suppressed because it is too large. Load diff
+5 -4
View File
@@ -7,8 +7,8 @@ large part of which is incompatible or completely changes how the player
behaves. Although there are still many similarities to its ancestors, **mpv**
should generally be treated as a completely different program.
.. note::
These lists are incomplete.
.. admonition:: Warning
This document is not updated anymore, and is incomplete and outdated.
General Changes from MPlayer to mpv
-----------------------------------
@@ -262,13 +262,14 @@ Command Line Switches
``-ssf <sub>`` ``--sws-...``
``-stop-xscreensaver`` ``--stop-screensaver``
``-sub-fuzziness`` ``--sub-auto``
``-sub-text-*`` ``--sub-*``
``-sub`` ``--sub-file``
``-subcp`` ``--sub-codepage``
``-subdelay`` ``--sub-delay``
``-subfile`` ``--sub-file``
``-subfont-*`` ``--sub-text-*``, ``--osd-*``
``-subfont-*`` ``--sub-*``, ``--osd-*``
``-subfont-text-scale`` ``--sub-scale``
``-subfont`` ``--sub-text-font``
``-subfont`` ``--sub-font``
``-subfps`` ``--sub-fps``
``-subpos`` ``--sub-pos``
``-sws`` ``--sws-scaler``
+209
View File
@@ -1,3 +1,212 @@
Release 0.21.0
==============
Features
--------
Added
~~~~~
- config: allow profile forward-references in default profile
- demux_lavf: "support" mov edit lists and log errors if used (FFmpeg only)
- hwdec: Add support for CUDA and cuvid/NvDecode (mostly useful on Linux where VDPAU still lacks HEVC Main 10 support; keep using DXVA2 on Windows)
- osc: add right-click behavior to playlist and chapter buttons
- osc: add user-alterable margin for top/bottombar
- rpi: add --hwdec=rpi-copy (#3604)
- sd_lavc: enable teletext
- vaapi: support drm devices when running in vaapi-copy mode
- vd_lavc: Add hwdec wrapper for crystalhd
- vo_opengl: add hw overlay support and use it for RPI
- vo_opengl: basic mali fbdev support
- vo_opengl: rpi: merge vo_rpi features
Removed
~~~~~~~
- vo_opengl: remove pre/post/scale-shaders in favor of user-shaders
Deprecated
~~~~~~~~~~
- config: deprecate ao and vo auto-profiles
- vo_rpi: deprecate this VO
Options and Commands
--------------------
Added
~~~~~
- add --teletext-page option
- af_pan: add af-command support to change the matrix
- af_rubberband: add af-command and option to change the pitch
- command: add a load-script command
- command: add a video-dec-params property
- command: add an apply-profile command
- command: add audio-pts property to get the audio pts
- command: add options to property list
- command: add sub-text property for current subtitle text
- command: export profile list as a property (#977)
- options: add --hwdec=yes as alias for --hwdec=auto
- player: add --player-operation-mode=pseudo-gui
- player: add --video-osd=no option to disable video OSD (#3387)
- player: add --watch-later-directory option
- stream_bluray: select title by playlist (bd://mpls/[playlist])
- vo_opengl: disable glFlush() by default, and add an option to enable it for testing
Changed
~~~~~~~
- af_rubberband: default to channels=together
- command: allow absolute seeks relative to end of stream
- command: make bitrate properties observable
- command: make most options observable
- msg: make --log-file and --dump-stats accept config path expansion (#3591)
- options: deprecate --playlist-pos to --playlist-start
- options: make input options generally runtime-settable
- options: rename subtitle options (--sub-text- → --sub; --ass- → --sub-ass-)
- osc: change default layout to bottombar, seekbarstyle to bar, use larger scalewindowed and scalefullscreen
- player: make --terminal, --log-file, --dump-stats, --osc, --ytdl, --audio-*, --priority, --stop-screensaver (#3615) settable at runtime
- vo_drm: change CLI options
- Change connector selection to accept human readable names (such as eDP-1, HDMI-A-2) rather than arbitrary numbers.
- Change GPU selection to accept GPU number rather than device paths.
- Merge connector and GPU selection into one --drm-connector.
- Add support for --drm-connector=help.
- Add support for --drm-* in EGL backend.
- vo_opengl: rename 3dlut-size to icc-3dlut-size
Removed
~~~~~~~
- command: remove hwdec-active and hwdec-detected properties
- command: remove vo-cmdline
- options: drop unreferenced --bluray-angle option
- vo, ao: disable positional parameter suboptions
- vo_xv: replace no-colorkey with ck-method=none
Deprecated
~~~~~~~~~~
- all VOs and AOs: deprecate sub-options, add them as global options
- command: deprecate "cache" property, replace with "cache-percent"
- deprecate --vo-defaults
- deprecate --vo=opengl-hq alias in favor of opengl-hq profile
- options: deprecate --mute=auto
- vo_direct3d: deprecate direct3d_shaders alias, use shaders by default
- vo_opengl: deprecate 'drm-egl' backend and introduce 'drm' instead
Fixes and Minor Enhancements
----------------------------
- TOOLS/zsh.pl: die if we can't parse main options
- TOOLS/zsh.pl: don't filter files by extension (#2273)
- ao_alsa: try to fallback to "hdmi" before "iec958" for spdif
- ao_rsound: fix compilation (#3501)
- aspect: use nominal width instead of actual width for video-unscaled
- audio/out: prevent underruns with spdif under certain conditions
- audio: fix late audio start (#3610)
- audio: fix missed wakeup when changing audio output device
- audio: fix segfault when yanking USB DAC
- charset_conv: Use CP949 instead of EUC-KR
- command: don't log "ignore" command with -v verbosity
- command: try selecting the next track if track switching fails (#3446)
- demux_mkv: don't crash if --ordered-chapters-files fails
- displayconfig: treat a refresh rate of 1 as invalid
- ipc: log when listening to IPC socket (#3598)
- macOS: fix fullscreen regression on 10.11 and newer (#3364)
- mp_image: fix clearing to black with p010 format
- osc: Fix scaling issues when toggling fullscreen (#3429)
- osc: align text vertically in top/bottombar (#2093)
- osc: change seekbar background's alpha scaling
- osc: fix display of chapters and playlist scaling
- osc: move tooltip to inside seekbar for top/bottombar
- osc: show playlist/chapter list on prev/next instead of osd
- path: default ~~ paths to home directory (#3591)
- player: do not let pseudo-gui override user config settings
- player: enable reading from stdin after loading input.conf
- player: fix instant subtitle refresh on track switches
- player: make --force-window work with opengl-cb
- stream_file: don't use poll() on directories (would hang on macOS; #3530, #3649)
- stream_lavf: fix determining seekability (#1701)
- sub: actually apply text alignment options to non-ASS subtitles
- terminal-win: support modifier keys in console input (#3625)
- vo_drm: fix segfault when using invalid card
- vo_opengl: apply 90° rotation to chroma texture size (#3568)
- vo_opengl: fix incorrect video rendering after vdpau preemption recovery
- vo_opengl: partially fix dumb-mode cropping with rotation
- vo_opengl: rpi: use overlay for yuv420p too
- w32_common: initialize playback status as soon as possible (#3482)
- wayland: reject resize events with either dimension being 0 (#3679)
- x11: fix external fullscreen update (#3570)
- ytdl_hook: Add title to playlist items if available
- ytdl_hook: Set aspect ratio for anamorphic video
- ytdl_hook: Support playlist entries without subtitles
- ytdl_hook: add chapters by parsing video's description
- ytdl_hook: don't add subtitles with unknown duration
- ytdl_hook: temporarily force disable dash segments formats
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.20.0..v0.21.0`
in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.20.0...v0.21.0 or
https://git.srsfckn.biz/mpv/log/?qt=range&q=v0.20.0..v0.21.0
Release 0.20.0
==============
Options and Commands
--------------------
Added
~~~~~
- aspect: add --video-unscaled=downscale-big
- player: add --image-display-duration option to control duration of image display (#3425)
- vo_opengl: angle: new flag (dcomposition) to control DirectComposition
- command: add sub-speed property
Fixes and Minor Enhancements
----------------------------
- af_lavrresample: fix error if resampler could not be recreated
- audio: avoid missed wakeups with ab-loops
- audio: do not apply --audio-channels if spdif passthrough is in use (#3445)
- cache: don't use a backbuffer if the cache is as large as the file
- command: prevent O(n^2) behaviour for playlist property
- demux: close underlying stream if it's fully read anyway (#3456)
- demux: fix undefined behavior with ogg metadata update (#3451)
- player: make looping slightly more seamless
- player: refresh very low framerate video on filter changes (#3435)
- stream_memory: disable stream cache
- vf_rotate: allow arbitrary rotation (#3434)
- vo: be more trusting to estimated display FPS (#3433)
- w32_common: use hooks to detect parent window resize
- x11: work around mutter fullscreen issue (#2072)
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.19.0..v0.20.0`
in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.19.0...v0.20.0 or
http://git.srsfckn.biz/mpv/log/?qt=range&q=v0.19.0..v0.20.0
Release 0.19.0
==============
+9 -1
View File
@@ -6,9 +6,17 @@
local utils = require("mp.utils")
for i,name in ipairs(mp.get_property_native("property-list")) do
function observe(name)
mp.observe_property(name, "native", function(name, val)
print("property '" .. name .. "' changed to '" ..
utils.to_string(val) .. "'")
end)
end
for i,name in ipairs(mp.get_property_native("property-list")) do
observe(name)
end
for i,name in ipairs(mp.get_property_native("options")) do
observe("options/" .. name)
end
@@ -1 +1 @@
profile=pseudo-gui
player-operation-mode=pseudo-gui
+6 -5
View File
@@ -151,15 +151,16 @@ for cur in ax:
cur.addLegend(offset = (-1, 1))
for e in G.sevents:
cur = ax[1 if e.type == "value" else 0]
if not cur in G.curveno:
G.curveno[cur] = 0
args = {'name': e.name,'antialias':True}
color = mkColor(colors[G.curveno[cur] % len(colors)])
if e.type == "event-signal":
args['symbol'] = e.marker
args['pen'] = None
args['symbolBrush'] = pg.mkBrush(color, width=0)
else:
if not cur in G.curveno:
G.curveno[cur] = 0
args['pen'] = pg.mkPen(mkColor(colors[G.curveno[cur] % len(colors)]), width=0)
G.curveno[cur] += 1
args['pen'] = pg.mkPen(color, width=0)
G.curveno[cur] += 1
n = cur.plot([x for x,y in e.vals], [y for x,y in e.vals], **args)
QtGui.QApplication.instance().exec_()
+29
View File
@@ -0,0 +1,29 @@
#!/bin/sh
if [ "x$LIBAV" != "xffmpeg-git" ] || [ "x$TRAVIS_OS_NAME" != "xlinux" ]; then
# trigger build only on one of the matrix nodes
exit;
fi
if [ "x$TRAVIS_BRANCH" != "xmaster" ]; then
# only rebuild website with pushes to master
exit;
fi
TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE:-HEAD^..}
if git diff --quiet --name-only --exit-code "$TRAVIS_COMMIT_RANGE" DOCS/; then
exit;
fi
body='{
"request": {
"branch":"master"
}}'
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Travis-API-Version: 3" \
-H "Authorization: token $WEBSITE_TRAVIS_TOKEN" \
-d "$body" \
https://api.travis-ci.org/repo/mpv-player%2Fmpv.io/requests
+4 -2
View File
@@ -4,11 +4,14 @@
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*: (.*)');
@@ -141,8 +144,7 @@ $runtime_completions
local expl
_tags files urls
while _tags; do
_requested files expl 'media file' _files -g \\
"*.(#i)(asf|asx|avi|f4v|flac|flv|m1v|m2p|m2v|m4v|mjpg|mka|mkv|mov|mp3|mp4|mpe|mpeg|mpg|ogg|ogm|ogv|opus|qt|rm|ts|vob|wav|webm|wma|wmv|wv)(-.)" && rc=0
_requested files expl 'media file' _files && rc=0
if _requested urls; then
while _next_label urls expl URL; do
_urls "\$expl[@]" && rc=0
+1 -1
View File
@@ -1 +1 @@
0.19.0
0.21.0
+7 -2
View File
@@ -86,7 +86,7 @@ static int init(struct dec_audio *da, const char *decoder)
struct priv *ctx = talloc_zero(NULL, struct priv);
da->priv = ctx;
ctx->codec_timebase = (AVRational){0};
ctx->codec_timebase = mp_get_codec_timebase(da->codec);
ctx->force_channel_map = c->force_channels;
@@ -104,6 +104,10 @@ static int init(struct dec_audio *da, const char *decoder)
lavc_context->codec_type = AVMEDIA_TYPE_AUDIO;
lavc_context->codec_id = lavc_codec->id;
#if LIBAVCODEC_VERSION_MICRO >= 100
lavc_context->pkt_timebase = ctx->codec_timebase;
#endif
if (opts->downmix && mpopts->audio_output_channels.num_chmaps == 1) {
lavc_context->request_channel_layout =
mp_chmap_to_lavc(&mpopts->audio_output_channels.chmaps[0]);
@@ -241,7 +245,8 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
if (!got_frame)
return 0;
double out_pts = mp_pts_from_av(priv->avframe->pkt_pts, &priv->codec_timebase);
double out_pts = mp_pts_from_av(MP_AVFRAME_DEC_PTS(priv->avframe),
&priv->codec_timebase);
struct mp_audio *mpframe = mp_audio_from_avframe(priv->avframe);
if (!mpframe)
+5 -1
View File
@@ -180,10 +180,14 @@ static void fix_audio_pts(struct dec_audio *da)
if (da->current_frame->pts != MP_NOPTS_VALUE) {
double newpts = da->current_frame->pts;
if (da->pts != MP_NOPTS_VALUE)
MP_STATS(da, "value %f audio-pts-err", da->pts - newpts);
// Keep the interpolated timestamp if it doesn't deviate more
// than 1 ms from the real one. (MKV rounded timestamps.)
if (da->pts == MP_NOPTS_VALUE || fabs(da->pts - newpts) > 0.001)
da->pts = da->current_frame->pts;
da->pts = newpts;
}
if (da->pts == MP_NOPTS_VALUE && da->header->missing_timestamps)
+10 -4
View File
@@ -166,10 +166,10 @@ static struct af_instance *af_create(struct af_stream *s, char *name,
.replaygain_data = s->replaygain_data,
.out_pool = mp_audio_pool_create(af),
};
struct m_config *config = m_config_from_obj_desc(af, s->log, &desc);
if (m_config_apply_defaults(config, name, s->opts->af_defs) < 0)
goto error;
if (m_config_set_obj_params(config, args) < 0)
struct m_config *config =
m_config_from_obj_desc_and_args(af, s->log, NULL, &desc,
name, s->opts->af_defs, args);
if (!config)
goto error;
af->priv = config->optstruct;
@@ -779,6 +779,12 @@ struct mp_audio *af_read_output_frame(struct af_stream *s)
return af_dequeue_output_frame(s->last);
}
void af_unread_output_frame(struct af_stream *s, struct mp_audio *frame)
{
struct af_instance *af = s->last;
MP_TARRAY_INSERT_AT(af, af->out_queued, af->num_out_queued, 0, frame);
}
// Make sure the caller can change data referenced by the frame.
// Return negative error code on failure (i.e. you can't write).
int af_make_writeable(struct af_instance *af, struct mp_audio *frame)
+1
View File
@@ -148,6 +148,7 @@ void af_add_output_frame(struct af_instance *af, struct mp_audio *frame);
int af_filter_frame(struct af_stream *s, struct mp_audio *frame);
int af_output_frame(struct af_stream *s, bool eof);
struct mp_audio *af_read_output_frame(struct af_stream *s);
void af_unread_output_frame(struct af_stream *s, struct mp_audio *frame);
int af_make_writeable(struct af_instance *af, struct mp_audio *frame);
double af_calc_delay(struct af_stream *s);
+16 -14
View File
@@ -99,10 +99,6 @@ static double get_delay(struct af_resample *s)
return avresample_get_delay(s->avrctx) / (double)s->in_rate +
avresample_available(s->avrctx) / (double)s->out_rate;
}
static void drop_all_output(struct af_resample *s)
{
while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
}
static int get_out_samples(struct af_resample *s, int in_samples)
{
return avresample_get_out_samples(s->avrctx, in_samples);
@@ -113,10 +109,6 @@ static double get_delay(struct af_resample *s)
int64_t base = s->in_rate * (int64_t)s->out_rate;
return swr_get_delay(s->avrctx, base) / (double)base;
}
static void drop_all_output(struct af_resample *s)
{
while (swr_drop_output(s->avrctx, 1000) > 0) {}
}
static int get_out_samples(struct af_resample *s, int in_samples)
{
#if LIBSWRESAMPLE_VERSION_MAJOR > 1 || LIBSWRESAMPLE_VERSION_MINOR >= 2
@@ -406,8 +398,17 @@ static int control(struct af_instance *af, int cmd, void *arg)
return AF_OK;
}
case AF_CONTROL_RESET:
if (s->avrctx)
drop_all_output(s);
if (s->avrctx) {
#if HAVE_LIBSWRESAMPLE
swr_close(s->avrctx);
if (swr_init(s->avrctx) < 0) {
close_lavrr(af);
return AF_ERROR;
}
#else
while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
#endif
}
return AF_OK;
}
return AF_UNKNOWN;
@@ -479,19 +480,20 @@ static void reorder_planes(struct mp_audio *mpa, int *reorder,
static int filter_resample(struct af_instance *af, struct mp_audio *in)
{
struct af_resample *s = af->priv;
struct mp_audio *out = NULL;
if (!s->avrctx)
goto error;
int samples = get_out_samples(s, in ? in->samples : 0);
struct mp_audio out_format = s->pool_fmt;
struct mp_audio *out = mp_audio_pool_get(af->out_pool, &out_format, samples);
out = mp_audio_pool_get(af->out_pool, &out_format, samples);
if (!out)
goto error;
if (in)
mp_audio_copy_attributes(out, in);
if (!s->avrctx)
goto error;
if (out->samples) {
out->samples = resample_frame(s->avrctx, out, in);
if (out->samples < 0)
+138 -124
View File
@@ -28,12 +28,11 @@
#include "af.h"
// Data for specific instances of this filter
typedef struct af_pan_s
{
int nch; // Number of output channels; zero means same as input
float level[AF_NCH][AF_NCH]; // Gain level for each channel
char *matrixstr;
}af_pan_t;
typedef struct af_pan_s {
int nch; // Number of output channels; zero means same as input
float level[AF_NCH][AF_NCH]; // Gain level for each channel
char *matrixstr;
} af_pan_t;
static void set_channels(struct mp_audio *mpa, int num)
{
@@ -44,129 +43,17 @@ static void set_channels(struct mp_audio *mpa, int num)
mp_audio_set_channels(mpa, &map);
}
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
static void parse_matrix(struct af_instance *af, const char *cp)
{
af_pan_t* s = af->priv;
switch(cmd){
case AF_CONTROL_REINIT:
// Sanity check
if(!arg) return AF_ERROR;
af->data->rate = ((struct mp_audio*)arg)->rate;
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
set_channels(af->data, s->nch ? s->nch: ((struct mp_audio*)arg)->nch);
if((af->data->format != ((struct mp_audio*)arg)->format) ||
(af->data->bps != ((struct mp_audio*)arg)->bps)){
mp_audio_set_format((struct mp_audio*)arg, af->data->format);
return AF_FALSE;
}
return AF_OK;
case AF_CONTROL_SET_PAN_LEVEL:{
int i;
int ch = ((af_control_ext_t*)arg)->ch;
float* level = ((af_control_ext_t*)arg)->arg;
if (ch >= AF_NCH)
return AF_FALSE;
for(i=0;i<AF_NCH;i++)
s->level[ch][i] = level[i];
return AF_OK;
}
case AF_CONTROL_SET_PAN_NOUT:
// Reinit must be called after this function has been called
// Sanity check
if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH){
MP_ERR(af, "The number of output channels must be"
" between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]);
return AF_ERROR;
}
s->nch=((int*)arg)[0];
return AF_OK;
case AF_CONTROL_SET_PAN_BALANCE:{
float val = *(float*)arg;
if (s->nch)
return AF_ERROR;
if (af->data->nch >= 2) {
s->level[0][0] = MPMIN(1.f, 1.f - val);
s->level[0][1] = MPMAX(0.f, val);
s->level[1][0] = MPMAX(0.f, -val);
s->level[1][1] = MPMIN(1.f, 1.f + val);
}
return AF_OK;
}
case AF_CONTROL_GET_PAN_BALANCE:
if (s->nch)
return AF_ERROR;
*(float*)arg = s->level[0][1] - s->level[1][0];
return AF_OK;
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance *af, struct mp_audio *c)
{
if (!c)
return 0;
struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples);
if (!l) {
talloc_free(c);
return -1;
}
mp_audio_copy_attributes(l, c);
af_pan_t* s = af->priv; // Setup for this instance
float* in = c->planes[0]; // Input audio data
float* out = NULL; // Output audio data
float* end = in+c->samples*c->nch; // End of loop
int nchi = c->nch; // Number of input channels
int ncho = l->nch; // Number of output channels
register int j,k;
out = l->planes[0];
// Execute panning
// FIXME: Too slow
while(in < end){
for(j=0;j<ncho;j++){
register float x = 0.0;
register float* tin = in;
for(k=0;k<nchi;k++)
x += tin[k] * s->level[j][k];
out[j] = x;
}
out+= ncho;
in+= nchi;
}
talloc_free(c);
af_add_output_frame(af, l);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = filter_frame;
af_pan_t *s = af->priv;
int n = 0;
int j,k;
int nch = s->nch;
if(nch && AF_OK != control(af,AF_CONTROL_SET_PAN_NOUT, &nch))
return AF_ERROR;
// Read pan values
char *cp = s->matrixstr;
j = 0; k = 0;
while(cp && k < AF_NCH){
int j = 0, k = 0, n;
while (*cp && k < AF_NCH) {
sscanf(cp, "%f%n" , &s->level[j][k], &n);
MP_VERBOSE(af, "Pan level from channel %i to"
" channel %i = %f\n",k,j,s->level[j][k]);
cp =&cp[n];
" channel %i = %f\n", k, j, s->level[j][k]);
cp = &cp[n];
j++;
if(j>=nch){
if (j >= s->nch) {
j = 0;
k++;
}
@@ -174,6 +61,133 @@ static int af_open(struct af_instance* af){
break;
cp++;
}
}
// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
af_pan_t* s = af->priv;
switch(cmd){
case AF_CONTROL_REINIT:
// Sanity check
if (!arg)
return AF_ERROR;
af->data->rate = ((struct mp_audio*)arg)->rate;
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
set_channels(af->data, s->nch ? s->nch : ((struct mp_audio*)arg)->nch);
if ((af->data->format != ((struct mp_audio*)arg)->format) ||
(af->data->bps != ((struct mp_audio*)arg)->bps)) {
mp_audio_set_format((struct mp_audio*)arg, af->data->format);
return AF_FALSE;
}
return AF_OK;
case AF_CONTROL_SET_PAN_LEVEL: {
int i;
int ch = ((af_control_ext_t*)arg)->ch;
float *level = ((af_control_ext_t*)arg)->arg;
if (ch >= AF_NCH)
return AF_FALSE;
for (i = 0; i < AF_NCH; i++)
s->level[ch][i] = level[i];
return AF_OK;
}
case AF_CONTROL_SET_PAN_NOUT:
// Reinit must be called after this function has been called
// Sanity check
if (((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH) {
MP_ERR(af, "The number of output channels must be"
" between 1 and %i. Current value is %i\n",
AF_NCH, ((int*)arg)[0]);
return AF_ERROR;
}
s->nch = ((int*)arg)[0];
return AF_OK;
case AF_CONTROL_SET_PAN_BALANCE: {
float val = *(float*)arg;
if (s->nch)
return AF_ERROR;
if (af->data->nch >= 2) {
s->level[0][0] = MPMIN(1.f, 1.f - val);
s->level[0][1] = MPMAX(0.f, val);
s->level[1][0] = MPMAX(0.f, -val);
s->level[1][1] = MPMIN(1.f, 1.f + val);
}
return AF_OK;
}
case AF_CONTROL_GET_PAN_BALANCE:
if (s->nch)
return AF_ERROR;
*(float*)arg = s->level[0][1] - s->level[1][0];
return AF_OK;
case AF_CONTROL_COMMAND: {
char **args = arg;
if (!strcmp(args[0], "set-matrix")) {
parse_matrix(af, args[1]);
return CONTROL_OK;
} else {
return CONTROL_ERROR;
}
}
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance *af, struct mp_audio *c)
{
if (!c)
return 0;
struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples);
if (!l) {
talloc_free(c);
return -1;
}
mp_audio_copy_attributes(l, c);
af_pan_t* s = af->priv; // Setup for this instance
float *in = c->planes[0]; // Input audio data
float *out = NULL; // Output audio data
float *end = in+c->samples * c->nch; // End of loop
int nchi = c->nch; // Number of input channels
int ncho = l->nch; // Number of output channels
register int j, k;
out = l->planes[0];
// Execute panning
// FIXME: Too slow
while (in < end) {
for (j = 0; j < ncho; j++) {
register float x = 0.0;
register float *tin = in;
for (k = 0; k < nchi; k++)
x += tin[k] * s->level[j][k];
out[j] = x;
}
out += ncho;
in += nchi;
}
talloc_free(c);
af_add_output_frame(af, l);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance *af)
{
af->control = control;
af->filter_frame = filter_frame;
af_pan_t *s = af->priv;
int nch = s->nch;
if (nch && AF_OK != control(af, AF_CONTROL_SET_PAN_NOUT, &nch))
return AF_ERROR;
// Read pan values
if (s->matrixstr)
parse_matrix(af, s->matrixstr);
return AF_OK;
}
+26
View File
@@ -26,6 +26,7 @@
struct priv {
RubberBandState rubber;
double speed;
double pitch;
struct mp_audio *pending;
bool needs_reset;
// Estimate how much librubberband has buffered internally.
@@ -44,6 +45,14 @@ static void update_speed(struct af_instance *af, double new_speed)
rubberband_set_time_ratio(p->rubber, 1.0 / p->speed);
}
static void update_pitch(struct af_instance *af, double new_pitch)
{
struct priv *p = af->priv;
p->pitch = new_pitch;
rubberband_set_pitch_scale(p->rubber, p->pitch);
}
static int control(struct af_instance *af, int cmd, void *arg)
{
struct priv *p = af->priv;
@@ -72,6 +81,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
}
update_speed(af, p->speed);
update_pitch(af, p->pitch);
control(af, AF_CONTROL_RESET, NULL);
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
@@ -87,6 +97,19 @@ static int control(struct af_instance *af, int cmd, void *arg)
p->pending = NULL;
p->rubber_delay = 0;
return AF_OK;
case AF_CONTROL_COMMAND: {
char **args = arg;
if (!strcmp(args[0], "set-pitch")) {
char *endptr;
double pitch = strtod(args[1], &endptr);
if (*endptr || pitch < 0.01 || pitch > 100.0)
return CONTROL_ERROR;
update_pitch(af, pitch);
return CONTROL_OK;
} else {
return CONTROL_ERROR;
}
}
}
return AF_UNKNOWN;
}
@@ -187,9 +210,11 @@ const struct af_info af_info_rubberband = {
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.speed = 1.0,
.pitch = 1.0,
.opt_pitch = RubberBandOptionPitchHighConsistency,
.opt_transients = RubberBandOptionTransientsMixed,
.opt_formant = RubberBandOptionFormantPreserved,
.opt_channels = RubberBandOptionChannelsTogether,
},
.options = (const struct m_option[]) {
OPT_CHOICE("transients", opt_transients, 0,
@@ -220,6 +245,7 @@ const struct af_info af_info_rubberband = {
OPT_CHOICE("channels", opt_channels, 0,
({"apart", RubberBandOptionChannelsApart},
{"together", RubberBandOptionChannelsTogether})),
OPT_DOUBLE("pitch-scale", pitch, M_OPT_RANGE, .min = 0.01, .max = 100),
{0}
},
};
+35 -21
View File
@@ -28,7 +28,6 @@
#include "audio/format.h"
#include "audio/audio.h"
#include "input/input.h"
#include "options/options.h"
#include "options/m_config.h"
#include "common/msg.h"
@@ -109,6 +108,8 @@ static bool get_desc(struct m_obj_desc *dst, int index)
.priv_size = ao->priv_size,
.priv_defaults = ao->priv_defaults,
.options = ao->options,
.global_opts = ao->global_opts,
.legacy_prefix = ao->legacy_prefix,
.hidden = ao->encode,
.p = ao,
};
@@ -121,11 +122,15 @@ const struct m_obj_list ao_obj_list = {
.description = "audio outputs",
.allow_unknown_entries = true,
.allow_trailer = true,
.disallow_positional_parameters = true,
};
static struct ao *ao_alloc(bool probing, struct mpv_global *global,
struct input_ctx *input_ctx, char *name, char **args)
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
char *name, char **args)
{
assert(wakeup_cb);
struct MPOpts *opts = global->opts;
struct mp_log *log = mp_log_new(NULL, global->log, "ao");
struct m_obj_desc desc;
@@ -139,15 +144,17 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global,
*ao = (struct ao) {
.driver = desc.p,
.probing = probing,
.input_ctx = input_ctx,
.global = global,
.wakeup_cb = wakeup_cb,
.wakeup_ctx = wakeup_ctx,
.log = mp_log_new(ao, log, name),
.def_buffer = opts->audio_buffer,
.client_name = talloc_strdup(ao, opts->audio_client_name),
};
struct m_config *config = m_config_from_obj_desc(ao, ao->log, &desc);
if (m_config_apply_defaults(config, name, opts->ao_defs) < 0)
goto error;
if (m_config_set_obj_params(config, args) < 0)
struct m_config *config =
m_config_from_obj_desc_and_args(ao, ao->log, global, &desc,
name, opts->ao_defs, args);
if (!config)
goto error;
ao->priv = config->optstruct;
return ao;
@@ -157,12 +164,12 @@ error:
}
static struct ao *ao_init(bool probing, struct mpv_global *global,
struct input_ctx *input_ctx,
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
struct encode_lavc_context *encode_lavc_ctx, int flags,
int samplerate, int format, struct mp_chmap channels,
char *dev, char *name, char **args)
{
struct ao *ao = ao_alloc(probing, global, input_ctx, name, args);
struct ao *ao = ao_alloc(probing, global, wakeup_cb, wakeup_ctx, name, args);
if (!ao)
return NULL;
ao->samplerate = samplerate;
@@ -193,8 +200,9 @@ static struct ao *ao_init(bool probing, struct mpv_global *global,
snprintf(redirect, sizeof(redirect), "%s", ao->redirect);
snprintf(rdevice, sizeof(rdevice), "%s", ao->device ? ao->device : "");
talloc_free(ao);
return ao_init(probing, global, input_ctx, encode_lavc_ctx, flags,
samplerate, format, channels, rdevice, redirect, NULL);
return ao_init(probing, global, wakeup_cb, wakeup_ctx,
encode_lavc_ctx, flags, samplerate, format, channels,
rdevice, redirect, NULL);
}
goto fail;
}
@@ -244,7 +252,7 @@ static void split_ao_device(void *tmp, char *opt, char **out_ao, char **out_dev)
struct ao *ao_init_best(struct mpv_global *global,
int init_flags,
struct input_ctx *input_ctx,
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
struct encode_lavc_context *encode_lavc_ctx,
int samplerate, int format, struct mp_chmap channels)
{
@@ -300,8 +308,8 @@ struct ao *ao_init_best(struct mpv_global *global,
dev = pref_dev;
mp_verbose(log, "Using preferred device '%s'\n", dev);
}
ao = ao_init(probing, global, input_ctx, encode_lavc_ctx, init_flags,
samplerate, format, channels, dev,
ao = ao_init(probing, global, wakeup_cb, wakeup_ctx, encode_lavc_ctx,
init_flags, samplerate, format, channels, dev,
entry->name, entry->attribs);
if (ao)
break;
@@ -405,8 +413,7 @@ int ao_query_and_reset_events(struct ao *ao, int events)
static void ao_add_events(struct ao *ao, int events)
{
atomic_fetch_or(&ao->events_, events);
if (ao->input_ctx)
mp_input_wakeup(ao->input_ctx);
ao->wakeup_cb(ao->wakeup_ctx);
}
// Request that the player core destroys and recreates the AO. Fully thread-safe.
@@ -490,7 +497,8 @@ bool ao_untimed(struct ao *ao)
struct ao_hotplug {
struct mpv_global *global;
struct input_ctx *input_ctx;
void (*wakeup_cb)(void *ctx);
void *wakeup_ctx;
// A single AO instance is used to listen to hotplug events. It wouldn't
// make much sense to allow multiple AO drivers; all sane platforms have
// a single such audio API.
@@ -502,12 +510,14 @@ struct ao_hotplug {
};
struct ao_hotplug *ao_hotplug_create(struct mpv_global *global,
struct input_ctx *input_ctx)
void (*wakeup_cb)(void *ctx),
void *wakeup_ctx)
{
struct ao_hotplug *hp = talloc_ptrtype(NULL, hp);
*hp = (struct ao_hotplug){
.global = global,
.input_ctx = input_ctx,
.wakeup_cb = wakeup_cb,
.wakeup_ctx = wakeup_ctx,
.needs_update = true,
};
return hp;
@@ -560,7 +570,7 @@ struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp)
if (d == &audio_out_null)
break; // don't add unsafe/special entries
struct ao *ao = ao_alloc(true, hp->global, hp->input_ctx,
struct ao *ao = ao_alloc(true, hp->global, hp->wakeup_cb, hp->wakeup_ctx,
(char *)d->name, NULL);
if (!ao)
continue;
@@ -601,9 +611,13 @@ void ao_hotplug_destroy(struct ao_hotplug *hp)
talloc_free(hp);
}
static void dummy_wakeup(void *ctx)
{
}
void ao_print_devices(struct mpv_global *global, struct mp_log *log)
{
struct ao_hotplug *hp = ao_hotplug_create(global, NULL);
struct ao_hotplug *hp = ao_hotplug_create(global, dummy_wakeup, NULL);
struct ao_device_list *list = ao_hotplug_get_device_list(hp);
mp_info(log, "List of detected audio devices:\n");
for (int n = 0; n < list->num_devices; n++) {
+5 -2
View File
@@ -58,6 +58,8 @@ enum {
AO_INIT_SAFE_MULTICHANNEL_ONLY = 1 << 1,
// Stream silence as long as no audio is playing.
AO_INIT_STREAM_SILENCE = 1 << 2,
// Force exclusive mode, i.e. lock out the system mixer.
AO_INIT_EXCLUSIVE = 1 << 3,
};
typedef struct ao_control_vol {
@@ -83,7 +85,7 @@ struct mp_audio;
struct ao *ao_init_best(struct mpv_global *global,
int init_flags,
struct input_ctx *input_ctx,
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
struct encode_lavc_context *encode_lavc_ctx,
int samplerate, int format, struct mp_chmap channels);
void ao_uninit(struct ao *ao);
@@ -106,7 +108,8 @@ void ao_hotplug_event(struct ao *ao);
struct ao_hotplug;
struct ao_hotplug *ao_hotplug_create(struct mpv_global *global,
struct input_ctx *input_ctx);
void (*wakeup_cb)(void *ctx),
void *wakeup_ctx);
void ao_hotplug_destroy(struct ao_hotplug *hp);
bool ao_hotplug_check_update(struct ao_hotplug *hp);
const char *ao_hotplug_get_detected_device(struct ao_hotplug *hp);
+65 -37
View File
@@ -35,6 +35,7 @@
#include "config.h"
#include "options/options.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "common/msg.h"
#include "osdep/endian.h"
@@ -48,6 +49,37 @@
#include "internal.h"
#include "audio/format.h"
struct ao_alsa_opts {
char *device;
char *mixer_device;
char *mixer_name;
int mixer_index;
int resample;
int ni;
int ignore_chmap;
};
#define OPT_BASE_STRUCT struct ao_alsa_opts
static const struct m_sub_options ao_alsa_conf = {
.opts = (const struct m_option[]) {
OPT_STRING("alsa-device", device, 0, DEVICE_OPT_DEPRECATION),
OPT_FLAG("alsa-resample", resample, 0),
OPT_STRING("alsa-mixer-device", mixer_device, 0),
OPT_STRING("alsa-mixer-name", mixer_name, 0),
OPT_INTRANGE("alsa-mixer-index", mixer_index, 0, 0, 99),
OPT_FLAG("alsa-non-interleaved", ni, 0),
OPT_FLAG("alsa-ignore-chmap", ignore_chmap, 0),
{0}
},
.defaults = &(const struct ao_alsa_opts) {
.mixer_device = "default",
.mixer_name = "Master",
.mixer_index = 0,
.ni = 0,
},
.size = sizeof(struct ao_alsa_opts),
};
struct priv {
snd_pcm_t *alsa;
bool device_lost;
@@ -61,13 +93,7 @@ struct priv {
snd_output_t *output;
char *cfg_device;
char *cfg_mixer_device;
char *cfg_mixer_name;
int cfg_mixer_index;
int cfg_resample;
int cfg_ni;
int cfg_ignore_chmap;
struct ao_alsa_opts *opts;
};
#define BUFFER_TIME 250000 // 250ms
@@ -125,13 +151,13 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, p->cfg_mixer_index);
snd_mixer_selem_id_set_name(sid, p->cfg_mixer_name);
snd_mixer_selem_id_set_index(sid, p->opts->mixer_index);
snd_mixer_selem_id_set_name(sid, p->opts->mixer_name);
err = snd_mixer_open(&handle, 0);
CHECK_ALSA_ERROR("Mixer open error");
err = snd_mixer_attach(handle, p->cfg_mixer_device);
err = snd_mixer_attach(handle, p->opts->mixer_device);
CHECK_ALSA_ERROR("Mixer attach error");
err = snd_mixer_selem_register(handle, NULL, NULL);
@@ -337,8 +363,10 @@ static bool query_chmaps(struct ao *ao, struct mp_chmap *chmap)
struct mp_chmap_sel chmap_sel = {.tmp = p};
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(p->alsa);
if (!maps)
if (!maps) {
MP_VERBOSE(ao, "snd_pcm_query_chmaps() returned NULL\n");
return false;
}
for (int i = 0; maps[i] != NULL; i++) {
char aname[128];
@@ -445,7 +473,7 @@ static int set_chmap(struct ao *ao, struct mp_chmap *dev_chmap, int num_channels
MP_VERBOSE(ao, "which we understand as: %s\n", mp_chmap_to_str(&chmap));
if (p->cfg_ignore_chmap) {
if (p->opts->ignore_chmap) {
MP_VERBOSE(ao, "user set ignore-chmap; ignoring the channel map.\n");
} else if (af_fmt_is_spdif(ao->format)) {
MP_VERBOSE(ao, "using spdif passthrough; ignoring the channel map.\n");
@@ -562,11 +590,16 @@ static int try_open_device(struct ao *ao, const char *device, int mode)
bstr dev;
bstr_split_tok(bstr0(device), ":", &dev, &(bstr){0});
if (bstr_equals0(dev, "default")) {
ac3_device = append_params(tmp, "iec958", params);
MP_VERBOSE(ao, "got error %d; opening iec fallback device '%s'\n",
err, ac3_device);
err = snd_pcm_open
(&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, mode);
const char *const fallbacks[] = {"hdmi", "iec958", NULL};
for (int n = 0; fallbacks[n]; n++) {
char *ndev = append_params(tmp, fallbacks[n], params);
MP_VERBOSE(ao, "got error %d; opening iec fallback "
"device '%s'\n", err, ndev);
err = snd_pcm_open
(&p->alsa, ndev, SND_PCM_STREAM_PLAYBACK, mode);
if (err >= 0)
break;
}
}
}
talloc_free(tmp);
@@ -613,8 +646,8 @@ static int init_device(struct ao *ao, int mode)
const char *device = "default";
if (ao->device)
device = ao->device;
if (p->cfg_device && p->cfg_device[0])
device = p->cfg_device;
if (p->opts->device && p->opts->device[0])
device = p->opts->device;
err = try_open_device(ao, device, mode);
CHECK_ALSA_ERROR("Playback open error");
@@ -639,7 +672,7 @@ static int init_device(struct ao *ao, int mode)
// Some ALSA drivers have broken delay reporting, so disable the ALSA
// resampling plugin by default.
if (!p->cfg_resample) {
if (!p->opts->resample) {
err = snd_pcm_hw_params_set_rate_resample(p->alsa, alsa_hwparams, 0);
CHECK_ALSA_ERROR("Unable to disable resampling");
}
@@ -682,7 +715,7 @@ static int init_device(struct ao *ao, int mode)
dump_hw_params(ao, MSGL_DEBUG, "HW params after format:\n", alsa_hwparams);
struct mp_chmap dev_chmap = ao->channels;
if (af_fmt_is_spdif(ao->format) || p->cfg_ignore_chmap) {
if (af_fmt_is_spdif(ao->format) || p->opts->ignore_chmap) {
dev_chmap.num = 0; // disable chmap API
} else if (dev_chmap.num == 1 && dev_chmap.speaker[0] == MP_SPEAKER_ID_FC) {
// As yet another ALSA API inconsistency, mono is not reported correctly.
@@ -804,7 +837,9 @@ alsa_error:
static int init(struct ao *ao)
{
struct priv *p = ao->priv;
if (!p->cfg_ni)
p->opts = mp_get_config_group(ao, ao->global, &ao_alsa_conf);
if (!p->opts->ni)
ao->format = af_fmt_from_planar(ao->format);
MP_VERBOSE(ao, "using ALSA version: %s\n", snd_asoundlib_version());
@@ -1123,8 +1158,6 @@ static void list_devs(struct ao *ao, struct ao_device_list *list)
snd_device_name_free_hint(hints);
}
#define OPT_BASE_STRUCT struct priv
const struct ao_driver audio_out_alsa = {
.description = "ALSA audio output",
.name = "alsa",
@@ -1142,20 +1175,15 @@ const struct ao_driver audio_out_alsa = {
.wakeup = ao_wakeup_poll,
.list_devs = list_devs,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.cfg_mixer_device = "default",
.cfg_mixer_name = "Master",
.cfg_mixer_index = 0,
.cfg_ni = 0,
},
.options = (const struct m_option[]) {
OPT_STRING("device", cfg_device, 0),
OPT_FLAG("resample", cfg_resample, 0),
OPT_STRING("mixer-device", cfg_mixer_device, 0),
OPT_STRING("mixer-name", cfg_mixer_name, 0),
OPT_INTRANGE("mixer-index", cfg_mixer_index, 0, 0, 99),
OPT_FLAG("non-interleaved", cfg_ni, 0),
OPT_FLAG("ignore-chmap", cfg_ignore_chmap, 0),
OPT_SUBOPT_LEGACY("device", "alsa-device"),
OPT_SUBOPT_LEGACY("resample", "alsa-resample"),
OPT_SUBOPT_LEGACY("mixer-device", "alsa-mixer-device"),
OPT_SUBOPT_LEGACY("mixer-name", "alsa-mixer-name"),
OPT_SUBOPT_LEGACY("mixer-index", "alsa-mixer-index"),
OPT_SUBOPT_LEGACY("non-interleaved", "alsa-non-interleaved"),
OPT_SUBOPT_LEGACY("ignore-chmap", "alsa-ignore-chmap"),
{0}
},
.global_opts = &ao_alsa_conf,
};
+5 -1
View File
@@ -143,6 +143,8 @@ static int init(struct ao *ao)
{
struct priv *p = ao->priv;
p->exclusive |= ao->init_flags & AO_INIT_EXCLUSIVE;
if (!af_fmt_is_pcm(ao->format) || p->exclusive) {
MP_VERBOSE(ao, "redirecting to coreaudio_exclusive\n");
ao->redirect = "coreaudio_exclusive";
@@ -427,7 +429,9 @@ const struct ao_driver audio_out_coreaudio = {
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]){
OPT_FLAG("change-physical-format", change_physical_format, 0),
OPT_FLAG("exclusive", exclusive, 0),
OPT_FLAG("exclusive", exclusive, 0,
.deprecation_message = "use --audio-exclusive"),
{0}
},
.legacy_prefix = "coreaudio",
};
+1 -1
View File
@@ -41,7 +41,7 @@
#include "internal.h"
#include "audio/format.h"
#include "osdep/timer.h"
#include "osdep/atomics.h"
#include "osdep/atomic.h"
#include "options/m_option.h"
#include "common/msg.h"
#include "audio/out/ao_coreaudio_chmap.h"
+42 -22
View File
@@ -34,24 +34,48 @@
#include "internal.h"
#include "audio/format.h"
#include "osdep/timer.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include <jack/jack.h>
struct priv {
jack_client_t *client;
float jack_latency;
char *cfg_port;
char *cfg_client_name;
struct jack_opts {
char *port;
char *client_name;
int connect;
int autostart;
int stdlayout;
};
#define OPT_BASE_STRUCT struct jack_opts
static const struct m_sub_options ao_jack_conf = {
.opts = (const struct m_option[]){
OPT_STRING("jack-port", port, 0),
OPT_STRING("jack-name", client_name, 0),
OPT_FLAG("jack-autostart", autostart, 0),
OPT_FLAG("jack-connect", connect, 0),
OPT_CHOICE("jack-std-channel-layout", stdlayout, 0,
({"waveext", 0}, {"any", 1})),
{0}
},
.defaults = &(const struct jack_opts) {
.client_name = "mpv",
.connect = 1,
},
.size = sizeof(struct jack_opts),
};
struct priv {
jack_client_t *client;
float jack_latency;
int last_chunk;
int num_ports;
jack_port_t *ports[MP_NUM_CHANNELS];
int activated;
struct jack_opts *opts;
};
static int process(jack_nframes_t nframes, void *arg)
@@ -77,7 +101,7 @@ connect_to_outports(struct ao *ao)
{
struct priv *p = ao->priv;
char *port_name = (p->cfg_port && p->cfg_port[0]) ? p->cfg_port : NULL;
char *port_name = (p->opts->port && p->opts->port[0]) ? p->opts->port : NULL;
const char **matching_ports = NULL;
int port_flags = JackPortIsInput;
int i;
@@ -144,7 +168,7 @@ static void resume(struct ao *ao)
if (jack_activate(p->client))
MP_FATAL(ao, "activate failed\n");
if (p->connect)
if (p->opts->connect)
connect_to_outports(ao);
}
}
@@ -155,9 +179,11 @@ static int init(struct ao *ao)
struct mp_chmap_sel sel = {0};
jack_options_t open_options;
p->opts = mp_get_config_group(ao, ao->global, &ao_jack_conf);
ao->format = AF_FORMAT_FLOATP;
switch (p->stdlayout) {
switch (p->opts->stdlayout) {
case 0:
mp_chmap_sel_add_waveext(&sel);
break;
@@ -170,10 +196,10 @@ static int init(struct ao *ao)
goto err_chmap;
open_options = JackNullOption;
if (!p->autostart)
if (!p->opts->autostart)
open_options |= JackNoStartServer;
p->client = jack_client_open(p->cfg_client_name, open_options, NULL);
p->client = jack_client_open(p->opts->client_name, open_options, NULL);
if (!p->client) {
MP_FATAL(ao, "cannot open server\n");
goto err_client_open;
@@ -213,8 +239,6 @@ static void uninit(struct ao *ao)
jack_client_close(p->client);
}
#define OPT_BASE_STRUCT struct priv
const struct ao_driver audio_out_jack = {
.description = "JACK audio output",
.name = "jack",
@@ -222,17 +246,13 @@ const struct ao_driver audio_out_jack = {
.uninit = uninit,
.resume = resume,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.cfg_client_name = "mpv",
.connect = 1,
},
.options = (const struct m_option[]) {
OPT_STRING("port", cfg_port, 0),
OPT_STRING("name", cfg_client_name, 0),
OPT_FLAG("autostart", autostart, 0),
OPT_FLAG("connect", connect, 0),
OPT_CHOICE("std-channel-layout", stdlayout, 0,
({"waveext", 0}, {"any", 1})),
OPT_SUBOPT_LEGACY("port", "jack-port"),
OPT_SUBOPT_LEGACY("name", "jack-name"),
OPT_SUBOPT_LEGACY("autostart", "jack-autostart"),
OPT_SUBOPT_LEGACY("connect", "jack-connect"),
OPT_SUBOPT_LEGACY("std-channel-layout", "jack-std-channel-layout"),
{0}
},
.global_opts = &ao_jack_conf,
};
+1
View File
@@ -241,4 +241,5 @@ const struct ao_driver audio_out_null = {
OPT_CHANNELS("channel-layouts", channel_layouts, 0),
{0}
},
.legacy_prefix = "ao-null",
};
+18 -2
View File
@@ -24,6 +24,19 @@
#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>
@@ -33,6 +46,7 @@
#include <AL/al.h>
#include <AL/alext.h>
#endif
#endif // __APPLE__
#include "common/msg.h"
@@ -96,7 +110,7 @@ static int validate_device_opt(struct mp_log *log, const m_option_t *opt,
mp_info(log, " '%s'\n", list);
list = list + strlen(list) + 1;
}
return M_OPT_EXIT - 1;
return M_OPT_EXIT;
}
return 0;
}
@@ -356,7 +370,9 @@ const struct ao_driver audio_out_openal = {
.list_devs = list_devs,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_STRING_VALIDATE("device", cfg_device, 0, validate_device_opt),
OPT_STRING_VALIDATE("device", cfg_device, 0, validate_device_opt,
DEVICE_OPT_DEPRECATION),
{0}
},
.legacy_prefix = "ao-openal",
};
+1
View File
@@ -246,4 +246,5 @@ const struct ao_driver audio_out_opensles = {
OPT_INTRANGE("sample-rate", cfg_sample_rate, 0, 1000, 100000),
{0}
},
.legacy_prefix = "opensles",
};
+2 -1
View File
@@ -648,9 +648,10 @@ const struct ao_driver audio_out_oss = {
.oss_mixer_device = PATH_DEV_MIXER,
},
.options = (const struct m_option[]) {
OPT_STRING("device", dsp, 0),
OPT_STRING("device", dsp, 0, DEVICE_OPT_DEPRECATION),
OPT_STRING("mixer-device", oss_mixer_device, 0),
OPT_STRING("mixer-channel", cfg_oss_mixer_channel, 0),
{0}
},
.legacy_prefix = "oss",
};
+1 -2
View File
@@ -152,8 +152,6 @@ static int init(struct ao *ao)
priv->outputfilename,
priv->waveheader ? "WAVE" : "RAW PCM", ao->samplerate,
ao->channels.num, af_fmt_to_str(ao->format));
MP_INFO(ao, "Info: Faster dumping is achieved with --no-video\n");
MP_INFO(ao, "Info: To write WAVE files use --ao=pcm:waveheader (default).\n");
priv->fp = fopen(priv->outputfilename, priv->append ? "ab" : "wb");
if (!priv->fp) {
@@ -226,4 +224,5 @@ const struct ao_driver audio_out_pcm = {
OPT_FLAG("append", append, 0),
{0}
},
.legacy_prefix = "ao-pcm",
};
+2 -1
View File
@@ -836,9 +836,10 @@ const struct ao_driver audio_out_pulse = {
},
.options = (const struct m_option[]) {
OPT_STRING("host", cfg_host, 0),
OPT_STRING("sink", cfg_sink, 0),
OPT_STRING("sink", cfg_sink, 0, DEVICE_OPT_DEPRECATION),
OPT_CHOICE_OR_INT("buffer", cfg_buffer, 0, 1, 2000, ({"native", 0})),
OPT_FLAG("latency-hacks", cfg_latency_hacks, 0),
{0}
},
.legacy_prefix = "pulse",
};
+5 -2
View File
@@ -156,9 +156,12 @@ const struct ao_driver audio_out_rsound = {
.resume = audio_resume,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_STRING("host", host, 0),
OPT_STRING("port", port, 0),
OPT_STRING("host", host, 0,
.deprecation_message = "request --audio-device support on issue tracker"),
OPT_STRING("port", port, 0,
.deprecation_message = "request --audio-device support on issue tracker"),
{0}
},
.legacy_prefix = "rsound",
};
+1
View File
@@ -212,4 +212,5 @@ const struct ao_driver audio_out_sdl = {
OPT_FLOAT("buflen", buflen, 0),
{0}
},
.legacy_prefix = "sdl",
};
+3 -1
View File
@@ -320,7 +320,9 @@ const struct ao_driver audio_out_sndio = {
.reset = reset,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_STRING("device", dev, 0, OPTDEF_STR(SIO_DEVANY)),
OPT_STRING("device", dev, 0, OPTDEF_STR(SIO_DEVANY),
DEVICE_OPT_DEPRECATION),
{0}
},
.legacy_prefix = "ao-sndio",
};
+6 -2
View File
@@ -275,6 +275,8 @@ static int init(struct ao *ao)
struct wasapi_state *state = ao->priv;
state->log = ao->log;
state->opt_exclusive |= ao->init_flags & AO_INIT_EXCLUSIVE;
state->deviceID = wasapi_find_deviceID(ao);
if (!state->deviceID) {
uninit(ao);
@@ -495,8 +497,10 @@ const struct ao_driver audio_out_wasapi = {
.hotplug_uninit = hotplug_uninit,
.priv_size = sizeof(wasapi_state),
.options = (const struct m_option[]) {
OPT_FLAG("exclusive", opt_exclusive, 0),
OPT_STRING("device", opt_device, 0),
OPT_FLAG("exclusive", opt_exclusive, 0,
.deprecation_message = "use --audio-exclusive"),
OPT_STRING("device", opt_device, 0, DEVICE_OPT_DEPRECATION),
{NULL},
},
.legacy_prefix = "ao-wasapi",
};
+1 -1
View File
@@ -29,7 +29,7 @@
#include <endpointvolume.h>
#include "common/msg.h"
#include "osdep/atomics.h"
#include "osdep/atomic.h"
#include "osdep/windows_utils.h"
#include "internal.h"
#include "ao.h"
-1
View File
@@ -17,7 +17,6 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <initguid.h>
#include <wchar.h>
#include "ao_wasapi.h"
-1
View File
@@ -20,7 +20,6 @@
#include <math.h>
#include <wchar.h>
#include <windows.h>
#include <initguid.h>
#include <errors.h>
#include <ksguid.h>
#include <ksmedia.h>
+9 -2
View File
@@ -21,7 +21,7 @@
#include <stdbool.h>
#include <pthread.h>
#include "osdep/atomics.h"
#include "osdep/atomic.h"
#include "audio/out/ao.h"
/* global data used by ao.c and ao drivers */
@@ -40,8 +40,10 @@ struct ao {
const struct ao_driver *api; // entrypoints to the wrapper (push.c/pull.c)
const struct ao_driver *driver;
void *priv;
struct mpv_global *global;
struct encode_lavc_context *encode_lavc_ctx;
struct input_ctx *input_ctx;
void (*wakeup_cb)(void *ctx);
void *wakeup_ctx;
struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix
int init_flags; // AO_INIT_* flags
bool stream_silence; // if audio inactive, just play silence
@@ -180,6 +182,8 @@ struct ao_driver {
int priv_size;
const void *priv_defaults;
const struct m_option *options;
const struct m_sub_options *global_opts;
const char *legacy_prefix;
};
// These functions can be called by AOs.
@@ -203,4 +207,7 @@ bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s,
void ao_device_list_add(struct ao_device_list *list, struct ao *ao,
struct ao_device_desc *e);
#define DEVICE_OPT_DEPRECATION \
.deprecation_message = "use --audio-device instead"
#endif
+2 -2
View File
@@ -30,7 +30,7 @@
#include "osdep/timer.h"
#include "osdep/threads.h"
#include "osdep/atomics.h"
#include "osdep/atomic.h"
#include "misc/ring.h"
/*
@@ -151,7 +151,7 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_us)
end:
if (need_wakeup)
mp_input_wakeup_nolock(ao->input_ctx);
ao->wakeup_cb(ao->wakeup_ctx);
// pad with silence (underflow/paused/eof)
for (int n = 0; n < ao->num_planes; n++)
+5 -3
View File
@@ -35,7 +35,7 @@
#include "osdep/threads.h"
#include "osdep/timer.h"
#include "osdep/atomics.h"
#include "osdep/atomic.h"
#include "audio/audio.h"
#include "audio/audio_buffer.h"
@@ -182,6 +182,7 @@ static int unlocked_get_space(struct ao *ao)
struct ao_push_state *p = ao->api_priv;
int space = mp_audio_buffer_get_write_available(p->buffer);
if (ao->driver->get_space) {
int align = af_format_sample_alignment(ao->format);
// The following code attempts to keep the total buffered audio to
// ao->buffer in order to improve latency.
int device_space = ao->driver->get_space(ao);
@@ -191,6 +192,7 @@ static int unlocked_get_space(struct ao *ao)
// byte based and doesn't do proper chunked processing.
int min_buffer = ao->buffer + 64;
int missing = min_buffer - device_buffered - soft_buffered;
missing = (missing + align - 1) / align * align;
// But always keep the device's buffer filled as much as we can.
int device_missing = device_space - soft_buffered;
missing = MPMAX(missing, device_missing);
@@ -305,7 +307,7 @@ static void ao_play_data(struct ao *ao)
bool more = needed >= (r == space ? ao->device_buffer / 4 : 1) && !stuck &&
!(flags & AOPLAY_FINAL_CHUNK);
if (more)
mp_input_wakeup(ao->input_ctx); // request more data
ao->wakeup_cb(ao->wakeup_ctx); // request more data
MP_TRACE(ao, "in=%d flags=%d space=%d r=%d wa/pl=%d/%d needed=%d more=%d\n",
max, flags, space, r, p->wait_on_ao, p->still_playing, needed, more);
}
@@ -347,7 +349,7 @@ static void *playthread(void *arg)
}
if (was_playing && !p->still_playing)
mp_input_wakeup(ao->input_ctx);
ao->wakeup_cb(ao->wakeup_ctx);
pthread_cond_signal(&p->wakeup); // for draining
if (p->still_playing && timeout > 0) {
+30 -2
View File
@@ -16,6 +16,7 @@
*/
#include <assert.h>
#include <math.h>
#include <libavutil/common.h>
#include <libavutil/log.h>
@@ -84,6 +85,30 @@ void mp_set_lav_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c)
#endif
}
// Pick a "good" timebase, which will be used to convert double timestamps
// back to fractions for passing them through libavcodec.
AVRational mp_get_codec_timebase(struct mp_codec_params *c)
{
AVRational tb = {c->native_tb_num, c->native_tb_den};
if (tb.num < 1 || tb.den < 1) {
if (c->reliable_fps)
tb = av_inv_q(av_d2q(c->fps, 1000000));
if (tb.num < 1 || tb.den < 1)
tb = AV_TIME_BASE_Q;
}
// If the timebase is too coarse, raise its precision, or small adjustments
// to timestamps done between decoder and demuxer could be lost.
if (av_q2d(tb) > 0.001) {
AVRational r = av_div_q(tb, (AVRational){1, 1000});
tb.den *= (r.num + r.den - 1) / r.den;
}
av_reduce(&tb.num, &tb.den, tb.num, tb.den, 1000000);
return tb;
}
// We merely pass-through our PTS/DTS as an int64_t; libavcodec won't use it.
union pts { int64_t i; double d; };
@@ -97,8 +122,10 @@ union pts { int64_t i; double d; };
int64_t mp_pts_to_av(double mp_pts, AVRational *tb)
{
assert(sizeof(int64_t) >= sizeof(double));
if (tb && tb->num > 0 && tb->den > 0)
return mp_pts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : mp_pts / av_q2d(*tb);
if (tb && tb->num > 0 && tb->den > 0) {
return mp_pts == MP_NOPTS_VALUE ?
AV_NOPTS_VALUE : llrint(mp_pts / av_q2d(*tb));
}
// The + 0.0 is to squash possible negative zero mp_pts, which would
// happen to end up as AV_NOPTS_VALUE.
return (union pts){.d = mp_pts + 0.0}.i;
@@ -133,6 +160,7 @@ void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb)
dst->side_data_elems = mpkt->avpacket->side_data_elems;
if (dst->data == mpkt->avpacket->data)
dst->buf = mpkt->avpacket->buf;
dst->flags |= mpkt->avpacket->flags;
}
if (mpkt && tb && tb->num > 0 && tb->den > 0)
dst->duration = mpkt->duration / av_q2d(*tb);
+10
View File
@@ -33,6 +33,7 @@ struct mp_log;
int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size);
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st);
void mp_set_lav_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c);
AVRational mp_get_codec_timebase(struct mp_codec_params *c);
void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb);
int64_t mp_pts_to_av(double mp_pts, AVRational *tb);
double mp_pts_from_av(int64_t av_pts, AVRational *tb);
@@ -45,4 +46,13 @@ 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);
#if (LIBAVCODEC_VERSION_MICRO >= 100 && \
LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 61, 100)) || \
(LIBAVCODEC_VERSION_MICRO < 100 && \
LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 0))
#define MP_AVFRAME_DEC_PTS(frame) ((frame)->pts)
#else
#define MP_AVFRAME_DEC_PTS(frame) ((frame)->pkt_pts)
#endif
#endif
+3 -2
View File
@@ -18,6 +18,7 @@
#ifndef MPLAYER_MPCOMMON_H
#define MPLAYER_MPCOMMON_H
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>
@@ -64,8 +65,8 @@ enum {
DATA_EOF = -2,
};
extern const char *const mpv_version;
extern const char *const mpv_builddate;
extern const char mpv_version[];
extern const char mpv_builddate[];
char *mp_format_time(double time, bool fractions);
char *mp_format_time_fmt(const char *fmt, double time);
+19 -19
View File
@@ -36,25 +36,25 @@
#define OPT_BASE_STRUCT struct encode_opts
const struct m_sub_options encode_config = {
.opts = (const m_option_t[]) {
OPT_STRING("o", file, CONF_GLOBAL | CONF_NOCFG | CONF_PRE_PARSE),
OPT_STRING("of", format, CONF_GLOBAL),
OPT_STRINGLIST("ofopts*", fopts, CONF_GLOBAL),
OPT_FLOATRANGE("ofps", fps, CONF_GLOBAL, 0.0, 1000000.0),
OPT_FLOATRANGE("omaxfps", maxfps, CONF_GLOBAL, 0.0, 1000000.0),
OPT_STRING("ovc", vcodec, CONF_GLOBAL),
OPT_STRINGLIST("ovcopts*", vopts, CONF_GLOBAL),
OPT_STRING("oac", acodec, CONF_GLOBAL),
OPT_STRINGLIST("oacopts*", aopts, CONF_GLOBAL),
OPT_FLAG("oharddup", harddup, CONF_GLOBAL),
OPT_FLOATRANGE("ovoffset", voffset, CONF_GLOBAL, -1000000.0, 1000000.0),
OPT_FLOATRANGE("oaoffset", aoffset, CONF_GLOBAL, -1000000.0, 1000000.0),
OPT_FLAG("ocopyts", copyts, CONF_GLOBAL),
OPT_FLAG("orawts", rawts, CONF_GLOBAL),
OPT_FLAG("oautofps", autofps, CONF_GLOBAL),
OPT_FLAG("oneverdrop", neverdrop, CONF_GLOBAL),
OPT_FLAG("ovfirst", video_first, CONF_GLOBAL),
OPT_FLAG("oafirst", audio_first, CONF_GLOBAL),
OPT_FLAG("ometadata", metadata, CONF_GLOBAL),
OPT_STRING("o", file, M_OPT_FIXED | CONF_NOCFG | CONF_PRE_PARSE),
OPT_STRING("of", format, M_OPT_FIXED),
OPT_STRINGLIST("ofopts*", fopts, M_OPT_FIXED),
OPT_FLOATRANGE("ofps", fps, M_OPT_FIXED, 0.0, 1000000.0),
OPT_FLOATRANGE("omaxfps", maxfps, M_OPT_FIXED, 0.0, 1000000.0),
OPT_STRING("ovc", vcodec, M_OPT_FIXED),
OPT_STRINGLIST("ovcopts*", vopts, M_OPT_FIXED),
OPT_STRING("oac", acodec, M_OPT_FIXED),
OPT_STRINGLIST("oacopts*", aopts, M_OPT_FIXED),
OPT_FLAG("oharddup", harddup, M_OPT_FIXED),
OPT_FLOATRANGE("ovoffset", voffset, M_OPT_FIXED, -1000000.0, 1000000.0),
OPT_FLOATRANGE("oaoffset", aoffset, M_OPT_FIXED, -1000000.0, 1000000.0),
OPT_FLAG("ocopyts", copyts, M_OPT_FIXED),
OPT_FLAG("orawts", rawts, M_OPT_FIXED),
OPT_FLAG("oautofps", autofps, M_OPT_FIXED),
OPT_FLAG("oneverdrop", neverdrop, M_OPT_FIXED),
OPT_FLAG("ovfirst", video_first, M_OPT_FIXED),
OPT_FLAG("oafirst", audio_first, M_OPT_FIXED),
OPT_FLAG("ometadata", metadata, M_OPT_FIXED),
{0}
},
.size = sizeof(struct encode_opts),
+5 -1
View File
@@ -5,9 +5,13 @@
// The only purpose of this is to make mpv library-safe.
// Think hard before adding new members.
struct mpv_global {
struct MPOpts *opts;
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;
};
#endif
+50 -22
View File
@@ -27,12 +27,13 @@
#include "mpv_talloc.h"
#include "misc/bstr.h"
#include "osdep/atomics.h"
#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"
#include "osdep/terminal.h"
#include "osdep/io.h"
#include "osdep/timer.h"
@@ -59,6 +60,8 @@ struct mp_log_root {
int num_buffers;
FILE *log_file;
FILE *stats_file;
char *log_path;
char *stats_path;
// --- must be accessed atomically
/* This is incremented every time the msglevels must be reloaded.
* (This is perhaps better than maintaining a globally accessible and
@@ -286,6 +289,7 @@ static void write_log_file(struct mp_log *log, int lev, char *text)
(mp_time_us() - MP_START_TIME) / 1e6,
mp_log_levels[lev][0],
log->verbose_prefix, text);
fflush(root->log_file);
}
static void write_msg_to_buffers(struct mp_log *log, int lev, char *text)
@@ -457,6 +461,43 @@ void mp_msg_init(struct mpv_global *global)
mp_msg_update_msglevels(global);
}
// If opt is different from *current_path, reopen *file and update *current_path.
// If there's an error, _append_ it to err_buf.
// *current_path and *file are, rather trickily, only accessible under the
// mp_msg_lock.
static void reopen_file(char *opt, char **current_path, FILE **file,
const char *type, struct mpv_global *global)
{
void *tmp = talloc_new(NULL);
bool fail = false;
char *new_path = mp_get_user_path(tmp, global, opt);
if (!new_path)
new_path = "";
pthread_mutex_lock(&mp_msg_lock); // for *current_path/*file
char *old_path = *current_path ? *current_path : "";
if (strcmp(old_path, new_path) != 0) {
if (*file)
fclose(*file);
*file = NULL;
talloc_free(*current_path);
*current_path = talloc_strdup(NULL, new_path);
if (new_path[0]) {
*file = fopen(new_path, "wb");
fail = !*file;
}
}
pthread_mutex_unlock(&mp_msg_lock);
if (fail)
mp_err(global->log, "Failed to open %s file '%s'\n", type, new_path);
talloc_free(tmp);
}
void mp_msg_update_msglevels(struct mpv_global *global)
{
struct mp_log_root *root = global->log->root;
@@ -480,11 +521,14 @@ void mp_msg_update_msglevels(struct mpv_global *global)
m_option_type_msglevels.copy(NULL, &root->msg_levels,
&global->opts->msg_levels);
if (!root->log_file && opts->log_file && opts->log_file[0])
root->log_file = fopen(opts->log_file, "wb");
atomic_fetch_add(&root->reload_counter, 1);
pthread_mutex_unlock(&mp_msg_lock);
reopen_file(opts->log_file, &root->log_path, &root->log_file,
"log", global);
reopen_file(opts->dump_stats, &root->stats_path, &root->stats_file,
"stats", global);
}
void mp_msg_force_stderr(struct mpv_global *global, bool force_stderr)
@@ -499,8 +543,10 @@ void mp_msg_uninit(struct mpv_global *global)
struct mp_log_root *root = global->log->root;
if (root->stats_file)
fclose(root->stats_file);
talloc_free(root->stats_path);
if (root->log_file)
fclose(root->log_file);
talloc_free(root->log_path);
m_option_type_msglevels.free(&root->msg_levels);
talloc_free(root);
global->log = NULL;
@@ -582,24 +628,6 @@ struct mp_log_buffer_entry *mp_msg_log_buffer_read(struct mp_log_buffer *buffer)
return ptr;
}
int mp_msg_open_stats_file(struct mpv_global *global, const char *path)
{
struct mp_log_root *root = global->log->root;
int r;
pthread_mutex_lock(&mp_msg_lock);
if (root->stats_file)
fclose(root->stats_file);
root->stats_file = fopen(path, "wb");
r = root->stats_file ? 0 : -1;
pthread_mutex_unlock(&mp_msg_lock);
mp_msg_update_msglevels(global);
return r;
}
// Thread-safety: fully thread-safe, but keep in mind that the lifetime of
// log must be guaranteed during the call.
// Never call this from signal handlers.
-1
View File
@@ -29,7 +29,6 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
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);
int mp_msg_open_stats_file(struct mpv_global *global, const char *path);
int mp_msg_find_level(const char *s);
extern const char *const mp_log_levels[MSGL_MAX + 1];
+2 -2
View File
@@ -22,5 +22,5 @@
#define BUILDDATE "UNKNOWN"
#endif
const char *const mpv_version = "mpv " VERSION;
const char *const mpv_builddate = BUILDDATE;
const char mpv_version[] = "mpv " VERSION;
const char mpv_builddate[] = BUILDDATE;
+78 -20
View File
@@ -20,6 +20,7 @@
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <math.h>
@@ -28,7 +29,8 @@
#include <sys/stat.h>
#include "config.h"
#include "options/options.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "mpv_talloc.h"
#include "common/msg.h"
#include "common/global.h"
@@ -81,6 +83,34 @@ const demuxer_desc_t *const demuxer_list[] = {
NULL
};
struct demux_opts {
int max_packs;
int max_bytes;
double min_secs;
int force_seekable;
double min_secs_cache;
};
#define OPT_BASE_STRUCT struct demux_opts
const struct m_sub_options demux_conf = {
.opts = (const struct m_option[]){
OPT_DOUBLE("demuxer-readahead-secs", min_secs, M_OPT_MIN, .min = 0),
OPT_INTRANGE("demuxer-max-packets", max_packs, 0, 0, INT_MAX),
OPT_INTRANGE("demuxer-max-bytes", max_bytes, 0, 0, INT_MAX),
OPT_FLAG("force-seekable", force_seekable, 0),
OPT_DOUBLE("cache-secs", min_secs_cache, M_OPT_MIN, .min = 0),
{0}
},
.size = sizeof(struct demux_opts),
.defaults = &(const struct demux_opts){
.max_packs = 16000,
.max_bytes = 400 * 1024 * 1024,
.min_secs = 1.0,
.min_secs_cache = 10.0,
},
};
struct demux_internal {
struct mp_log *log;
@@ -568,7 +598,7 @@ static bool read_packet(struct demux_internal *in)
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
active |= ds->active;
read_more |= ds->active && !ds->head;
read_more |= (ds->active && !ds->head) || ds->refreshing;
packs += ds->packs;
bytes += ds->bytes;
if (ds->active && ds->last_ts != MP_NOPTS_VALUE && in->min_secs > 0 &&
@@ -580,12 +610,12 @@ static bool read_packet(struct demux_internal *in)
if (packs >= in->max_packs || bytes >= in->max_bytes) {
if (!in->warned_queue_overflow) {
in->warned_queue_overflow = true;
MP_ERR(in, "Too many packets in the demuxer packet queues:\n");
MP_WARN(in, "Too many packets in the demuxer packet queues:\n");
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
if (ds->selected) {
MP_ERR(in, " %s/%d: %zd packets, %zd bytes\n",
stream_type_name(ds->type), n, ds->packs, ds->bytes);
MP_WARN(in, " %s/%d: %zd packets, %zd bytes\n",
stream_type_name(ds->type), n, ds->packs, ds->bytes);
}
}
}
@@ -602,11 +632,13 @@ static bool read_packet(struct demux_internal *in)
return false;
}
double seek_pts = get_refresh_seek_pts(in);
bool refresh_seek = seek_pts != MP_NOPTS_VALUE;
read_more |= refresh_seek;
if (!read_more)
return false;
double seek_pts = get_refresh_seek_pts(in);
// Actually read a packet. Drop the lock while doing so, because waiting
// for disk or network I/O can take time.
in->idle = false;
@@ -615,7 +647,7 @@ static bool read_packet(struct demux_internal *in)
struct demuxer *demux = in->d_thread;
if (seek_pts != MP_NOPTS_VALUE) {
if (refresh_seek) {
MP_VERBOSE(in, "refresh seek to %f\n", seek_pts);
demux->desc->seek(demux, seek_pts, SEEK_BACKWARD | SEEK_HR);
}
@@ -1031,6 +1063,7 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
dst->ts_resets_possible = src->ts_resets_possible;
dst->fully_read = src->fully_read;
dst->start_time = src->start_time;
dst->is_network = src->is_network;
dst->priv = src->priv;
}
@@ -1039,10 +1072,10 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
dst->metadata = mp_tags_dup(dst, src->metadata);
if (dst->num_update_stream_tags != src->num_update_stream_tags) {
dst->num_update_stream_tags = src->num_update_stream_tags;
talloc_free(dst->update_stream_tags);
dst->update_stream_tags =
talloc_zero_array(dst, struct mp_tags *, dst->num_update_stream_tags);
dst->num_update_stream_tags = src->num_update_stream_tags;
}
for (int n = 0; n < dst->num_update_stream_tags; n++) {
talloc_free(dst->update_stream_tags[n]);
@@ -1151,6 +1184,23 @@ static void demux_init_cuesheet(struct demuxer *demuxer)
}
}
static void demux_maybe_replace_stream(struct demuxer *demuxer)
{
struct demux_internal *in = demuxer->in;
assert(!in->threading && demuxer == in->d_user);
if (demuxer->fully_read) {
MP_VERBOSE(demuxer, "assuming demuxer read all data; closing stream\n");
free_stream(demuxer->stream);
demuxer->stream = open_memory_stream(NULL, 0); // dummy
in->d_thread->stream = demuxer->stream;
in->d_buffer->stream = demuxer->stream;
if (demuxer->desc->control)
demuxer->desc->control(in->d_thread, DEMUXER_CTRL_REPLACE_STREAM, NULL);
}
}
static struct demuxer *open_given_type(struct mpv_global *global,
struct mp_log *log,
const struct demuxer_desc *desc,
@@ -1167,11 +1217,11 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.stream = stream,
.seekable = stream->seekable,
.filepos = -1,
.opts = global->opts,
.global = global,
.log = mp_log_new(demuxer, log, desc->name),
.glog = log,
.filename = talloc_strdup(demuxer, stream->url),
.is_network = stream->is_network,
.events = DEMUX_EVENT_ALL,
};
demuxer->seekable = stream->seekable;
@@ -1179,22 +1229,24 @@ static struct demuxer *open_given_type(struct mpv_global *global,
!demuxer->stream->uncached_stream->seekable)
demuxer->seekable = false;
struct demux_opts *opts = mp_get_config_group(demuxer, global, &demux_conf);
struct demux_internal *in = demuxer->in = talloc_ptrtype(demuxer, in);
*in = (struct demux_internal){
.log = demuxer->log,
.d_thread = talloc(demuxer, struct demuxer),
.d_buffer = talloc(demuxer, struct demuxer),
.d_user = demuxer,
.min_secs = demuxer->opts->demuxer_min_secs,
.max_packs = demuxer->opts->demuxer_max_packs,
.max_bytes = demuxer->opts->demuxer_max_bytes,
.min_secs = opts->min_secs,
.max_packs = opts->max_packs,
.max_bytes = opts->max_bytes,
.initial_state = true,
};
pthread_mutex_init(&in->lock, NULL);
pthread_cond_init(&in->wakeup, NULL);
if (stream->uncached_stream)
in->min_secs = MPMAX(in->min_secs, demuxer->opts->demuxer_min_secs_cache);
in->min_secs = MPMAX(in->min_secs, opts->min_secs_cache);
*in->d_thread = *demuxer;
*in->d_buffer = *demuxer;
@@ -1225,7 +1277,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
mp_verbose(log, "Detected file format: %s\n", desc->desc);
if (!in->d_thread->seekable)
mp_verbose(log, "Stream is not seekable.\n");
if (!in->d_thread->seekable && demuxer->opts->force_seekable) {
if (!in->d_thread->seekable && opts->force_seekable) {
mp_warn(log, "Not seekable, but enabling seeking on user request.\n");
in->d_thread->seekable = true;
in->d_thread->partially_seekable = true;
@@ -1311,12 +1363,12 @@ done:
// Convenience function: open the stream, enable the cache (according to params
// and global opts.), open the demuxer.
// (use free_demuxer_and_stream() to free the underlying stream too)
// Also for some reason may close the opened stream if it's not needed.
struct demuxer *demux_open_url(const char *url,
struct demuxer_params *params,
struct mp_cancel *cancel,
struct mpv_global *global)
{
struct MPOpts *opts = global->opts;
struct demuxer_params dummy = {0};
if (!params)
params = &dummy;
@@ -1324,12 +1376,18 @@ struct demuxer *demux_open_url(const char *url,
cancel, global);
if (!s)
return NULL;
if (params->allow_capture)
stream_set_capture_file(s, opts->stream_capture);
if (params->allow_capture) {
char *f;
mp_read_option_raw(global, "stream-capture", &m_option_type_string, &f);
stream_set_capture_file(s, f);
talloc_free(f);
}
if (!params->disable_cache)
stream_enable_cache(&s, &opts->stream_cache);
stream_enable_cache_defaults(&s);
struct demuxer *d = demux_open(s, params, global);
if (!d) {
if (d) {
demux_maybe_replace_stream(d);
} else {
params->demuxer_failed = true;
free_stream(s);
}
+3 -1
View File
@@ -43,6 +43,7 @@ enum demux_ctrl {
DEMUXER_CTRL_STREAM_CTRL,
DEMUXER_CTRL_GET_READER_STATE,
DEMUXER_CTRL_GET_BITRATE_STATS, // double[STREAM_TYPE_COUNT]
DEMUXER_CTRL_REPLACE_STREAM,
};
struct demux_ctrl_reader_state {
@@ -183,6 +184,7 @@ typedef struct demuxer {
// packets is not slow either (unlike e.g. libavdevice pseudo-demuxers).
// Typical examples: text subtitles, playlists
bool fully_read;
bool is_network; // opened directly from a network stream
// Bitmask of DEMUX_EVENT_*
int events;
@@ -205,7 +207,6 @@ typedef struct demuxer {
struct mp_tags *metadata;
void *priv; // demuxer-specific internal data
struct MPOpts *opts;
struct mpv_global *global;
struct mp_log *log, *glog;
struct demuxer_params *params;
@@ -219,6 +220,7 @@ typedef struct demuxer {
// thread-safe, only the demuxer is allowed to access the stream directly.
// You can freely use demux_stream_control() to send STREAM_CTRLs, or use
// demux_pause() to get exclusive access to the stream.
// Also note that the stream can get replaced if fully_read is set.
struct stream *stream;
} demuxer_t;
-1
View File
@@ -28,7 +28,6 @@
#include "demux.h"
#include "timeline.h"
#include "common/msg.h"
#include "common/global.h"
#include "options/path.h"
#include "misc/bstr.h"
#include "common/common.h"
+66 -25
View File
@@ -35,7 +35,6 @@
#include <libavutil/display.h>
#include <libavutil/opt.h>
#include "options/options.h"
#include "common/msg.h"
#include "common/tags.h"
#include "common/av_common.h"
@@ -45,6 +44,7 @@
#include "stream/stream.h"
#include "demux.h"
#include "stheader.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "options/path.h"
@@ -69,22 +69,32 @@ struct demux_lavf_opts {
char **avopts;
int hacks;
int genptsmode;
char *sub_cp;
int rtsp_transport;
};
const struct m_sub_options demux_lavf_conf = {
.opts = (const m_option_t[]) {
OPT_INTRANGE("probesize", probesize, 0, 32, INT_MAX),
OPT_STRING("format", format, 0),
OPT_FLOATRANGE("analyzeduration", analyzeduration, 0, 0, 3600),
OPT_INTRANGE("buffersize", buffersize, 0, 1, 10 * 1024 * 1024,
OPTDEF_INT(BIO_BUFFER_SIZE)),
OPT_FLAG("allow-mimetype", allow_mimetype, 0),
OPT_INTRANGE("probescore", probescore, 0, 1, AVPROBE_SCORE_MAX),
OPT_STRING("cryptokey", cryptokey, 0),
OPT_FLAG("hacks", hacks, 0),
OPT_CHOICE("genpts-mode", genptsmode, 0,
OPT_INTRANGE("demuxer-lavf-probesize", probesize, 0, 32, INT_MAX),
OPT_STRING("demuxer-lavf-format", format, 0),
OPT_FLOATRANGE("demuxer-lavf-analyzeduration", analyzeduration, 0,
0, 3600),
OPT_INTRANGE("demuxer-lavf-buffersize", buffersize, 0, 1,
10 * 1024 * 1024, OPTDEF_INT(BIO_BUFFER_SIZE)),
OPT_FLAG("demuxer-lavf-allow-mimetype", allow_mimetype, 0),
OPT_INTRANGE("demuxer-lavf-probescore", probescore, 0,
1, AVPROBE_SCORE_MAX),
OPT_STRING("demuxer-lavf-cryptokey", cryptokey, 0),
OPT_FLAG("demuxer-lavf-hacks", hacks, 0),
OPT_CHOICE("demuxer-lavf-genpts-mode", genptsmode, 0,
({"lavf", 1}, {"no", 0})),
OPT_KEYVALUELIST("o", avopts, 0),
OPT_KEYVALUELIST("demuxer-lavf-o", avopts, 0),
OPT_STRING("sub-codepage", sub_cp, 0),
OPT_CHOICE("rtsp-transport", rtsp_transport, 0,
({"lavf", 0},
{"udp", 1},
{"tcp", 2},
{"http", 3})),
{0}
},
.size = sizeof(struct demux_lavf_opts),
@@ -95,6 +105,8 @@ const struct m_sub_options demux_lavf_conf = {
// user is supposed to retry with larger probe sizes until a higher
// value is reached.
.probescore = AVPROBE_SCORE_MAX/4 + 1,
.sub_cp = "auto",
.rtsp_transport = 2,
},
};
@@ -114,6 +126,7 @@ struct format_hack {
// Do not confuse player's position estimation (position is into external
// segment, with e.g. HLS, player knows about the playlist main file only).
bool clear_filepos : 1;
bool ignore_start : 1;
};
#define BLACKLIST(fmt) {fmt, .ignore = true}
@@ -137,6 +150,9 @@ static const struct format_hack format_hacks[] = {
{"h264", .if_flags = AVFMT_NOTIMESTAMPS },
{"hevc", .if_flags = AVFMT_NOTIMESTAMPS },
// Rebasing start time to 0 is very weird with ogg shoutcast streams.
{"ogg", .ignore_start = true},
TEXTSUB("aqtitle"), TEXTSUB("jacosub"), TEXTSUB("microdvd"),
TEXTSUB("mpl2"), TEXTSUB("mpsub"), TEXTSUB("pjs"), TEXTSUB("realtext"),
TEXTSUB("sami"), TEXTSUB("srt"), TEXTSUB("stl"), TEXTSUB("subviewer"),
@@ -158,6 +174,7 @@ static const struct format_hack format_hacks[] = {
typedef struct lavf_priv {
struct stream *stream;
bool own_stream;
char *filename;
struct format_hack format_hack;
AVInputFormat *avif;
@@ -169,6 +186,9 @@ typedef struct lavf_priv {
int cur_program;
char *mime_type;
double seek_delay;
struct demux_lavf_opts *opts;
double mf_fps;
} lavf_priv_t;
// At least mp4 has name="mov,mp4,m4a,3gp,3g2,mj2", so we split the name
@@ -266,7 +286,7 @@ static void list_formats(struct demuxer *demuxer)
static void convert_charset(struct demuxer *demuxer)
{
lavf_priv_t *priv = demuxer->priv;
char *cp = demuxer->opts->sub_cp;
char *cp = priv->opts->sub_cp;
if (!cp || mp_charset_is_utf8(cp))
return;
bstr data = stream_read_complete(priv->stream, NULL, 128 * 1024 * 1024);
@@ -286,8 +306,10 @@ static void convert_charset(struct demuxer *demuxer)
if (conv.start)
data = conv;
}
if (data.start)
if (data.start) {
priv->stream = open_memory_stream(data.start, data.len);
priv->own_stream = true;
}
talloc_free(alloc);
}
@@ -306,9 +328,8 @@ static const char *const prefixes[] =
static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
{
struct MPOpts *opts = demuxer->opts;
struct demux_lavf_opts *lavfdopts = opts->demux_lavf;
lavf_priv_t *priv = demuxer->priv;
struct demux_lavf_opts *lavfdopts = priv->opts;
struct stream *s = priv->stream;
priv->filename = remove_prefix(s->url, prefixes);
@@ -599,7 +620,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
if (st->avg_frame_rate.num)
sh->codec->fps = av_q2d(st->avg_frame_rate);
if (priv->format_hack.image_format)
sh->codec->fps = demuxer->opts->mf_fps;
sh->codec->fps = priv->mf_fps;
sh->codec->par_w = st->sample_aspect_ratio.num;
sh->codec->par_h = st->sample_aspect_ratio.den;
@@ -666,6 +687,8 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
if (sh->codec->lav_headers)
mp_copy_lav_codec_headers(sh->codec->lav_headers, codec);
#endif
sh->codec->native_tb_num = st->time_base.num;
sh->codec->native_tb_den = st->time_base.den;
if (st->disposition & AV_DISPOSITION_DEFAULT)
sh->default_track = true;
@@ -727,8 +750,6 @@ static int interrupt_cb(void *ctx)
static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
{
struct MPOpts *opts = demuxer->opts;
struct demux_lavf_opts *lavfdopts = opts->demux_lavf;
AVFormatContext *avfc;
AVDictionaryEntry *t = NULL;
float analyze_duration = 0;
@@ -736,6 +757,15 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
demuxer->priv = priv;
priv->stream = demuxer->stream;
priv->opts = mp_get_config_group(priv, demuxer->global, &demux_lavf_conf);
struct demux_lavf_opts *lavfdopts = priv->opts;
int index_mode;
mp_read_option_raw(demuxer->global, "index", &m_option_type_choice,
&index_mode);
mp_read_option_raw(demuxer->global, "mf-fps", &m_option_type_double,
&priv->mf_fps);
if (lavf_check_file(demuxer, check) < 0)
return -1;
@@ -747,7 +777,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
parse_cryptokey(avfc, lavfdopts->cryptokey);
if (lavfdopts->genptsmode)
avfc->flags |= AVFMT_FLAG_GENPTS;
if (opts->index_mode != 1)
if (index_mode != 1)
avfc->flags |= AVFMT_FLAG_IGNIDX;
#if LIBAVFORMAT_VERSION_MICRO >= 100
@@ -780,7 +810,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
priv->stream->type == STREAMTYPE_AVDEVICE ||
priv->format_hack.no_stream)
{
mp_setup_av_network_options(&dopts, demuxer->global, demuxer->log, opts);
mp_setup_av_network_options(&dopts, demuxer->global, demuxer->log);
// This might be incorrect.
demuxer->seekable = true;
} else {
@@ -803,7 +833,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
if (matches_avinputformat_name(priv, "rtsp")) {
const char *transport = NULL;
switch (opts->network_rtsp_transport) {
switch (lavfdopts->rtsp_transport) {
case 1: transport = "udp"; break;
case 2: transport = "tcp"; break;
case 3: transport = "http"; break;
@@ -855,8 +885,8 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
demuxer->ts_resets_possible =
priv->avif_flags & (AVFMT_TS_DISCONT | AVFMT_NOTIMESTAMPS);
demuxer->start_time = priv->avfc->start_time == AV_NOPTS_VALUE ?
0 : (double)priv->avfc->start_time / AV_TIME_BASE;
if (avfc->start_time != AV_NOPTS_VALUE && !priv->format_hack.ignore_start)
demuxer->start_time = avfc->start_time / (double)AV_TIME_BASE;
demuxer->fully_read = priv->format_hack.fully_read;
@@ -908,6 +938,11 @@ static int demux_lavf_fill_buffer(demuxer_t *demux)
#endif
dp->pos = pkt->pos;
dp->keyframe = pkt->flags & AV_PKT_FLAG_KEY;
#if LIBAVFORMAT_VERSION_MICRO >= 100 && \
LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 50, 100)
if (pkt->flags & AV_PKT_FLAG_DISCARD)
MP_ERR(demux, "Edit lists are not correctly supported (FFmpeg issue).\n");
#endif
av_packet_unref(pkt);
if (priv->format_hack.clear_filepos)
@@ -1062,6 +1097,12 @@ redo:
av_seek_frame(priv->avfc, 0, stream_tell(priv->stream),
AVSEEK_FLAG_BYTE);
return DEMUXER_CTRL_OK;
case DEMUXER_CTRL_REPLACE_STREAM:
if (priv->own_stream)
free_stream(priv->stream);
priv->own_stream = false;
priv->stream = demuxer->stream;
return DEMUXER_CTRL_OK;
default:
return DEMUXER_CTRL_NOTIMPL;
}
@@ -1086,7 +1127,7 @@ static void demux_close_lavf(demuxer_t *demuxer)
#endif
}
}
if (priv->stream != demuxer->stream)
if (priv->own_stream)
free_stream(priv->stream);
talloc_free(priv);
demuxer->priv = NULL;
+11 -4
View File
@@ -27,6 +27,7 @@
#include "mpv_talloc.h"
#include "common/msg.h"
#include "options/options.h"
#include "options/m_config.h"
#include "options/path.h"
#include "misc/ctype.h"
@@ -304,10 +305,15 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check)
if (!mf || mf->nr_of_files < 1)
goto error;
char *force_type = demuxer->opts->mf_type;
double mf_fps;
char *mf_type;
mp_read_option_raw(demuxer->global, "mf-fps", &m_option_type_double, &mf_fps);
mp_read_option_raw(demuxer->global, "mf-type", &m_option_type_string, &mf_type);
const char *codec = mp_map_mimetype_to_video_codec(demuxer->stream->mime_type);
if (!codec || (force_type && force_type[0]))
codec = probe_format(mf, force_type, check);
if (!codec || (mf_type && mf_type[0]))
codec = probe_format(mf, mf_type, check);
talloc_free(mf_type);
if (!codec)
goto error;
@@ -320,7 +326,8 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check)
c->codec = codec;
c->disp_w = 0;
c->disp_h = 0;
c->fps = demuxer->opts->mf_fps;
c->fps = mf_fps;
c->reliable_fps = true;
demux_add_sh_stream(demuxer, sh);
+22 -15
View File
@@ -43,7 +43,7 @@
#include "mpv_talloc.h"
#include "common/av_common.h"
#include "options/options.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "misc/bstr.h"
#include "stream/stream.h"
@@ -162,6 +162,8 @@ struct block_info {
};
typedef struct mkv_demuxer {
struct demux_mkv_opts *opts;
int64_t segment_start, segment_end;
double duration;
@@ -179,6 +181,9 @@ typedef struct mkv_demuxer {
mkv_index_t *indexes;
size_t num_indexes;
bool index_complete;
int index_mode;
int edition_id;
struct header_elem {
int32_t id;
@@ -747,11 +752,10 @@ static void add_block_position(demuxer_t *demuxer, struct mkv_track *track,
static int demux_mkv_read_cues(demuxer_t *demuxer)
{
struct MPOpts *opts = demuxer->opts;
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
stream_t *s = demuxer->stream;
if (opts->index_mode != 1 || mkv_d->index_complete) {
if (mkv_d->index_mode != 1 || mkv_d->index_complete) {
ebml_read_skip(demuxer->log, -1, s);
return 0;
}
@@ -810,9 +814,9 @@ done:
static int demux_mkv_read_chapters(struct demuxer *demuxer)
{
struct MPOpts *opts = demuxer->opts;
mkv_demuxer_t *mkv_d = demuxer->priv;
stream_t *s = demuxer->stream;
int wanted_edition = opts->edition_id;
int wanted_edition = mkv_d->edition_id;
uint64_t wanted_edition_uid = demuxer->matroska_data.uid.edition;
/* A specific edition UID was requested; ignore the user option which is
@@ -1191,10 +1195,9 @@ static int read_deferred_element(struct demuxer *demuxer,
static void read_deferred_cues(demuxer_t *demuxer)
{
struct MPOpts *opts = demuxer->opts;
mkv_demuxer_t *mkv_d = demuxer->priv;
if (mkv_d->index_complete || opts->index_mode != 1)
if (mkv_d->index_complete || mkv_d->index_mode != 1)
return;
for (int n = 0; n < mkv_d->num_headers; n++) {
@@ -1855,7 +1858,6 @@ static int read_mkv_segment_header(demuxer_t *demuxer, int64_t *segment_end)
static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
{
stream_t *s = demuxer->stream;
struct MPOpts *opts = demuxer->opts;
mkv_demuxer_t *mkv_d;
int64_t start_pos;
int64_t end_pos;
@@ -1882,6 +1884,12 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
mkv_d->a_skip_preroll = 1;
mkv_d->skip_to_timecode = INT64_MIN;
mp_read_option_raw(demuxer->global, "index", &m_option_type_choice,
&mkv_d->index_mode);
mp_read_option_raw(demuxer->global, "edition", &m_option_type_choice,
&mkv_d->edition_id);
mkv_d->opts = mp_get_config_group(mkv_d, demuxer->global, &demux_mkv_conf);
if (demuxer->params && demuxer->params->matroska_was_valid)
*demuxer->params->matroska_was_valid = true;
@@ -1941,7 +1949,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
process_tags(demuxer);
probe_first_timestamp(demuxer);
if (opts->demux_mkv->probe_duration)
if (mkv_d->opts->probe_duration)
probe_last_timestamp(demuxer, start_pos);
return 0;
@@ -2730,7 +2738,6 @@ static int create_index_until(struct demuxer *demuxer, int64_t timecode)
static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
int64_t target_timecode, int flags)
{
struct MPOpts *opts = demuxer->opts;
struct mkv_demuxer *mkv_d = demuxer->priv;
struct mkv_index *index = NULL;
@@ -2758,9 +2765,9 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
if (flags & FLAG_SUBPREROLL) {
// Find the cluster with the highest filepos, that has a timestamp
// still lower than min_tc.
double secs = opts->demux_mkv->subtitle_preroll_secs;
double secs = mkv_d->opts->subtitle_preroll_secs;
if (mkv_d->index_has_durations)
secs = MPMAX(secs, opts->demux_mkv->subtitle_preroll_secs_index);
secs = MPMAX(secs, mkv_d->opts->subtitle_preroll_secs_index);
int64_t pre = MPMIN(INT64_MAX, secs * 1e9 / mkv_d->tc_scale);
int64_t min_tc = pre < index->timecode ? index->timecode - pre : 0;
uint64_t prev_target = 0;
@@ -2823,7 +2830,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, double seek_pts, int flags)
int cueflags = (flags & SEEK_BACKWARD) ? FLAG_BACKWARD : 0;
mkv_d->subtitle_preroll = NUM_SUB_PREROLL_PACKETS;
int preroll_opt = demuxer->opts->demux_mkv->subtitle_preroll;
int preroll_opt = mkv_d->opts->subtitle_preroll;
if (((flags & SEEK_HR) || preroll_opt == 1 ||
(preroll_opt == 2 && mkv_d->index_has_durations))
&& st_active[STREAM_SUB] && st_active[STREAM_VIDEO])
@@ -2917,7 +2924,7 @@ static void probe_last_timestamp(struct demuxer *demuxer, int64_t start_pos)
// In full mode, we start reading data from the current file position,
// which works because this function is called after headers are parsed.
if (demuxer->opts->demux_mkv->probe_duration != 2) {
if (mkv_d->opts->probe_duration != 2) {
read_deferred_cues(demuxer);
if (mkv_d->index_complete) {
// Find last cluster that still has video packets
@@ -2974,7 +2981,7 @@ static void probe_first_timestamp(struct demuxer *demuxer)
{
mkv_demuxer_t *mkv_d = demuxer->priv;
if (!demuxer->opts->demux_mkv->probe_start_time)
if (!mkv_d->opts->probe_start_time)
return;
struct block_info block;
+14 -12
View File
@@ -32,10 +32,10 @@
#include "mpv_talloc.h"
#include "common/msg.h"
#include "common/global.h"
#include "demux/demux.h"
#include "demux/timeline.h"
#include "demux/matroska.h"
#include "options/m_config.h"
#include "options/options.h"
#include "options/path.h"
#include "misc/bstr.h"
@@ -46,6 +46,7 @@
struct tl_ctx {
struct mp_log *log;
struct mpv_global *global;
struct MPOpts *opts;
struct timeline *tl;
struct demuxer *demuxer;
@@ -209,8 +210,7 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment)
MP_TARRAY_APPEND(NULL, ctx->sources, ctx->num_sources, NULL);
}
if (stream_wants_cache(d->stream, &ctx->global->opts->stream_cache))
{
if (stream_wants_cache(d->stream, ctx->opts->stream_cache)) {
free_demuxer_and_stream(d);
params.disable_cache = false;
params.matroska_wanted_uids = ctx->uids; // potentially reallocated, same data
@@ -247,7 +247,7 @@ static bool missing(struct tl_ctx *ctx)
static void find_ordered_chapter_sources(struct tl_ctx *ctx)
{
struct MPOpts *opts = ctx->global->opts;
struct MPOpts *opts = ctx->opts;
void *tmp = talloc_new(NULL);
int num_filenames = 0;
char **filenames = NULL;
@@ -260,7 +260,7 @@ static void find_ordered_chapter_sources(struct tl_ctx *ctx)
struct playlist *pl =
playlist_parse_file(opts->ordered_chapters_files, ctx->global);
talloc_steal(tmp, pl);
for (struct playlist_entry *e = pl->first; e; e = e->next)
for (struct playlist_entry *e = pl ? pl->first : NULL; e; e = e->next)
MP_TARRAY_APPEND(tmp, filenames, num_filenames, e->filename);
} else if (ctx->demuxer->stream->uncached_type != STREAMTYPE_FILE) {
MP_WARN(ctx, "Playback source is not a "
@@ -317,7 +317,7 @@ static int64_t add_timeline_part(struct tl_ctx *ctx,
* early; we don't want to try seeking over a one frame gap. */
int64_t join_diff = start - ctx->last_end_time;
if (ctx->num_parts == 0
|| FFABS(join_diff) > ctx->global->opts->chapter_merge_threshold * 1e6
|| FFABS(join_diff) > ctx->opts->chapter_merge_threshold * 1e6
|| source != ctx->timeline[ctx->num_parts - 1].source)
{
struct timeline_part new = {
@@ -505,20 +505,22 @@ void build_ordered_chapter_timeline(struct timeline *tl)
if (!demuxer->matroska_data.ordered_chapters)
return;
if (!demuxer->global->opts->ordered_chapters) {
MP_INFO(demuxer, "File uses ordered chapters, but "
"you have disabled support for them. Ignoring.\n");
return;
}
struct tl_ctx *ctx = talloc_ptrtype(tl, ctx);
*ctx = (struct tl_ctx){
.log = tl->log,
.global = tl->global,
.tl = tl,
.demuxer = demuxer,
.opts = mp_get_config_group(ctx, tl->global, NULL),
};
if (!ctx->opts->ordered_chapters) {
MP_INFO(demuxer, "File uses ordered chapters, but "
"you have disabled support for them. Ignoring.\n");
talloc_free(ctx);
return;
}
MP_INFO(ctx, "File uses ordered chapters, will build edit timeline.\n");
struct matroska_data *m = &demuxer->matroska_data;
+9 -3
View File
@@ -22,8 +22,8 @@
#include <unistd.h>
#include <string.h>
#include "options/m_config.h"
#include "options/m_option.h"
#include "options/options.h"
#include "stream/stream.h"
#include "demux.h"
@@ -129,7 +129,8 @@ struct priv {
static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
{
struct demux_rawaudio_opts *opts = demuxer->opts->demux_rawaudio;
struct demux_rawaudio_opts *opts =
mp_get_config_group(demuxer, demuxer->global, &demux_rawaudio_conf);
if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE)
return -1;
@@ -145,6 +146,9 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
c->force_channels = true;
c->samplerate = opts->samplerate;
c->native_tb_num = 1;
c->native_tb_den = c->samplerate;
int f = opts->aformat;
// See PCM(): sign float bits endian
mp_set_pcm_codec(sh->codec, f & 1, f & 2, f >> 3, f & 4);
@@ -166,7 +170,8 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check)
{
struct demux_rawvideo_opts *opts = demuxer->opts->demux_rawvideo;
struct demux_rawvideo_opts *opts =
mp_get_config_group(demuxer, demuxer->global, &demux_rawvideo_conf);
if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE)
return -1;
@@ -233,6 +238,7 @@ static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check)
c->codec = decoder;
c->codec_tag = imgfmt;
c->fps = opts->fps;
c->reliable_fps = true;
c->disp_w = width;
c->disp_h = height;
demux_add_sh_stream(demuxer, sh);
+16 -8
View File
@@ -25,15 +25,23 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
if (check > DEMUX_CHECK_REQUEST || demuxer->stream->type != STREAMTYPE_TV)
return -1;
tv_param_t *params = m_sub_options_copy(demuxer, &tv_params_conf,
demuxer->opts->tv_params);
struct tv_stream_params *sparams = demuxer->stream->priv;
if (sparams->channel && sparams->channel[0]) {
talloc_free(params->channel);
params->channel = talloc_strdup(NULL, sparams->channel);
tv_param_t *params = mp_get_config_group(demuxer, demuxer->global,
&tv_params_conf);
bstr urlparams = bstr0(demuxer->stream->path);
bstr channel, input;
bstr_split_tok(urlparams, "/", &channel, &input);
if (channel.len) {
talloc_free(params->channels);
params->channel = bstrto0(NULL, channel);
}
if (input.len) {
bstr r;
params->input = bstrtoll(input, &r, 0);
if (r.len) {
MP_ERR(demuxer->stream, "invalid input: '%.*s'\n", BSTR_P(input));
return -1;
}
}
if (sparams->input >= 0)
params->input = sparams->input;
assert(demuxer->priv==NULL);
if(!(tvh=tv_begin(params, demuxer->log))) return -1;
+5 -1
View File
@@ -74,6 +74,9 @@ struct mp_codec_params {
struct AVCodecContext *lav_headers;
struct AVCodecParameters *lav_codecpar;
// Timestamp granularity for converting double<->rational timestamps.
int native_tb_num, native_tb_den;
// STREAM_AUDIO
int samplerate;
struct mp_chmap channels;
@@ -84,7 +87,8 @@ struct mp_codec_params {
// STREAM_VIDEO
bool avi_dts; // use DTS timing; first frame and DTS is 0
float fps; // frames per second (set only if constant fps)
double fps; // frames per second (set only if constant fps)
bool reliable_fps; // the fps field is definitely not broken
int par_w, par_h; // pixel aspect ratio (0 if unknown/square)
int disp_w, disp_h; // display size
int rotate; // intended display rotation, in degrees, [0, 359]
+47
View File
@@ -0,0 +1,47 @@
# This file is baked into the mpv binary at compile time, and automatically
# loaded at early initialization time. Some of the profiles are automatically
# applied at later stages during loading.
[pseudo-gui]
player-operation-mode=pseudo-gui
[builtin-pseudo-gui]
terminal=no
force-window=yes
idle=once
screenshot-directory=~~desktop/
[libmpv]
config=no
idle=yes
terminal=no
input-terminal=no
osc=no
ytdl=no
input-default-bindings=no
input-vo-keyboard=no
stop-playback-on-init-failure=yes
# OSX/Cocoa global input hooks
input-appleremote=no
input-media-keys=no
input-app-events=no
[encoding]
vo=lavc
ao=lavc
keep-open=no
force-window=no
gapless-audio=yes
resume-playback=no
load-scripts=no
osc=no
framedrop=no
[opengl-hq]
scale=spline36
cscale=spline36
dscale=mitchell
dither-depth=auto
correct-downscaling=yes
sigmoid-upscaling=yes
deband=yes
+2 -2
View File
@@ -109,10 +109,10 @@
#t add sub-pos +1 # down
#v cycle sub-visibility
# stretch SSA/ASS subtitles with anamorphic videos to match historical
#V cycle ass-vsfilter-aspect-compat
#V cycle sub-ass-vsfilter-aspect-compat
# switch between applying no style overrides to SSA/ASS subtitles, and
# overriding them almost completely with the normal subtitle style
#u cycle-values ass-style-override "force" "no"
#u cycle-values sub-ass-style-override "force" "no"
#j cycle sub # cycle through subtitles
#J cycle sub down # ...backwards
#SHARP cycle audio # switch audio streams
+5 -3
View File
@@ -53,9 +53,11 @@
#ontop=yes
# Specify default video driver (see --vo=help for a list).
# This one selects high quality video scaling etc. - can cause problems with
# some drivers and GPUs.
#vo=opengl-hq
#vo=opengl
# Specify high quality video rendering preset (for OpenGL VO only)
# Can cause performance problems with some drivers and GPUs.
#profile=opengl-hq
# Force video to lock on the display's refresh rate, and change video and audio
# speed to some degree to ensure synchronous playback - can cause problems
+1 -1
View File
@@ -24,7 +24,7 @@ Comment[zh-CN]=播放电影和歌曲
Comment[zh-TW]=播放電影和歌曲
Icon=mpv
TryExec=mpv
Exec=mpv --profile=pseudo-gui -- %U
Exec=mpv --player-operation-mode=pseudo-gui -- %U
Terminal=false
Categories=AudioVideo;Audio;Video;Player;TV;
MimeType=application/ogg;application/x-ogg;application/sdp;application/smil;application/x-smil;application/streamingmedia;application/x-streamingmedia;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;audio/aac;audio/x-aac;audio/m4a;audio/x-m4a;audio/mp1;audio/x-mp1;audio/mp2;audio/x-mp2;audio/mp3;audio/x-mp3;audio/mpeg;audio/x-mpeg;audio/mpegurl;audio/x-mpegurl;audio/mpg;audio/x-mpg;audio/rn-mpeg;audio/ogg;audio/scpls;audio/x-scpls;audio/vnd.rn-realaudio;audio/wav;audio/x-pn-windows-pcm;audio/x-realaudio;audio/x-pn-realaudio;audio/x-ms-wma;audio/x-pls;audio/x-wav;video/mpeg;video/x-mpeg;video/x-mpeg2;video/mp4;video/msvideo;video/x-msvideo;video/ogg;video/quicktime;video/vnd.rn-realvideo;video/x-ms-afs;video/x-ms-asf;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvxvideo;video/x-avi;video/x-fli;video/x-flv;video/x-theora;video/x-matroska;video/webm;audio/x-flac;audio/x-vorbis+ogg;video/x-ogm+ogg;audio/x-shorten;audio/x-ape;audio/x-wavpack;audio/x-tta;audio/AMR;audio/ac3;video/mp2t;audio/flac;audio/mp4;
+4 -2
View File
@@ -186,8 +186,6 @@ const struct mp_cmd_def mp_cmds[] = {
{ MP_CMD_VF, "vf", { ARG_STRING, ARG_STRING } },
{ MP_CMD_VF_COMMAND, "vf-command", { ARG_STRING, ARG_STRING, ARG_STRING } },
{ MP_CMD_VO_CMDLINE, "vo-cmdline", { ARG_STRING } },
{ MP_CMD_SCRIPT_BINDING, "script-binding", { ARG_STRING },
.allow_auto_repeat = true, .on_updown = true},
@@ -226,6 +224,10 @@ const struct mp_cmd_def mp_cmds[] = {
{"reselect", 1})),
}},
{ MP_CMD_APPLY_PROFILE, "apply-profile", {ARG_STRING } },
{ MP_CMD_LOAD_SCRIPT, "load-script", {ARG_STRING} },
{0}
};
+4 -3
View File
@@ -99,9 +99,6 @@ enum mp_command_type {
MP_CMD_VF,
MP_CMD_VF_COMMAND,
/// Video output commands
MP_CMD_VO_CMDLINE,
/// Internal for Lua scripts
MP_CMD_SCRIPT_BINDING,
MP_CMD_SCRIPT_MESSAGE,
@@ -117,6 +114,10 @@ enum mp_command_type {
MP_CMD_RESCAN_EXTERNAL_FILES,
MP_CMD_APPLY_PROFILE,
MP_CMD_LOAD_SCRIPT,
// Internal
MP_CMD_COMMAND_LIST, // list of sub-commands in args[0].v.p
};
+110 -83
View File
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -34,7 +35,6 @@
#include <libavutil/common.h>
#include "osdep/io.h"
#include "osdep/semaphore.h"
#include "misc/rendezvous.h"
#include "input.h"
@@ -73,6 +73,7 @@ struct cmd_bind {
};
struct cmd_bind_section {
char *owner;
struct cmd_bind *binds;
int num_binds;
char *section;
@@ -96,15 +97,13 @@ struct cmd_queue {
struct input_ctx {
pthread_mutex_t mutex;
sem_t wakeup;
struct mp_log *log;
struct mpv_global *global;
struct m_config_cache *opts_cache;
struct input_opts *opts;
bool using_alt_gr;
bool using_ar;
bool using_cocoa_media_keys;
bool win_drag;
// Autorepeat stuff
short ar_state;
@@ -146,6 +145,9 @@ struct input_ctx {
struct cmd_queue cmd_queue;
struct mp_cancel *cancel;
void (*wakeup_cb)(void *ctx);
void *wakeup_ctx;
};
static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
@@ -170,28 +172,30 @@ struct input_opts {
int enable_mouse_movements;
int vo_key_input;
int test;
int allow_win_drag;
};
const struct m_sub_options input_config = {
.opts = (const m_option_t[]) {
OPT_STRING("conf", config_file, CONF_GLOBAL | M_OPT_FILE),
OPT_INT("ar-delay", ar_delay, CONF_GLOBAL),
OPT_INT("ar-rate", ar_rate, CONF_GLOBAL),
OPT_PRINT("keylist", mp_print_key_list),
OPT_PRINT("cmdlist", mp_print_cmd_list),
OPT_FLAG("default-bindings", default_bindings, CONF_GLOBAL),
OPT_FLAG("test", test, CONF_GLOBAL),
OPT_INTRANGE("doubleclick-time", doubleclick_time, 0, 0, 1000),
OPT_FLAG("right-alt-gr", use_alt_gr, CONF_GLOBAL),
OPT_INTRANGE("key-fifo-size", key_fifo_size, CONF_GLOBAL, 2, 65000),
OPT_FLAG("cursor", enable_mouse_movements, CONF_GLOBAL),
OPT_FLAG("vo-keyboard", vo_key_input, CONF_GLOBAL),
OPT_FLAG("x11-keyboard", vo_key_input, CONF_GLOBAL), // old alias
OPT_STRING("input-conf", config_file, M_OPT_FIXED | M_OPT_FILE),
OPT_INT("input-ar-delay", ar_delay, 0),
OPT_INT("input-ar-rate", ar_rate, 0),
OPT_PRINT("input-keylist", mp_print_key_list),
OPT_PRINT("input-cmdlist", mp_print_cmd_list),
OPT_FLAG("input-default-bindings", default_bindings, 0),
OPT_FLAG("input-test", test, 0),
OPT_INTRANGE("input-doubleclick-time", doubleclick_time, 0, 0, 1000),
OPT_FLAG("input-right-alt-gr", use_alt_gr, 0),
OPT_INTRANGE("input-key-fifo-size", key_fifo_size, 0, 2, 65000),
OPT_FLAG("input-cursor", enable_mouse_movements, 0),
OPT_FLAG("input-vo-keyboard", vo_key_input, 0),
#if HAVE_COCOA
OPT_FLAG("appleremote", use_appleremote, CONF_GLOBAL),
OPT_FLAG("media-keys", use_media_keys, CONF_GLOBAL),
OPT_FLAG("app-events", use_app_events, CONF_GLOBAL),
OPT_FLAG("input-appleremote", use_appleremote, 0),
OPT_FLAG("input-media-keys", use_media_keys, 0),
OPT_FLAG("input-app-events", use_app_events, M_OPT_FIXED),
#endif
OPT_FLAG("window-dragging", allow_win_drag, 0),
OPT_REPLACED("input-x11-keyboard", "input-vo-keyboard"),
{0}
},
.size = sizeof(struct input_opts),
@@ -209,7 +213,9 @@ const struct m_sub_options input_config = {
#endif
.default_bindings = 1,
.vo_key_input = 1,
.allow_win_drag = 1,
},
.change_flags = UPDATE_INPUT,
};
static const char builtin_input_conf[] =
@@ -845,33 +851,18 @@ static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
return NULL;
}
void mp_input_wait(struct input_ctx *ictx, double seconds)
double mp_input_get_delay(struct input_ctx *ictx)
{
input_lock(ictx);
double seconds = INFINITY;
adjust_max_wait_time(ictx, &seconds);
input_unlock(ictx);
while (sem_trywait(&ictx->wakeup) == 0)
seconds = -1;
if (seconds > 0) {
MP_STATS(ictx, "start sleep");
struct timespec ts =
mp_time_us_to_timespec(mp_add_timeout(mp_time_us(), seconds));
sem_timedwait(&ictx->wakeup, &ts);
MP_STATS(ictx, "end sleep");
}
}
void mp_input_wakeup_nolock(struct input_ctx *ictx)
{
// Some audio APIs discourage use of locking in their audio callback,
// and these audio callbacks happen to call mp_input_wakeup_nolock()
// when new data is needed. This is why we use semaphores here.
sem_post(&ictx->wakeup);
return seconds;
}
void mp_input_wakeup(struct input_ctx *ictx)
{
mp_input_wakeup_nolock(ictx);
ictx->wakeup_cb(ictx->wakeup_ctx);
}
mp_cmd_t *mp_input_read_cmd(struct input_ctx *ictx)
@@ -996,7 +987,8 @@ bool mp_input_test_mouse_active(struct input_ctx *ictx, int x, int y)
bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y)
{
input_lock(ictx);
bool r = !ictx->win_drag || test_mouse(ictx, x, y, MP_INPUT_ALLOW_VO_DRAGGING);
bool r = !ictx->opts->allow_win_drag ||
test_mouse(ictx, x, y, MP_INPUT_ALLOW_VO_DRAGGING);
input_unlock(ictx);
return r;
}
@@ -1021,13 +1013,19 @@ static void remove_binds(struct cmd_bind_section *bs, bool builtin)
}
void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
char *contents, bool builtin)
char *contents, bool builtin, char *owner)
{
if (!name || !name[0])
return; // parse_config() changes semantics with restrict_section==empty
input_lock(ictx);
// Delete:
struct cmd_bind_section *bs = get_bind_section(ictx, bstr0(name));
if ((!bs->owner || (owner && strcmp(bs->owner, owner) != 0)) &&
strcmp(bs->section, "default") != 0)
{
talloc_free(bs->owner);
bs->owner = talloc_strdup(bs, owner);
}
remove_binds(bs, builtin);
if (contents && contents[0]) {
// Redefine:
@@ -1039,6 +1037,21 @@ void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
input_unlock(ictx);
}
void mp_input_remove_sections_by_owner(struct input_ctx *ictx, char *owner)
{
input_lock(ictx);
struct cmd_bind_section *bs = ictx->cmd_bind_sections;
while (bs) {
if (bs->owner && owner && strcmp(bs->owner, owner) == 0) {
mp_input_disable_section(ictx, bs->section);
remove_binds(bs, false);
remove_binds(bs, true);
}
bs = bs->next;
}
input_unlock(ictx);
}
static bool bind_matches_key(struct cmd_bind *bind, int num_keys, const int *keys)
{
if (bind->num_keys != num_keys)
@@ -1195,22 +1208,23 @@ done:
return r;
}
struct input_ctx *mp_input_init(struct mpv_global *global)
struct input_ctx *mp_input_init(struct mpv_global *global,
void (*wakeup_cb)(void *ctx),
void *wakeup_ctx)
{
struct input_ctx *ictx = talloc_ptrtype(NULL, ictx);
*ictx = (struct input_ctx){
.global = global,
.opts = talloc_zero(ictx, struct input_opts), // replaced later
.ar_state = -1,
.log = mp_log_new(ictx, global->log, "input"),
.mouse_section = "default",
.opts_cache = m_config_cache_alloc(ictx, global, &input_config),
.wakeup_cb = wakeup_cb,
.wakeup_ctx = wakeup_ctx,
};
if (sem_init(&ictx->wakeup, 0, 0)) {
MP_FATAL(ictx, "mpv doesn't work on systems without POSIX semaphores.\n");
abort();
}
ictx->opts = ictx->opts_cache->opts;
mpthread_mutex_init_recursive(&ictx->mutex);
@@ -1221,13 +1235,45 @@ struct input_ctx *mp_input_init(struct mpv_global *global)
return ictx;
}
void mp_input_load(struct input_ctx *ictx)
static void reload_opts(struct input_ctx *ictx, bool shutdown)
{
struct input_opts *input_conf =
m_sub_options_copy(ictx, &input_config, ictx->global->opts->input_opts);
m_config_cache_update(ictx->opts_cache);
talloc_free(ictx->opts);
ictx->opts = input_conf;
#if HAVE_COCOA
struct input_opts *opts = ictx->opts;
if (ictx->using_ar != (opts->use_appleremote && !shutdown)) {
ictx->using_ar = !ictx->using_ar;
if (ictx->using_ar) {
cocoa_init_apple_remote();
} else {
cocoa_uninit_apple_remote();
}
}
if (ictx->using_cocoa_media_keys != (opts->use_media_keys && !shutdown)) {
ictx->using_cocoa_media_keys = !ictx->using_cocoa_media_keys;
if (ictx->using_cocoa_media_keys) {
cocoa_init_media_keys();
} else {
cocoa_uninit_media_keys();
}
}
#endif
}
void mp_input_update_opts(struct input_ctx *ictx)
{
input_lock(ictx);
reload_opts(ictx, false);
input_unlock(ictx);
}
void mp_input_load_config(struct input_ctx *ictx)
{
input_lock(ictx);
reload_opts(ictx, false);
// "Uncomment" the default key bindings in etc/input.conf and add them.
// All lines that do not start with '# ' are parsed.
@@ -1240,8 +1286,8 @@ void mp_input_load(struct input_ctx *ictx)
}
bool config_ok = false;
if (input_conf->config_file)
config_ok = parse_config_file(ictx, input_conf->config_file, true);
if (ictx->opts->config_file && ictx->opts->config_file[0])
config_ok = parse_config_file(ictx, ictx->opts->config_file, true);
if (!config_ok) {
// Try global conf dir
void *tmp = talloc_new(NULL);
@@ -1251,32 +1297,17 @@ void mp_input_load(struct input_ctx *ictx)
talloc_free(tmp);
}
if (input_conf->use_alt_gr) {
ictx->using_alt_gr = true;
}
#if HAVE_COCOA
if (input_conf->use_app_events) {
if (ictx->opts->use_app_events)
cocoa_start_event_monitor();
}
if (input_conf->use_appleremote) {
cocoa_init_apple_remote();
ictx->using_ar = true;
}
if (input_conf->use_media_keys) {
cocoa_init_media_keys();
ictx->using_cocoa_media_keys = true;
}
#endif
ictx->win_drag = ictx->global->opts->allow_win_drag;
#if defined(__MINGW32__)
if (ictx->global->opts->input_file && *ictx->global->opts->input_file)
mp_input_pipe_add(ictx, ictx->global->opts->input_file);
#endif
input_unlock(ictx);
}
static void clear_queue(struct cmd_queue *queue)
@@ -1293,21 +1324,14 @@ void mp_input_uninit(struct input_ctx *ictx)
if (!ictx)
return;
#if HAVE_COCOA
if (ictx->using_ar) {
cocoa_uninit_apple_remote();
}
if (ictx->using_cocoa_media_keys) {
cocoa_uninit_media_keys();
}
#endif
input_lock(ictx);
reload_opts(ictx, true);
input_unlock(ictx);
close_input_sources(ictx);
clear_queue(&ictx->cmd_queue);
talloc_free(ictx->current_down_cmd);
pthread_mutex_destroy(&ictx->mutex);
sem_destroy(&ictx->wakeup);
talloc_free(ictx);
}
@@ -1320,7 +1344,10 @@ void mp_input_set_cancel(struct input_ctx *ictx, struct mp_cancel *cancel)
bool mp_input_use_alt_gr(struct input_ctx *ictx)
{
return ictx->using_alt_gr;
input_lock(ictx);
bool r = ictx->opts->use_alt_gr;
input_unlock(ictx);
return r;
}
struct mp_cmd *mp_input_parse_cmd(struct input_ctx *ictx, bstr str,
+14 -9
View File
@@ -196,9 +196,13 @@ void mp_input_disable_all_sections(struct input_ctx *ictx);
// builtin: create as builtin section; this means if the user defines bindings
// using "{name}", they won't be ignored or overwritten - instead,
// they are preferred to the bindings defined with this call
// owner: string ID of the client which defined this, or NULL
// If the section already exists, its bindings are removed and replaced.
void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
char *contents, bool builtin);
char *contents, bool builtin, char *owner);
// Remove all sections that have been defined by the given owner.
void mp_input_remove_sections_by_owner(struct input_ctx *ictx, char *owner);
// Define where on the screen the named input section should receive.
// Setting a rectangle of size 0 unsets the mouse area.
@@ -219,22 +223,23 @@ bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y);
// Initialize the input system
struct mpv_global;
struct input_ctx *mp_input_init(struct mpv_global *global);
struct input_ctx *mp_input_init(struct mpv_global *global,
void (*wakeup_cb)(void *ctx),
void *wakeup_ctx);
// Load config, options, and devices.
void mp_input_load(struct input_ctx *ictx);
void mp_input_load_config(struct input_ctx *ictx);
void mp_input_update_opts(struct input_ctx *ictx);
void mp_input_uninit(struct input_ctx *ictx);
// Sleep for the given amount of seconds, until mp_input_wakeup() is called,
// or new input arrives. seconds<=0 returns immediately.
void mp_input_wait(struct input_ctx *ictx, double seconds);
// Return number of seconds until the next autorepeat event will be generated.
// Returns INFINITY if no autorepeated key is active.
double mp_input_get_delay(struct input_ctx *ictx);
// Wake up sleeping input loop from another thread.
void mp_input_wakeup(struct input_ctx *ictx);
void mp_input_wakeup_nolock(struct input_ctx *ictx);
// Used to asynchronously abort playback. Needed because the core still can
// block on network in some situations.
struct mp_cancel;
+9 -5
View File
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -97,6 +98,11 @@ static void *client_thread(void *p)
{
pthread_detach(pthread_self());
// We don't use MSG_NOSIGNAL because the moldy fruit OS doesn't support it.
struct sigaction sa = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART };
sigfillset(&sa.sa_mask);
sigaction(SIGPIPE, &sa, NULL);
int rc;
struct client_arg *arg = p;
@@ -118,15 +124,11 @@ static void *client_thread(void *p)
};
fcntl(arg->client_fd, F_SETFL, fcntl(arg->client_fd, F_GETFL, 0) | O_NONBLOCK);
mpv_suspend(arg->client);
while (1) {
rc = poll(fds, 2, 0);
if (rc == 0) {
mpv_resume(arg->client);
if (rc == 0)
rc = poll(fds, 2, -1);
mpv_suspend(arg->client);
}
if (rc < 0) {
MP_ERR(arg, "Poll error\n");
continue;
@@ -337,6 +339,8 @@ static void *ipc_thread(void *p)
goto done;
}
MP_VERBOSE(arg, "Listening to IPC socket.\n");
int client_num = 0;
struct pollfd fds[2] = {
+3 -5
View File
@@ -222,7 +222,6 @@ static void *client_thread(void *p)
MP_VERBOSE(arg, "Client connected\n");
mpv_set_wakeup_callback(arg->client, wakeup_cb, wakeup_event);
mpv_suspend(arg->client);
// Do the first read operation on the pipe
if ((ioerr = async_read(arg->client_h, buf, 4096, &ol))) {
@@ -233,11 +232,8 @@ static void *client_thread(void *p)
while (1) {
HANDLE handles[] = { wakeup_event, ol.hEvent };
int n = WaitForMultipleObjects(2, handles, FALSE, 0);
if (n == WAIT_TIMEOUT) {
mpv_resume(arg->client);
if (n == WAIT_TIMEOUT)
n = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
mpv_suspend(arg->client);
}
switch (n) {
case WAIT_OBJECT_0: // wakeup_event
@@ -381,6 +377,8 @@ static void *ipc_thread(void *p)
goto done;
}
MP_VERBOSE(arg, "Listening to IPC pipe.\n");
while (1) {
DWORD err = ConnectNamedPipe(server, &ol) ? 0 : GetLastError();
+1 -1
View File
@@ -19,7 +19,7 @@
#include <io.h>
#include "common/msg.h"
#include "osdep/atomics.h"
#include "osdep/atomic.h"
#include "osdep/io.h"
#include "input.h"
+58 -20
View File
@@ -135,10 +135,6 @@ extern "C" {
* (used through libass), ALSA, FFmpeg, and possibly more.
* - The FPU precision must be set at least to double precision.
* - On Windows, mpv will call timeBeginPeriod(1).
* - On UNIX, every mpv_initialize() call will block SIGPIPE. This is done
* because FFmpeg makes unsafe use of OpenSSL and GnuTLS, which can raise
* this signal under certain circumstances. Once these libraries (or FFmpeg)
* are fixed, libmpv will not block the signal anymore.
* - On memory exhaustion, mpv will kill the process.
*
* Encoding of filenames
@@ -215,7 +211,7 @@ extern "C" {
* relational operators (<, >, <=, >=).
*/
#define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 22)
#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 23)
/**
* Return the MPV_CLIENT_API_VERSION the mpv source has been compiled with.
@@ -370,10 +366,11 @@ const char *mpv_client_name(mpv_handle *ctx);
* and needs to be initialized to be actually used with most other API
* functions.
*
* Most API functions will return MPV_ERROR_UNINITIALIZED in the uninitialized
* state. You can call mpv_set_option() (or mpv_set_option_string() and other
* variants) to set initial options. After this, call mpv_initialize() to start
* the player, and then use e.g. mpv_command() to start playback of a file.
* Some API functions will return MPV_ERROR_UNINITIALIZED in the uninitialized
* state. You can call mpv_set_property() (or mpv_set_property_string() and
* other variants, and before mpv 0.21.0 mpv_set_option() etc.) to set initial
* options. After this, call mpv_initialize() to start the player, and then use
* e.g. mpv_command() to start playback of a file.
*
* The point of separating handle creation and actual initialization is that
* you can configure things which can't be changed during runtime.
@@ -401,7 +398,7 @@ const char *mpv_client_name(mpv_handle *ctx);
* options.
*
* The mpv command line parser is not available through this API, but you can
* set individual options with mpv_set_option(). Files for playback must be
* set individual options with mpv_set_property(). Files for playback must be
* loaded with mpv_command() or others.
*
* Note that you should avoid doing concurrent accesses on the uninitialized
@@ -422,6 +419,17 @@ mpv_handle *mpv_create(void);
* This function needs to be called to make full use of the client API if the
* client API handle was created with mpv_create().
*
* Only the following options require to be set _before_ mpv_initialize():
* - options which are only read at initialization time:
* - config
* - config-dir
* - input-conf
* - load-scripts
* - script
* - player-operation-mode
* - input-app-events (OSX)
* - all encoding mode options
*
* @return error code
*/
int mpv_initialize(mpv_handle *ctx);
@@ -492,10 +500,6 @@ mpv_handle *mpv_create_client(mpv_handle *ctx, const char *name);
* possible that some options were successfully set even if any of these errors
* happen.
*
* The same restrictions as with mpv_set_option() apply: some options can't
* be set outside of idle or uninitialized state, and many options don't
* take effect immediately.
*
* @param filename absolute path to the config file on the local filesystem
* @return error code
*/
@@ -518,6 +522,11 @@ int mpv_load_config_file(mpv_handle *ctx, const char *filename);
* mpv_suspend() is not allowed.
*
* Calling this on an uninitialized player (see mpv_create()) will deadlock.
*
* @deprecated This function, as well as mpv_resume(), are deprecated, and
* will stop doing anything soon. Their semantics were never
* well-defined, and their usefulness is extremely limited. The
* calls will remain stubs in order to keep ABI compatibility.
*/
void mpv_suspend(mpv_handle *ctx);
@@ -778,16 +787,36 @@ void mpv_free_node_contents(mpv_node *node);
* works in uninitialized state (see mpv_create()), and in some cases in at
* runtime.
*
* Changing options at runtime does not always work. For some options, attempts
* to change them simply fails. Many other options may require reloading the
* file for changes to take effect. In general, you should prefer calling
* mpv_set_property() to change settings during playback, because the property
* mechanism guarantees that changes take effect immediately.
*
* Using a format other than MPV_FORMAT_NODE is equivalent to constructing a
* mpv_node with the given format and data, and passing the mpv_node to this
* function.
*
* Note: this is semi-deprecated. For most purposes, this is not needed anymore.
* Starting with mpv version 0.21.0 (version 1.23) most options can be set
* with mpv_set_property() (and related functions), and even before
* mpv_initialize(). In some obscure corner cases, using this function
* to set options might still be required (see below, and also section
* "Inconsistencies between options and properties" on the manpage). Once
* these are resolved, the option setting functions might be fully
* deprecated.
*
* The following options still need to be set either _before_
* mpv_initialize() with mpv_set_property() (or related functions), or
* with mpv_set_option() (or related functions) at any time:
* - options shadowed by deprecated properties:
* - demuxer (property deprecated in 0.21.0)
* - idle (property deprecated in 0.21.0)
* - fps (property deprecated in 0.21.0)
* - cache (property deprecated in 0.21.0)
* - length (property deprecated in 0.10.0)
* - audio-samplerate (property deprecated in 0.10.0)
* - audio-channels (property deprecated in 0.10.0)
* - audio-format (property deprecated in 0.10.0)
* - deprecated options shadowed by properties:
* - chapter (option deprecated in 0.21.0)
* - playlist-pos (option deprecated in 0.21.0)
* The deprecated properties will be removed in mpv 0.22.0.
*
* @param name Option name. This is the same as on the mpv command line, but
* without the leading "--".
* @param format see enum mpv_format.
@@ -893,6 +922,15 @@ int mpv_command_node_async(mpv_handle *ctx, uint64_t reply_userdata,
* mpv_node with the given format and data, and passing the mpv_node to this
* function. (Before API version 1.21, this was different.)
*
* Note: starting with mpv 0.21.0 (client API version 1.23), this can be used to
* set options in general. It even can be used before mpv_initialize()
* has been called. If called before mpv_initialize(), setting properties
* not backed by options will result in MPV_ERROR_PROPERTY_UNAVAILABLE.
* In some cases, properties and options still conflict. In these cases,
* mpv_set_property() accesses the options before mpv_initialize(), and
* the properties after mpv_initialize(). These conflicts will be removed
* in mpv 0.22.0. See mpv_set_option() for further remarks.
*
* @param name The property name. See input.rst for a list of properties.
* @param format see enum mpv_format.
* @param[in] data Option value.
+23
View File
@@ -190,6 +190,29 @@ extern "C" {
* In previous libmpv releases, this used "GL_MP_D3D_interfaces" and
* "glMPGetD3DInterface". This is deprecated; use glMPGetNativeDisplay instead
* (the semantics are 100% compatible).
*
* Windowing system interop on RPI
* -------------------------------
*
* The RPI uses no proper interop, but hardware overlays instead. To place the
* overlay correctly, you can communicate the window parameters as follows to
* libmpv. gl->MPGetNativeDisplay("MPV_RPI_WINDOW") return an array of type int
* with the following 4 elements:
* 0: display number (default 0)
* 1: layer number of the GL layer - video will be placed in the layer
* directly below (default: 0)
* 2: absolute x position of the GL context (default: 0)
* 3: absolute y position of the GL context (default: 0)
* The (x,y) position must be the absolute screen pixel position of the
* top/left pixel of the dispmanx layer used for the GL context. If you render
* to a FBO, the position must be that of the final position of the FBO
* contents on screen. You can't transform or scale the video other than what
* mpv will render to the video overlay. The defaults are suitable for
* rendering the video at fullscreen.
* The parameters are checked on every draw by calling MPGetNativeDisplay and
* checking the values in the returned array for changes. The returned array
* must remain valid until the libmpv render function returns; then it can be
* deallocated by the API user.
*/
/**
+96
View File
@@ -29,6 +29,7 @@
#include <QList>
#include <QHash>
#include <QSharedPointer>
#include <QMetaType>
#include <mpv/client.h>
@@ -227,6 +228,8 @@ struct node_autofree {
* Return the given property as mpv_node converted to QVariant, or QVariant()
* on error.
*
* @deprecated use get_property() instead
*
* @param name the property name
*/
static inline QVariant get_property_variant(mpv_handle *ctx, const QString &name)
@@ -240,6 +243,8 @@ static inline QVariant get_property_variant(mpv_handle *ctx, const QString &name
/**
* Set the given property as mpv_node converted from the QVariant argument.
* @deprecated use set_property() instead
*/
static inline int set_property_variant(mpv_handle *ctx, const QString &name,
const QVariant &v)
@@ -250,6 +255,8 @@ static inline int set_property_variant(mpv_handle *ctx, const QString &name,
/**
* Set the given option as mpv_node converted from the QVariant argument.
*
* @deprecated use set_property() instead
*/
static inline int set_option_variant(mpv_handle *ctx, const QString &name,
const QVariant &v)
@@ -261,6 +268,8 @@ static inline int set_option_variant(mpv_handle *ctx, const QString &name,
/**
* mpv_command_node() equivalent. Returns QVariant() on error (and
* unfortunately, the same on success).
*
* @deprecated use command() instead
*/
static inline QVariant command_variant(mpv_handle *ctx, const QVariant &args)
{
@@ -272,7 +281,94 @@ static inline QVariant command_variant(mpv_handle *ctx, const QVariant &args)
return node_to_variant(&res);
}
/**
* This is used to return error codes wrapped in QVariant for functions which
* return QVariant.
*
* You can use get_error() or is_error() to extract the error status from a
* QVariant value.
*/
struct ErrorReturn
{
/**
* enum mpv_error value (or a value outside of it if ABI was extended)
*/
int error;
ErrorReturn() : error(0) {}
explicit ErrorReturn(int err) : error(err) {}
};
/**
* Return the mpv error code packed into a QVariant, or 0 (success) if it's not
* an error value.
*
* @return error code (<0) or success (>=0)
*/
static inline int get_error(const QVariant &v)
{
if (!v.canConvert<ErrorReturn>())
return 0;
return v.value<ErrorReturn>().error;
}
/**
* Return whether the QVariant carries a mpv error code.
*/
static inline bool is_error(const QVariant &v)
{
return get_error(v) < 0;
}
/**
* Return the given property as mpv_node converted to QVariant, or QVariant()
* on error.
*
* @param name the property name
* @return the property value, or an ErrorReturn with the error code
*/
static inline QVariant get_property(mpv_handle *ctx, const QString &name)
{
mpv_node node;
int err = mpv_get_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, &node);
if (err < 0)
return QVariant::fromValue(ErrorReturn(err));
node_autofree f(&node);
return node_to_variant(&node);
}
/**
* Set the given property as mpv_node converted from the QVariant argument.
*
* @return mpv error code (<0 on error, >= 0 on success)
*/
static inline int set_property(mpv_handle *ctx, const QString &name,
const QVariant &v)
{
node_builder node(v);
return mpv_set_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, node.node());
}
/**
* mpv_command_node() equivalent.
*
* @param args command arguments, with args[0] being the command name as string
* @return the property value, or an ErrorReturn with the error code
*/
static inline QVariant command(mpv_handle *ctx, const QVariant &args)
{
node_builder node(args);
mpv_node res;
int err = mpv_command_node(ctx, node.node(), &res);
if (err < 0)
return QVariant::fromValue(ErrorReturn(err));
node_autofree f(&res);
return node_to_variant(&res);
}
}
}
Q_DECLARE_METATYPE(mpv::qt::ErrorReturn)
#endif
+5
View File
@@ -291,6 +291,11 @@ bstr mp_iconv_to_utf8(struct mp_log *log, bstr buf, const char *cp, int flags)
if (strcasecmp(cp, "UTF-8-BROKEN") == 0)
return bstr_sanitize_utf8_latin1(NULL, buf);
// Force CP949 over EUC-KR since iconv distinguishes them and
// EUC-KR causes error on CP949 encoded data
if (strcasecmp(cp, "EUC-KR") == 0)
cp = "CP949";
iconv_t icdsc;
if ((icdsc = iconv_open("UTF-8", cp)) == (iconv_t) (-1)) {
if (flags & MP_ICONV_VERBOSE)
+132 -73
View File
@@ -28,19 +28,31 @@ struct mp_dispatch_queue {
struct mp_dispatch_item *head, *tail;
pthread_mutex_t lock;
pthread_cond_t cond;
int suspend_requested;
bool suspended;
void (*wakeup_fn)(void *wakeup_ctx);
void *wakeup_ctx;
// This lock grant access to the target thread's state during suspend mode.
// During suspend mode, the target thread is blocked in the function
// mp_dispatch_queue_process(), however this function may be processing
// dispatch queue items. This lock serializes the dispatch queue processing
// and external mp_dispatch_lock() calls.
// Invariant: can be held only while suspended==true, and suspend_requested
// must be >0 (unless mp_dispatch_queue_process() locks it). In particular,
// suspend mode must not be left while the lock is held.
pthread_mutex_t exclusive_lock;
// Make mp_dispatch_queue_process() exit if it's idle.
bool interrupted;
// The target thread is blocked by mp_dispatch_queue_process(). Note that
// mp_dispatch_lock() can set this from true to false to keep the thread
// blocked (this stops if from processing other dispatch items, and from
// other threads to return from mp_dispatch_lock(), making it an exclusive
// lock).
bool idling;
// A mp_dispatch_lock() call is requesting an exclusive lock.
bool lock_request;
// Used to block out threads calling mp_dispatch_queue_process() while
// they're externall locked via mp_dispatch_lock().
// We could use a simple counter (increment it instead of adding a frame,
// also increment it when locking), but with this we can perform some
// minimal debug checks.
struct lock_frame *frame;
};
struct lock_frame {
struct lock_frame *prev;
pthread_t thread;
pthread_t locked_thread;
bool locked;
};
struct mp_dispatch_item {
@@ -55,11 +67,11 @@ static void queue_dtor(void *p)
{
struct mp_dispatch_queue *queue = p;
assert(!queue->head);
assert(!queue->suspend_requested);
assert(!queue->suspended);
assert(!queue->idling);
assert(!queue->lock_request);
assert(!queue->frame);
pthread_cond_destroy(&queue->cond);
pthread_mutex_destroy(&queue->lock);
pthread_mutex_destroy(&queue->exclusive_lock);
}
// A dispatch queue lets other threads run callbacks in a target thread.
@@ -76,7 +88,6 @@ struct mp_dispatch_queue *mp_dispatch_create(void *ta_parent)
struct mp_dispatch_queue *queue = talloc_ptrtype(ta_parent, queue);
*queue = (struct mp_dispatch_queue){0};
talloc_set_destructor(queue, queue_dtor);
pthread_mutex_init(&queue->exclusive_lock, NULL);
pthread_mutex_init(&queue->lock, NULL);
pthread_cond_init(&queue->cond, NULL);
return queue;
@@ -111,6 +122,10 @@ static void mp_dispatch_append(struct mp_dispatch_queue *queue,
// Wake up the main thread; note that other threads might wait on this
// condition for reasons, so broadcast the condition.
pthread_cond_broadcast(&queue->cond);
// No wakeup callback -> assume mp_dispatch_queue_process() needs to be
// interrupted instead.
if (!queue->wakeup_fn)
queue->interrupted = true;
pthread_mutex_unlock(&queue->lock);
if (queue->wakeup_fn)
queue->wakeup_fn(queue->wakeup_ctx);
@@ -170,24 +185,47 @@ void mp_dispatch_run(struct mp_dispatch_queue *queue,
}
// Process any outstanding dispatch items in the queue. This also handles
// suspending or locking the target thread.
// suspending or locking the this thread from another thread via
// mp_dispatch_lock().
// The timeout specifies the minimum wait time. The actual time spent in this
// function can be much higher if the suspending/locking functions are used, or
// if executing the dispatch items takes time. On the other hand, this function
// can return much earlier than the timeout due to sporadic wakeups.
// It is also guaranteed that if at least one queue item was processed, the
// function will return as soon as possible, ignoring the timeout. This
// simplifies users, such as re-checking conditions before waiting. (It will
// still process the remaining queue items, and wait for unsuspend.)
// Note that this will strictly return only after:
// - timeout has passed,
// - all queue items were processed,
// - the possibly acquired lock has been released
// It's possible to cancel the timeout by calling mp_dispatch_interrupt().
void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
{
int64_t wait = timeout > 0 ? mp_add_timeout(mp_time_us(), timeout) : 0;
struct lock_frame frame = {
.thread = pthread_self(),
};
pthread_mutex_lock(&queue->lock);
queue->suspended = true;
// Wake up thread which called mp_dispatch_suspend().
pthread_cond_broadcast(&queue->cond);
while (queue->head || queue->suspend_requested || wait > 0) {
if (queue->head) {
frame.prev = queue->frame;
queue->frame = &frame;
// Logically, the queue is idling if the target thread is blocked in
// mp_dispatch_queue_process() doing nothing, so it's not possible to call
// it again. (Reentrant calls via callbacks temporarily reset the field.)
assert(!queue->idling);
queue->idling = true;
// Wake up thread which called mp_dispatch_lock().
if (queue->lock_request)
pthread_cond_broadcast(&queue->cond);
while (1) {
if (queue->lock_request || queue->frame != &frame || frame.locked) {
// Block due to something having called mp_dispatch_lock(). This
// is either a lock "acquire" (lock_request=true), or a lock in
// progress, with the possibility the thread which called
// mp_dispatch_lock() is now calling mp_dispatch_queue_process()
// (the latter means we must ignore any queue state changes,
// until it has been unlocked again).
pthread_cond_wait(&queue->cond, &queue->lock);
if (queue->frame == &frame && !frame.locked)
assert(queue->idling);
} else if (queue->head) {
struct mp_dispatch_item *item = queue->head;
queue->head = item->next;
if (!queue->head)
@@ -195,66 +233,50 @@ void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
item->next = NULL;
// Unlock, because we want to allow other threads to queue items
// while the dispatch item is processed.
// At the same time, exclusive_lock must be held to protect the
// thread's user state.
// At the same time, we must prevent other threads from returning
// from mp_dispatch_lock(), which is done by idling=false.
queue->idling = false;
pthread_mutex_unlock(&queue->lock);
pthread_mutex_lock(&queue->exclusive_lock);
item->fn(item->fn_data);
pthread_mutex_unlock(&queue->exclusive_lock);
pthread_mutex_lock(&queue->lock);
assert(!queue->idling);
queue->idling = true;
// Wakeup mp_dispatch_run(), also mp_dispatch_lock().
pthread_cond_broadcast(&queue->cond);
if (item->asynchronous) {
talloc_free(item);
} else {
item->completed = true;
// Wakeup mp_dispatch_run()
pthread_cond_broadcast(&queue->cond);
}
} else if (wait > 0 && !queue->interrupted) {
struct timespec ts = mp_time_us_to_timespec(wait);
if (pthread_cond_timedwait(&queue->cond, &queue->lock, &ts))
wait = 0;
} else {
if (wait > 0) {
struct timespec ts = mp_time_us_to_timespec(wait);
pthread_cond_timedwait(&queue->cond, &queue->lock, &ts);
} else {
pthread_cond_wait(&queue->cond, &queue->lock);
}
}
wait = 0;
}
queue->suspended = false;
pthread_mutex_unlock(&queue->lock);
}
// Set the target thread into suspend mode: in this mode, the thread will enter
// mp_dispatch_queue_process(), process any outstanding dispatch items, and
// wait for new items when done (instead of exiting the process function).
// Multiple threads can enter suspend mode at the same time. Suspend mode is
// not a synchronization mechanism; it merely makes sure the target thread does
// not leave mp_dispatch_queue_process(), even if it's done. mp_dispatch_lock()
// can be used for exclusive access.
void mp_dispatch_suspend(struct mp_dispatch_queue *queue)
{
pthread_mutex_lock(&queue->lock);
queue->suspend_requested++;
while (!queue->suspended) {
pthread_mutex_unlock(&queue->lock);
if (queue->wakeup_fn)
queue->wakeup_fn(queue->wakeup_ctx);
pthread_mutex_lock(&queue->lock);
if (queue->suspended)
break;
pthread_cond_wait(&queue->cond, &queue->lock);
}
}
queue->idling = false;
assert(!frame.locked);
assert(queue->frame == &frame);
queue->frame = frame.prev;
queue->interrupted = false;
pthread_mutex_unlock(&queue->lock);
}
// Undo mp_dispatch_suspend().
void mp_dispatch_resume(struct mp_dispatch_queue *queue)
// If the queue is inside of mp_dispatch_queue_process(), make it return as
// soon as all work items have been run, without waiting for the timeout. This
// does not make it return early if it's blocked by a mp_dispatch_lock().
// If mp_dispatch_queue_process() is called in a reentrant way (including the
// case where another thread calls mp_dispatch_lock() and then
// mp_dispatch_queue_process()), this affects only the "topmost" invocation.
void mp_dispatch_interrupt(struct mp_dispatch_queue *queue)
{
pthread_mutex_lock(&queue->lock);
assert(queue->suspended);
assert(queue->suspend_requested > 0);
queue->suspend_requested--;
if (queue->suspend_requested == 0)
pthread_cond_broadcast(&queue->cond);
queue->interrupted = true;
pthread_cond_broadcast(&queue->cond);
pthread_mutex_unlock(&queue->lock);
}
@@ -265,13 +287,50 @@ void mp_dispatch_resume(struct mp_dispatch_queue *queue)
// and the mutex behavior applies to this function only.
void mp_dispatch_lock(struct mp_dispatch_queue *queue)
{
mp_dispatch_suspend(queue);
pthread_mutex_lock(&queue->exclusive_lock);
pthread_mutex_lock(&queue->lock);
// First grab the queue lock. Something else could be holding the lock.
while (queue->lock_request)
pthread_cond_wait(&queue->cond, &queue->lock);
queue->lock_request = true;
// And now wait until the target thread gets "trapped" within the
// mp_dispatch_queue_process() call, which will mean we get exclusive
// access to the target's thread state.
while (!queue->idling) {
pthread_mutex_unlock(&queue->lock);
if (queue->wakeup_fn)
queue->wakeup_fn(queue->wakeup_ctx);
pthread_mutex_lock(&queue->lock);
if (queue->idling)
break;
pthread_cond_wait(&queue->cond, &queue->lock);
}
assert(queue->lock_request);
assert(queue->frame); // must be set if idling
assert(!queue->frame->locked); // no recursive locking on the same level
// "Lock".
queue->frame->locked = true;
queue->frame->locked_thread = pthread_self();
// Reset state for recursive mp_dispatch_queue_process() calls.
queue->lock_request = false;
queue->idling = false;
pthread_mutex_unlock(&queue->lock);
}
// Undo mp_dispatch_lock().
void mp_dispatch_unlock(struct mp_dispatch_queue *queue)
{
pthread_mutex_unlock(&queue->exclusive_lock);
mp_dispatch_resume(queue);
pthread_mutex_lock(&queue->lock);
// Must be called atfer a mp_dispatch_lock().
assert(queue->frame);
assert(queue->frame->locked);
assert(pthread_equal(queue->frame->locked_thread, pthread_self()));
// "Unlock".
queue->frame->locked = false;
// This must have been set to false during locking (except temporarily
// during recursive mp_dispatch_queue_process() calls).
assert(!queue->idling);
queue->idling = true;
// Wakeup mp_dispatch_queue_process(), and maybe other mp_dispatch_lock()s.
pthread_cond_broadcast(&queue->cond);
pthread_mutex_unlock(&queue->lock);
}
+1 -2
View File
@@ -15,8 +15,7 @@ void mp_dispatch_enqueue_autofree(struct mp_dispatch_queue *queue,
void mp_dispatch_run(struct mp_dispatch_queue *queue,
mp_dispatch_fn fn, void *fn_data);
void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout);
void mp_dispatch_suspend(struct mp_dispatch_queue *queue);
void mp_dispatch_resume(struct mp_dispatch_queue *queue);
void mp_dispatch_interrupt(struct mp_dispatch_queue *queue);
void mp_dispatch_lock(struct mp_dispatch_queue *queue);
void mp_dispatch_unlock(struct mp_dispatch_queue *queue);
+65
View File
@@ -0,0 +1,65 @@
#include "common/common.h"
#include "node.h"
// Init a node with the given format. If parent is not NULL, it is set as
// parent allocation according to m_option_type_node rules (which means
// the mpv_node_list allocs are used for chaining the TA allocations).
// format == MPV_FORMAT_NONE will simply initialize it with all-0.
void node_init(struct mpv_node *dst, int format, struct mpv_node *parent)
{
// Other formats need to be initialized manually.
assert(format == MPV_FORMAT_NODE_MAP || format == MPV_FORMAT_NODE_ARRAY ||
format == MPV_FORMAT_FLAG || format == MPV_FORMAT_INT64 ||
format == MPV_FORMAT_DOUBLE || format == MPV_FORMAT_NONE);
void *ta_parent = NULL;
if (parent) {
assert(parent->format == MPV_FORMAT_NODE_MAP ||
parent->format == MPV_FORMAT_NODE_ARRAY);
ta_parent = parent->u.list;
}
*dst = (struct mpv_node){ .format = format };
if (format == MPV_FORMAT_NODE_MAP || format == MPV_FORMAT_NODE_ARRAY)
dst->u.list = talloc_zero(ta_parent, struct mpv_node_list);
}
// Add an entry to a MPV_FORMAT_NODE_ARRAY.
// m_option_type_node memory management rules apply.
struct mpv_node *node_array_add(struct mpv_node *dst, int format)
{
struct mpv_node_list *list = dst->u.list;
assert(dst->format == MPV_FORMAT_NODE_ARRAY && dst->u.list);
MP_TARRAY_GROW(list, list->values, list->num);
node_init(&list->values[list->num], format, dst);
return &list->values[list->num++];
}
// Add an entry to a MPV_FORMAT_NODE_MAP. Keep in mind that this does
// not check for already existing entries under the same key.
// m_option_type_node memory management rules apply.
struct mpv_node *node_map_add(struct mpv_node *dst, const char *key, int format)
{
assert(key);
struct mpv_node_list *list = dst->u.list;
assert(dst->format == MPV_FORMAT_NODE_MAP && dst->u.list);
MP_TARRAY_GROW(list, list->values, list->num);
MP_TARRAY_GROW(list, list->keys, list->num);
list->keys[list->num] = talloc_strdup(list, key);
node_init(&list->values[list->num], format, dst);
return &list->values[list->num++];
}
// Add a string entry to a MPV_FORMAT_NODE_MAP. Keep in mind that this does
// not check for already existing entries under the same key.
// m_option_type_node memory management rules apply.
void node_map_add_string(struct mpv_node *dst, const char *key, const char *val)
{
assert(val);
struct mpv_node *entry = node_map_add(dst, key, MPV_FORMAT_NONE);
entry->format = MPV_FORMAT_STRING;
entry->u.string = talloc_strdup(dst->u.list, val);
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef MP_MISC_NODE_H_
#define MP_MISC_NODE_H_
#include "libmpv/client.h"
void node_init(struct mpv_node *dst, int format, struct mpv_node *parent);
struct mpv_node *node_array_add(struct mpv_node *dst, int format);
struct mpv_node *node_map_add(struct mpv_node *dst, const char *key, int format);
void node_map_add_string(struct mpv_node *dst, const char *key, const char *val);
#endif
+1 -1
View File
@@ -21,7 +21,7 @@
#include <libavutil/common.h>
#include <assert.h>
#include "mpv_talloc.h"
#include "osdep/atomics.h"
#include "osdep/atomic.h"
#include "ring.h"
struct mp_ring {
+601 -280
View File
File diff suppressed because it is too large. Load diff
+107 -31
View File
@@ -19,6 +19,7 @@
#define MPLAYER_M_CONFIG_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "misc/bstr.h"
@@ -37,10 +38,13 @@ struct mp_log;
// Config option
struct m_config_option {
bool is_generated : 1; // Automatically added ("no-" options)
bool is_hidden : 1; // Does not show up in help
bool is_set_from_cmdline : 1; // Set by user from command line
bool is_set_from_config : 1; // Set by a config file
bool is_set_locally : 1; // Has a backup entry
bool warning_was_printed : 1;
int16_t shadow_offset; // Offset into m_config_shadow.data
int16_t group; // Index into m_config.groups
const char *name; // Full name (ie option-subopt)
const struct m_option *opt; // Option description
void *data; // Raw value of the option
@@ -74,10 +78,33 @@ typedef struct m_config {
int (*includefunc)(void *ctx, char *filename, int flags);
void *includefunc_ctx;
// Can intercept option write accesses.
int (*option_set_callback)(void *ctx, struct m_config_option *co,
void *data, int flags);
void *option_set_callback_cb;
// Notification after an option was successfully written to.
// Uses flags as set in UPDATE_OPTS_MASK.
void (*option_change_callback)(void *ctx, struct m_config_option *co,
int flags);
void *option_change_callback_ctx;
// For the command line parser
int recursion_depth;
bool subopt_deprecation_warning;
void *optstruct; // struct mpopts or other
int shadow_size;
// List of m_sub_options instances.
// Index 0 is the top-level and is always present.
struct m_config_group *groups;
int num_groups;
// Thread-safe shadow memory; only set for the main m_config.
struct m_config_shadow *shadow;
} m_config_t;
// Create a new config object.
@@ -94,8 +121,9 @@ struct m_config *m_config_new(void *talloc_ctx, struct mp_log *log,
size_t size, const void *defaults,
const struct m_option *options);
// (Warning: new object references config->log and others.)
struct m_config *m_config_dup(void *talloc_ctx, struct m_config *config);
// Creates "backup" shadow memory for use with m_config_cache. Sets it on
// mpv_global. Expected to be called at early init on the main m_config.
void m_config_create_shadow(struct m_config *config);
struct m_config *m_config_from_obj_desc(void *talloc_ctx, struct mp_log *log,
struct m_obj_desc *desc);
@@ -104,12 +132,9 @@ struct m_config *m_config_from_obj_desc_noalloc(void *talloc_ctx,
struct mp_log *log,
struct m_obj_desc *desc);
int m_config_set_obj_params(struct m_config *conf, char **args);
// Search for the object with the given name in the defaults list, and apply
// its parameters.
int m_config_apply_defaults(struct m_config *config, const char *name,
struct m_obj_settings *defaults);
struct m_config *m_config_from_obj_desc_and_args(void *ta_parent,
struct mp_log *log, struct mpv_global *global, struct m_obj_desc *desc,
const char *name, struct m_obj_settings *defaults, char **args);
// Make sure the option is backed up. If it's already backed up, do nothing.
// All backed up options can be restored with m_config_restore_backups().
@@ -131,10 +156,11 @@ enum {
M_SETOPT_PRESERVE_CMDLINE = 32, // Don't set if already marked as FROM_CMDLINE
M_SETOPT_NO_FIXED = 64, // Reject M_OPT_FIXED options
M_SETOPT_NO_PRE_PARSE = 128, // Reject M_OPT_PREPARSE options
M_SETOPT_NO_OVERWRITE = 256, // Skip options marked with FROM_*
};
// Flags for safe option setting during runtime.
#define M_SETOPT_RUNTIME (M_SETOPT_NO_FIXED | M_SETOPT_NO_PRE_PARSE)
#define M_SETOPT_RUNTIME M_SETOPT_NO_FIXED
// Set the named option to the given string.
// flags: combination of M_SETOPT_* flags (0 for normal operation)
@@ -157,11 +183,15 @@ static inline int m_config_set_option0(struct m_config *config,
return m_config_set_option(config, bstr0(name), bstr0(param));
}
// Similar to m_config_set_option_ext(), but set as data in its native format.
// The type data points to is as in co->opt
int m_config_set_option_raw(struct m_config *config, struct m_config_option *co,
void *data, int flags);
void m_config_mark_co_flags(struct m_config_option *co, int flags);
int m_config_set_option_raw_direct(struct m_config *config,
struct m_config_option *co,
void *data, int flags);
// Similar to m_config_set_option_ext(), but set as data using mpv_node.
struct mpv_node;
int m_config_set_option_node(struct m_config *config, bstr name,
@@ -171,17 +201,14 @@ int m_config_set_option_node(struct m_config *config, bstr name,
int m_config_parse_suboptions(struct m_config *config, char *name,
char *subopts);
/* Get the option matching the given name.
* \param config The config object.
* \param name The option's name.
*/
const struct m_option *m_config_get_option(const struct m_config *config,
struct bstr name);
struct m_config_option *m_config_get_co_raw(const struct m_config *config,
struct bstr name);
struct m_config_option *m_config_get_co(const struct m_config *config,
struct bstr name);
int m_config_get_co_count(struct m_config *config);
struct m_config_option *m_config_get_co_index(struct m_config *config, int index);
// Return the n-th option by position. n==0 is the first option. If there are
// less than (n + 1) options, return NULL.
const char *m_config_get_positional_option(const struct m_config *config, int n);
@@ -193,13 +220,18 @@ const char *m_config_get_positional_option(const struct m_config *config, int n)
// Returns: error code (<0), or number of expected params (0, 1)
int m_config_option_requires_param(struct m_config *config, bstr name);
// Notify m_config_cache users that the option has (probably) changed its value.
void m_config_notify_change_co(struct m_config *config,
struct m_config_option *co);
bool m_config_is_in_group(struct m_config *config,
const struct m_sub_options *group,
struct m_config_option *co);
// Return all (visible) option names as NULL terminated string list.
char **m_config_list_options(void *ta_parent, const struct m_config *config);
/* Print a list of all registered options.
* \param config The config object.
*/
void m_config_print_option_list(const struct m_config *config);
void m_config_print_option_list(const struct m_config *config, const char *name);
/* Find the profile with the given name.
@@ -211,6 +243,10 @@ struct m_profile *m_config_get_profile0(const struct m_config *config,
char *name);
struct m_profile *m_config_get_profile(const struct m_config *config, bstr name);
// Apply and clear the default profile - it's the only profile that new config
// files do not simply append to (for configfile parser).
void m_config_finish_default_profile(struct m_config *config, int flags);
/* Get the profile with the given name, creating it if necessary.
* \param config The config object.
* \param arg The profile's name.
@@ -247,13 +283,53 @@ int m_config_set_profile_option(struct m_config *config, struct m_profile *p,
*/
int m_config_set_profile(struct m_config *config, char *name, int flags);
void *m_config_alloc_struct(void *talloc_ctx,
const struct m_sub_options *subopts);
struct mpv_node m_config_get_profiles(struct m_config *config);
// Create a copy of the struct ptr, described by opts.
// "opts" must live until the struct is free'd.
// Freeing the struct frees all members.
void *m_sub_options_copy(void *talloc_ctx, const struct m_sub_options *opts,
const void *ptr);
// This can be used to create and synchronize per-thread option structs,
// which then can be read without synchronization. No concurrent access to
// the cache itself is allowed.
struct m_config_cache {
// The struct as indicated by m_config_cache_alloc's group parameter.
void *opts;
// Internal.
struct m_config_shadow *shadow;
struct m_config *shadow_config;
long long ts;
int group;
};
// Create a mirror copy from the global options.
// ta_parent: parent for the returned allocation
// global: option data source
// group: the option group to return. This can be NULL for the global option
// struct (MPOpts), or m_sub_options used in a certain OPT_SUBSTRUCT()
// item.
struct m_config_cache *m_config_cache_alloc(void *ta_parent,
struct mpv_global *global,
const struct m_sub_options *group);
// Update the options in cache->opts to current global values. Return whether
// there was an update notification at all (which may or may not indicate that
// some options have changed).
// Keep in mind that while the cache->opts pointer does not change, the option
// data itself will (e.g. string options might be reallocated).
bool m_config_cache_update(struct m_config_cache *cache);
// Like m_config_cache_alloc(), but return the struct (m_config_cache->opts)
// directly, with no way to update the config.
// Warning: does currently not set the child as its own talloc root, which
// means the only way to free the struct is by freeing ta_parent.
void *mp_get_config_group(void *ta_parent, struct mpv_global *global,
const struct m_sub_options *group);
// Read a single global option in a thread-safe way. For multiple options,
// use m_config_cache. The option must exist and match the provided type (the
// type is used as a sanity check only). Performs semi-expensive lookup.
void mp_read_option_raw(struct mpv_global *global, const char *name,
const struct m_option_type *type, void *dst);
struct m_config *mp_get_root_config(struct mpv_global *global);
#endif /* MPLAYER_M_CONFIG_H */
+63 -132
View File
@@ -133,14 +133,6 @@ static void copy_opt(const m_option_t *opt, void *dst, const void *src)
#define VAL(x) (*(int *)(x))
static int clamp_flag(const m_option_t *opt, void *val)
{
if (VAL(val) == 0 || VAL(val) == 1)
return 0;
VAL(val) = 0;
return M_OPT_OUT_OF_RANGE;
}
static int parse_flag(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
@@ -202,7 +194,6 @@ const m_option_type_t m_option_type_flag = {
.print = print_flag,
.copy = copy_opt,
.add = add_flag,
.clamp = clamp_flag,
.set = flag_set,
.get = flag_get,
};
@@ -243,45 +234,6 @@ const m_option_type_t m_option_type_store = {
.set = store_set,
};
// Same for float types
#undef VAL
#define VAL(x) (*(float *)(x))
static int parse_store_float(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
if (param.len == 0) {
if (dst)
VAL(dst) = opt->max;
return 0;
} else {
mp_err(log, "Invalid parameter for %.*s flag: %.*s\n",
BSTR_P(name), BSTR_P(param));
return M_OPT_DISALLOW_PARAM;
}
}
static int store_float_set(const m_option_t *opt, void *dst, struct mpv_node *src)
{
if (src->format != MPV_FORMAT_FLAG)
return M_OPT_UNKNOWN;
if (!src->u.flag)
return M_OPT_INVALID;
VAL(dst) = opt->max;
return 1;
}
const m_option_type_t m_option_type_float_store = {
// can only be activated
.name = "Flag",
.size = sizeof(float),
.flags = M_OPT_TYPE_OPTIONAL_PARAM,
.parse = parse_store_float,
.copy = copy_opt,
.set = store_float_set,
};
// Integer
#undef VAL
@@ -336,14 +288,6 @@ static int parse_longlong(struct mp_log *log, const m_option_t *opt,
return 1;
}
static int clamp_int(const m_option_t *opt, void *val)
{
long long tmp = *(int *)val;
int r = clamp_longlong(opt, &tmp);
*(int *)val = tmp;
return r;
}
static int clamp_int64(const m_option_t *opt, void *val)
{
long long tmp = *(int64_t *)val;
@@ -475,7 +419,6 @@ const m_option_type_t m_option_type_int = {
.copy = copy_opt,
.add = add_int,
.multiply = multiply_int,
.clamp = clamp_int,
.set = int_set,
.get = int_get,
};
@@ -488,7 +431,6 @@ const m_option_type_t m_option_type_int64 = {
.copy = copy_opt,
.add = add_int64,
.multiply = multiply_int64,
.clamp = clamp_int64,
.set = int64_set,
.get = int64_get,
};
@@ -546,21 +488,6 @@ const char *m_opt_choice_str(const struct m_opt_choice_alternatives *choices,
return NULL;
}
static int clamp_choice(const m_option_t *opt, void *val)
{
int v = *(int *)val;
if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
if (v >= opt->min && v <= opt->max)
return 0;
}
;
for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) {
if (alt->value == v)
return 0;
}
return M_OPT_INVALID;
}
static int parse_choice(struct mp_log *log, const struct m_option *opt,
struct bstr name, struct bstr param, void *dst)
{
@@ -750,7 +677,6 @@ const struct m_option_type m_option_type_choice = {
.print = print_choice,
.copy = copy_opt,
.add = add_choice,
.clamp = clamp_choice,
.set = choice_set,
.get = choice_get,
};
@@ -894,7 +820,8 @@ static int clamp_double(const m_option_t *opt, void *val)
v = opt->min;
r = M_OPT_OUT_OF_RANGE;
}
if (!isfinite(v)) {
// (setting max/min to INFINITY/-INFINITY is allowed)
if (!isfinite(v) && v != opt->max && v != opt->min) {
v = opt->min;
r = M_OPT_OUT_OF_RANGE;
}
@@ -921,22 +848,8 @@ static int parse_double(struct mp_log *log, const m_option_t *opt,
return M_OPT_INVALID;
}
if (opt->flags & M_OPT_MIN)
if (tmp_float < opt->min) {
mp_err(log, "The %.*s option must be >= %f: %.*s\n",
BSTR_P(name), opt->min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
if (opt->flags & M_OPT_MAX)
if (tmp_float > opt->max) {
mp_err(log, "The %.*s option must be <= %f: %.*s\n",
BSTR_P(name), opt->max, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
if (!isfinite(tmp_float)) {
mp_err(log, "The %.*s option must be a finite number: %.*s\n",
if (clamp_double(opt, &tmp_float) < 0) {
mp_err(log, "The %.*s option is out of range: %.*s\n",
BSTR_P(name), BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
@@ -990,11 +903,7 @@ static int double_set(const m_option_t *opt, void *dst, struct mpv_node *src)
} else {
return M_OPT_UNKNOWN;
}
if ((opt->flags & M_OPT_MIN) && val < opt->min)
return M_OPT_OUT_OF_RANGE;
if ((opt->flags & M_OPT_MAX) && val > opt->max)
return M_OPT_OUT_OF_RANGE;
if (!isfinite(val))
if (clamp_double(opt, &val) < 0)
return M_OPT_OUT_OF_RANGE;
*(double *)dst = val;
return 1;
@@ -1016,7 +925,6 @@ const m_option_type_t m_option_type_double = {
.print = print_double,
.pretty_print = print_double_f3,
.copy = copy_opt,
.clamp = clamp_double,
.add = add_double,
.multiply = multiply_double,
.set = double_set,
@@ -1026,14 +934,6 @@ const m_option_type_t m_option_type_double = {
#undef VAL
#define VAL(x) (*(float *)(x))
static int clamp_float(const m_option_t *opt, void *val)
{
double tmp = VAL(val);
int r = clamp_double(opt, &tmp);
VAL(val) = tmp;
return r;
}
static int parse_float(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
@@ -1095,7 +995,30 @@ const m_option_type_t m_option_type_float = {
.copy = copy_opt,
.add = add_float,
.multiply = multiply_float,
.clamp = clamp_float,
.set = float_set,
.get = float_get,
};
static int parse_float_aspect(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
if (bstr_equals0(param, "no")) {
if (dst)
VAL(dst) = 0.0f;
return 1;
}
return parse_float(log, opt, name, param, dst);
}
const m_option_type_t m_option_type_aspect = {
.name = "Aspect",
.size = sizeof(float),
.parse = parse_float_aspect,
.print = print_float,
.pretty_print = print_float_f3,
.copy = copy_opt,
.add = add_float,
.multiply = multiply_float,
.set = float_set,
.get = float_get,
};
@@ -1192,12 +1115,10 @@ static void free_str(void *src)
const m_option_type_t m_option_type_string = {
.name = "String",
.size = sizeof(char *),
.flags = M_OPT_TYPE_DYNAMIC,
.parse = parse_str,
.print = print_str,
.copy = copy_str,
.free = free_str,
.clamp = clamp_str,
.set = str_set,
.get = str_get,
};
@@ -1503,7 +1424,7 @@ const m_option_type_t m_option_type_string_list = {
*/
.name = "String list",
.size = sizeof(char **),
.flags = M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD,
.flags = M_OPT_TYPE_ALLOW_WILDCARD,
.parse = parse_str_list,
.print = print_str_list,
.copy = copy_str_list,
@@ -1539,7 +1460,6 @@ static int parse_str_append_list(struct mp_log *log, const m_option_t *opt,
const m_option_type_t m_option_type_string_append_list = {
.name = "String list",
.size = sizeof(char **),
.flags = M_OPT_TYPE_DYNAMIC,
.parse = parse_str_append_list,
.print = print_str_list,
.copy = copy_str_list,
@@ -1653,7 +1573,6 @@ static int keyvalue_list_get(const m_option_t *opt, void *ta_parent,
const m_option_type_t m_option_type_keyvalue_list = {
.name = "Key/value list",
.size = sizeof(char **),
.flags = M_OPT_TYPE_DYNAMIC,
.parse = parse_keyvalue_list,
.print = print_keyvalue_list,
.copy = copy_str_list,
@@ -1720,7 +1639,6 @@ static int set_msglevels(const m_option_t *opt, void *dst,
const m_option_type_t m_option_type_msglevels = {
.name = "Output verbosity levels",
.size = sizeof(char **),
.flags = M_OPT_TYPE_DYNAMIC,
.parse = parse_msglevels,
.print = print_keyvalue_list,
.copy = copy_str_list,
@@ -2186,7 +2104,7 @@ static int parse_imgfmt(struct mp_log *log, const m_option_t *opt,
mp_info(log, " %s", list[i]);
mp_info(log, "\n");
talloc_free(list);
return M_OPT_EXIT - 1;
return M_OPT_EXIT;
}
unsigned int fmt = mp_imgfmt_from_name(param, true);
@@ -2257,7 +2175,7 @@ static int parse_afmt(struct mp_log *log, const m_option_t *opt,
for (int i = 1; i < AF_FORMAT_COUNT; i++)
mp_info(log, " %s", af_fmt_to_str(i));
mp_info(log, "\n");
return M_OPT_EXIT - 1;
return M_OPT_EXIT;
}
int fmt = 0;
@@ -2301,7 +2219,7 @@ static int parse_channels(struct mp_log *log, const m_option_t *opt,
mp_info(log, "\nOther values:\n"
" auto-safe\n");
}
return M_OPT_EXIT - 1;
return M_OPT_EXIT;
}
bool auto_safe = bstr_equals0(param, "auto-safe");
@@ -2483,7 +2401,6 @@ const m_option_type_t m_option_type_time = {
.pretty_print = pretty_print_time,
.copy = copy_opt,
.add = add_double,
.clamp = clamp_double,
.set = time_set,
.get = time_get,
};
@@ -2731,17 +2648,21 @@ static void copy_obj_settings_list(const m_option_t *opt, void *dst,
// without '=' sets a flag, or whether it's a positional argument.
static int get_obj_param(struct mp_log *log, bstr opt_name, bstr obj_name,
struct m_config *config, bstr name, bstr val,
int flags, int *nold, bstr *out_name, bstr *out_val)
int flags, bool nopos,
int *nold, bstr *out_name, bstr *out_val)
{
int r;
if (!config)
return 0; // skip
if (!config) {
*out_name = name; // preserve args for opengl-hq legacy handling
*out_val = val;
return 1;
}
// va.start != NULL => of the form name=val (not positional)
// If it's just "name", and the associated option exists and is a flag,
// don't accept it as positional argument.
if (val.start || m_config_option_requires_param(config, name) == 0) {
if (val.start || m_config_option_requires_param(config, name) == 0 || nopos) {
r = m_config_set_option_ext(config, name, val, flags);
if (r < 0) {
if (r == M_OPT_UNKNOWN) {
@@ -2749,7 +2670,7 @@ static int get_obj_param(struct mp_log *log, bstr opt_name, bstr obj_name,
BSTR_P(opt_name), BSTR_P(obj_name), BSTR_P(name));
return M_OPT_UNKNOWN;
}
if (r > M_OPT_EXIT)
if (r != M_OPT_EXIT)
mp_err(log, "Option %.*s: "
"Error while parsing %.*s parameter %.*s (%.*s)\n",
BSTR_P(opt_name), BSTR_P(obj_name), BSTR_P(name),
@@ -2775,7 +2696,7 @@ static int get_obj_param(struct mp_log *log, bstr opt_name, bstr obj_name,
}
r = m_config_set_option_ext(config, bstr0(opt), val, flags);
if (r < 0) {
if (r > M_OPT_EXIT)
if (r != M_OPT_EXIT)
mp_err(log, "Option %.*s: "
"Error while parsing %.*s parameter %s (%.*s)\n",
BSTR_P(opt_name), BSTR_P(obj_name), opt, BSTR_P(val));
@@ -2797,7 +2718,7 @@ static int get_obj_param(struct mp_log *log, bstr opt_name, bstr obj_name,
// desc is optional.
static int m_obj_parse_sub_config(struct mp_log *log, struct bstr opt_name,
struct bstr name, struct bstr *pstr,
struct m_config *config, int flags,
struct m_config *config, int flags, bool nopos,
struct m_obj_desc *desc, char ***ret)
{
int nold = 0;
@@ -2818,8 +2739,8 @@ static int m_obj_parse_sub_config(struct mp_log *log, struct bstr opt_name,
goto exit;
if (bstr_equals0(fname, "help"))
goto print_help;
r = get_obj_param(log, opt_name, name, config, fname, fval, flags, &nold,
&fname, &fval);
r = get_obj_param(log, opt_name, name, config, fname, fval, flags,
nopos, &nold, &fname, &fval);
if (r < 0)
goto exit;
@@ -2850,12 +2771,12 @@ print_help: ;
if (config) {
if (desc->print_help)
desc->print_help(log);
m_config_print_option_list(config);
m_config_print_option_list(config, "*");
} else {
mp_warn(log, "Option %.*s: item %.*s doesn't exist.\n",
BSTR_P(opt_name), BSTR_P(name));
}
r = M_OPT_EXIT - 1;
r = M_OPT_EXIT;
exit:
free_str_list(&args);
@@ -2874,6 +2795,7 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
char **plist = NULL;
struct m_obj_desc desc;
bstr label = {0};
bool nopos = list->disallow_positional_parameters;
if (bstr_eatstart0(pstr, "@")) {
if (!bstr_split_tok(*pstr, ":", &label, pstr)) {
@@ -2909,7 +2831,7 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
struct m_config *config = m_config_from_obj_desc_noalloc(NULL, log, &desc);
bstr s = bstr0(desc.init_options);
m_obj_parse_sub_config(log, opt, str, &s, config,
M_SETOPT_CHECK_ONLY, NULL, &plist);
M_SETOPT_CHECK_ONLY, nopos, NULL, &plist);
assert(s.len == 0);
talloc_free(config);
}
@@ -2919,7 +2841,7 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
if (!skip)
config = m_config_from_obj_desc_noalloc(NULL, log, &desc);
r = m_obj_parse_sub_config(log, opt, str, pstr, config,
M_SETOPT_CHECK_ONLY, &desc,
M_SETOPT_CHECK_ONLY, nopos, &desc,
_ret ? &plist : NULL);
talloc_free(config);
if (r < 0)
@@ -3051,7 +2973,7 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt,
}
}
mp_info(log, "\n");
return M_OPT_EXIT - 1;
return M_OPT_EXIT;
}
if (op == OP_CLR) {
@@ -3301,7 +3223,7 @@ static int get_obj_settings_list(const m_option_t *opt, void *ta_parent,
const m_option_type_t m_option_type_obj_settings_list = {
.name = "Object settings list",
.size = sizeof(m_obj_settings_t *),
.flags = M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD,
.flags = M_OPT_TYPE_ALLOW_WILDCARD,
.parse = parse_obj_settings_list,
.print = print_obj_settings_list,
.copy = copy_obj_settings_list,
@@ -3422,7 +3344,6 @@ static int node_get(const m_option_t *opt, void *ta_parent,
const m_option_type_t m_option_type_node = {
.name = "Complex",
.size = sizeof(struct mpv_node),
.flags = M_OPT_TYPE_DYNAMIC,
.parse = parse_node,
.print = print_node,
.copy = copy_node,
@@ -3438,3 +3359,13 @@ const m_option_type_t m_option_type_alias = {
const m_option_type_t m_option_type_removed = {
.name = "removed",
};
static int parse_dummy(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
return 1;
}
const m_option_type_t m_option_type_subopt_legacy = {
.name = "legacy suboption",
.parse = parse_dummy,
};
+69 -42
View File
@@ -38,7 +38,6 @@ struct mpv_node;
// Simple types
extern const m_option_type_t m_option_type_flag;
extern const m_option_type_t m_option_type_store;
extern const m_option_type_t m_option_type_float_store;
extern const m_option_type_t m_option_type_int;
extern const m_option_type_t m_option_type_int64;
extern const m_option_type_t m_option_type_intpair;
@@ -62,7 +61,9 @@ extern const m_option_type_t m_option_type_color;
extern const m_option_type_t m_option_type_geometry;
extern const m_option_type_t m_option_type_size_box;
extern const m_option_type_t m_option_type_channels;
extern const m_option_type_t m_option_type_aspect;
extern const m_option_type_t m_option_type_node;
extern const m_option_type_t m_option_type_subopt_legacy;
// Used internally by m_config.c
extern const m_option_type_t m_option_type_alias;
@@ -129,6 +130,12 @@ struct m_obj_desc {
// Set by m_obj_list_find(). If the requested name is an old alias, this
// is set to the old name (while the name field uses the new name).
const char *replaced_name;
// For convenience: these are added as global command-line options.
const struct m_sub_options *global_opts;
// Evil hack to essentially force-move .options to global_opts. All options
// will be added as global options with the given prefix, and using
// sub-options will be treated as deprecated and redirected.
const char *legacy_prefix;
};
// Extra definition needed for \ref m_option_type_obj_settings_list options.
@@ -142,6 +149,8 @@ struct m_obj_list {
// Allow unknown entries, for which a dummy entry is inserted, and whose
// options are skipped and ignored.
bool allow_unknown_entries;
// This helps with confusing error messages if unknown flag options are used.
bool disallow_positional_parameters;
};
// Find entry by name
@@ -182,6 +191,9 @@ struct m_sub_options {
const struct m_option *opts;
size_t size;
const void *defaults;
// Change flags passed to mp_option_change_callback() if any option that is
// directly or indirectly part of this group is changed.
int change_flags;
};
#define CONF_TYPE_FLAG (&m_option_type_flag)
@@ -207,7 +219,6 @@ struct m_sub_options {
union m_option_value {
int flag; // not the C type "bool"!
int store;
float float_store;
int int_;
int64_t int64;
int intpair[2];
@@ -291,13 +302,6 @@ struct m_option_type {
// to the valid value range of the option.
void (*multiply)(const m_option_t *opt, void *val, double f);
// Clamp the value in val to the option's valid value range.
// Return values:
// M_OPT_OUT_OF_RANGE: val was invalid, and modified (clamped) to be valid
// M_OPT_INVALID: val was invalid, and can't be made valid
// 0: val was already valid and is unchanged
int (*clamp)(const m_option_t *opt, void *val);
// Set the option value in dst to the contents of src.
// (If the option is dynamic, the old value in *dst has to be freed.)
// Return values:
@@ -359,30 +363,45 @@ struct m_option {
// The option is forbidden in config files.
#define M_OPT_NOCFG (1 << 2)
// This option can't be set per-file when used with struct m_config.
#define M_OPT_GLOBAL (1 << 4)
// Can not be freely changed at runtime (normally, all options can be changed,
// even if the settings don't get effective immediately). Note that an option
// might still change even if this is set, e.g. via properties or per-file
// options.
#define M_OPT_FIXED (1 << 5)
#define M_OPT_FIXED (1 << 3)
// The option should be set during command line pre-parsing
#define M_OPT_PRE_PARSE (1 << 6)
#define M_OPT_PRE_PARSE (1 << 4)
// The option expects a file name (or a list of file names)
#define M_OPT_FILE (1 << 11)
#define M_OPT_FILE (1 << 5)
// Logging-related option - used to update log/terminal settings eagerly
#define M_OPT_TERM (1 << 12)
// Do not add as property.
#define M_OPT_NOPROP (1 << 6)
// The following are also part of the M_OPT_* flags, and are used to update
// certain groups of options.
#define UPDATE_OPT_FIRST (1 << 7)
#define UPDATE_TERM (1 << 7) // terminal options
#define UPDATE_RENDERER (1 << 8) // mainly vo_opengl options
#define UPDATE_VIDEOPOS (1 << 9) // video position (panscan etc.)
#define UPDATE_OSD (1 << 10) // related to OSD rendering
#define UPDATE_BUILTIN_SCRIPTS (1 << 11) // osc/ytdl
#define UPDATE_IMGPAR (1 << 12) // video image params overrides
#define UPDATE_INPUT (1 << 13) // mostly --input-* options
#define UPDATE_AUDIO (1 << 14) // --audio-channels etc.
#define UPDATE_PRIORITY (1 << 15) // --priority (Windows-only)
#define UPDATE_SCREENSAVER (1 << 16) // --stop-screensaver
#define UPDATE_OPT_LAST (1 << 16)
// All bits between _FIRST and _LAST (inclusive)
#define UPDATE_OPTS_MASK \
(((UPDATE_OPT_LAST << 1) - 1) & ~(unsigned)(UPDATE_OPT_FIRST - 1))
// These are kept for compatibility with older code.
#define CONF_MIN M_OPT_MIN
#define CONF_MAX M_OPT_MAX
#define CONF_RANGE M_OPT_RANGE
#define CONF_NOCFG M_OPT_NOCFG
#define CONF_GLOBAL (M_OPT_GLOBAL | M_OPT_FIXED)
#define CONF_PRE_PARSE M_OPT_PRE_PARSE
// These flags are used to describe special parser capabilities or behavior.
@@ -403,19 +422,11 @@ struct m_option {
*/
#define M_OPT_TYPE_ALLOW_WILDCARD (1 << 1)
// Dynamic data type.
/** This flag indicates that the data is dynamically allocated (m_option::p
* points to a pointer). It enables a little hack in the \ref Config which
* replaces the initial value of such variables with a dynamic copy in case
* the initial value is statically allocated (pretty common with strings).
*/
#define M_OPT_TYPE_DYNAMIC (1 << 2)
// The parameter is optional and by default no parameter is preferred. If
// ambiguous syntax is used ("--opt value"), the command line parser will
// assume that the argument takes no parameter. In config files, these
// options can be used without "=" and value.
#define M_OPT_TYPE_OPTIONAL_PARAM (1 << 3)
#define M_OPT_TYPE_OPTIONAL_PARAM (1 << 2)
///////////////////////////// Parser flags /////////////////////////////////
@@ -424,8 +435,7 @@ struct m_option {
// On success parsers return a number >= 0.
//
// To indicate that MPlayer should exit without playing anything,
// parsers return M_OPT_EXIT minus the number of parameters they
// consumed: \ref M_OPT_EXIT or \ref M_OPT_EXIT-1.
// parsers return M_OPT_EXIT.
//
// On error one of the following (negative) error codes is returned:
@@ -449,8 +459,6 @@ struct m_option {
#define M_OPT_PARSER_ERR -6
// Returned when MPlayer should exit. Used by various help stuff.
/** M_OPT_EXIT must be the lowest number on this list.
*/
#define M_OPT_EXIT -7
char *m_option_strerror(int code);
@@ -577,10 +585,6 @@ extern const char m_option_path_separator;
OPT_GENERAL(int, optname, varname, flags, .max = value, \
.type = &m_option_type_store)
#define OPT_FLOAT_STORE(optname, varname, flags, value) \
OPT_GENERAL(float, optname, varname, flags, .max = value, \
.type = &m_option_type_float_store)
#define OPT_STRINGLIST(...) \
OPT_GENERAL(char**, __VA_ARGS__, .type = &m_option_type_string_list)
@@ -622,10 +626,11 @@ extern const char m_option_path_separator;
#define OPT_STRING(...) \
OPT_GENERAL(char*, __VA_ARGS__, .type = &m_option_type_string)
#define OPT_SETTINGSLIST(optname, varname, flags, objlist) \
#define OPT_SETTINGSLIST(optname, varname, flags, objlist, ...) \
OPT_GENERAL(m_obj_settings_t*, optname, varname, flags, \
.type = &m_option_type_obj_settings_list, \
.priv = (void*)MP_EXPECT_TYPE(const struct m_obj_list*, objlist))
.priv = (void*)MP_EXPECT_TYPE(const struct m_obj_list*, objlist), \
__VA_ARGS__)
#define OPT_IMAGEFORMAT(...) \
OPT_GENERAL(int, __VA_ARGS__, .type = &m_option_type_imgfmt)
@@ -682,6 +687,9 @@ extern const char m_option_path_separator;
#define OPT_TRACKCHOICE(name, var) \
OPT_CHOICE_OR_INT(name, var, 0, 0, 8190, ({"no", -2}, {"auto", -1}))
#define OPT_ASPECT(...) \
OPT_GENERAL(float, __VA_ARGS__, .type = &m_option_type_aspect)
#define OPT_STRING_VALIDATE_(optname, varname, flags, validate_fn, ...) \
OPT_GENERAL(char*, optname, varname, flags, __VA_ARGS__, \
.priv = MP_EXPECT_TYPE(m_opt_string_validate_fn, validate_fn))
@@ -690,7 +698,7 @@ extern const char m_option_path_separator;
#define OPT_PRINT(optname, fn) \
{.name = optname, \
.flags = M_OPT_FIXED | M_OPT_GLOBAL | M_OPT_NOCFG | M_OPT_PRE_PARSE, \
.flags = M_OPT_FIXED | M_OPT_NOCFG | M_OPT_PRE_PARSE, \
.type = &m_option_type_print_fn, \
.priv = MP_EXPECT_TYPE(m_opt_print_fn, fn), \
.offset = -1}
@@ -706,13 +714,32 @@ extern const char m_option_path_separator;
.type = &m_option_type_subconfig, \
.priv = (void*)&subconf)
// If "--name" was removed, but "--newname" has the same semantics.
// Same as above, but for legacy suboption usage, which have no associated
// field (no actual data anywhere).
#define OPT_SUBSTRUCT_LEGACY(optname, subconf) \
{.name = optname, .offset = -1, .type = &m_option_type_subconfig, \
.priv = (void*)&subconf}
// Provide a another name for the option.
#define OPT_ALIAS(optname, newname) \
{.name = optname, .type = &m_option_type_alias, .priv = newname, \
.offset = -1}
// If "--optname" was removed, but "--newname" has the same semantics.
// It will be redirected, and a warning will be printed on first use.
#define OPT_REPLACED(optname, newname) \
{.name = optname, .type = &m_option_type_alias, .priv = newname, .offset = -1}
{.name = optname, .type = &m_option_type_alias, .priv = newname, \
.deprecation_message = "", .offset = -1}
// "--name" doesn't exist, but inform the user about a replacement with msg.
// "--optname" doesn't exist, but inform the user about a replacement with msg.
#define OPT_REMOVED(optname, msg) \
{.name = optname, .type = &m_option_type_removed, .priv = msg, .offset = -1}
{.name = optname, .type = &m_option_type_removed, .priv = msg, \
.deprecation_message = "", .offset = -1}
// Redirect a suboption (e.g. from --vo) to a global option. The redirection
// is handled as a special case instead of being applied automatically.
#define OPT_SUBOPT_LEGACY(optname, globalname) \
{.name = optname, .type = &m_option_type_subopt_legacy, .priv = globalname, \
.offset = -1}
#endif /* MPLAYER_M_OPTION_H */
+14 -11
View File
@@ -36,8 +36,8 @@
#include "common/msg.h"
#include "common/common.h"
static struct m_property *m_property_list_find(const struct m_property *list,
const char *name)
struct m_property *m_property_list_find(const struct m_property *list,
const char *name)
{
for (int n = 0; list && list[n].name; n++) {
if (strcmp(list[n].name, name) == 0)
@@ -115,6 +115,11 @@ int m_property_do(struct mp_log *log, const struct m_property *prop_list,
M_PROPERTY_NOT_IMPLEMENTED)
return r;
// Fallback to m_option
r = m_property_do(log, prop_list, name, M_PROPERTY_GET_CONSTRICTED_TYPE,
&opt, ctx);
if (r <= 0)
return r;
assert(opt.type);
if (!opt.type->add)
return M_PROPERTY_NOT_IMPLEMENTED;
if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0)
@@ -124,16 +129,14 @@ int m_property_do(struct mp_log *log, const struct m_property *prop_list,
m_option_free(&opt, &val);
return r;
}
case M_PROPERTY_GET_CONSTRICTED_TYPE: {
if ((r = do_action(prop_list, name, action, arg, ctx)) >= 0)
return r;
if ((r = do_action(prop_list, name, M_PROPERTY_GET_TYPE, arg, ctx)) >= 0)
return r;
return M_PROPERTY_NOT_IMPLEMENTED;
}
case M_PROPERTY_SET: {
if (!log)
return M_PROPERTY_ERROR;
m_option_copy(&opt, &val, arg);
r = opt.type->clamp ? opt.type->clamp(&opt, arg) : 0;
m_option_free(&opt, &val);
if (r != 0) {
mp_err(log, "Property '%s': invalid value.\n", name);
return M_PROPERTY_ERROR;
}
return do_action(prop_list, name, M_PROPERTY_SET, arg, ctx);
}
case M_PROPERTY_GET_NODE: {
+9
View File
@@ -48,6 +48,12 @@ enum mp_property_action {
// arg: char**
M_PROPERTY_PRINT,
// Like M_PROPERTY_GET_TYPE, but get a type that is compatible to the real
// type, but reflect practical limits, such as runtime-available values.
// This is mostly used for "UI" related things.
// (Example: volume property.)
M_PROPERTY_GET_CONSTRICTED_TYPE,
// Switch the property up/down by a given value.
// If unimplemented, the property wrapper uses the property type as
// fallback.
@@ -128,6 +134,9 @@ struct m_property {
void *priv;
};
struct m_property *m_property_list_find(const struct m_property *list,
const char *name);
// Access a property.
// action: one of m_property_action
// ctx: opaque value passed through to property implementation
+305 -228
View File
@@ -25,6 +25,7 @@
#include <stddef.h>
#include <sys/types.h>
#include <limits.h>
#include <math.h>
#include "config.h"
@@ -39,6 +40,7 @@
#include "stream/stream.h"
#include "video/csputils.h"
#include "video/hwdec.h"
#include "video/image_writer.h"
#include "sub/osd.h"
#include "audio/filter/af.h"
#include "audio/decode/dec_audio.h"
@@ -46,6 +48,10 @@
#include "player/command.h"
#include "stream/stream.h"
#if HAVE_DRM
#include "video/out/drm_common.h"
#endif
extern const char mp_help_text[];
static void print_version(struct mp_log *log)
@@ -71,7 +77,10 @@ extern const struct m_sub_options vd_lavc_conf;
extern const struct m_sub_options ad_lavc_conf;
extern const struct m_sub_options input_config;
extern const struct m_sub_options encode_config;
extern const struct m_sub_options image_writer_conf;
extern const struct m_sub_options gl_video_conf;
extern const struct m_sub_options ao_alsa_conf;
extern const struct m_sub_options demux_conf;
extern const struct m_obj_list vf_obj_list;
extern const struct m_obj_list af_obj_list;
@@ -81,6 +90,7 @@ extern const struct m_obj_list ao_obj_list;
const struct m_opt_choice_alternatives mp_hwdec_names[] = {
{"no", HWDEC_NONE},
{"auto", HWDEC_AUTO},
{"yes" , HWDEC_AUTO},
{"auto-copy", HWDEC_AUTO_COPY},
{"vdpau", HWDEC_VDPAU},
{"videotoolbox",HWDEC_VIDEOTOOLBOX},
@@ -92,41 +102,185 @@ const struct m_opt_choice_alternatives mp_hwdec_names[] = {
{"d3d11va", HWDEC_D3D11VA},
{"d3d11va-copy",HWDEC_D3D11VA_COPY},
{"rpi", HWDEC_RPI},
{"rpi-copy", HWDEC_RPI_COPY},
{"mediacodec", HWDEC_MEDIACODEC},
{"cuda", HWDEC_CUDA},
{"cuda-copy", HWDEC_CUDA_COPY},
{"crystalhd", HWDEC_CRYSTALHD},
{0}
};
static const struct m_sub_options screenshot_conf = {
.opts = image_writer_opts,
.size = sizeof(struct image_writer_opts),
.defaults = &image_writer_opts_defaults,
};
#define OPT_BASE_STRUCT struct mp_cache_opts
const struct m_sub_options stream_cache_conf = {
.opts = (const struct m_option[]){
OPT_CHOICE_OR_INT("cache", size, 0, 32, 0x7fffffff,
({"no", 0},
{"auto", -1},
{"yes", -2})),
OPT_CHOICE_OR_INT("cache-default", def_size, 0, 32, 0x7fffffff,
({"no", 0})),
OPT_INTRANGE("cache-initial", initial, 0, 0, 0x7fffffff),
OPT_INTRANGE("cache-seek-min", seek_min, 0, 0, 0x7fffffff),
OPT_INTRANGE("cache-backbuffer", back_buffer, 0, 0, 0x7fffffff),
OPT_STRING("cache-file", file, M_OPT_FILE),
OPT_INTRANGE("cache-file-size", file_max, 0, 0, 0x7fffffff),
{0}
},
.size = sizeof(struct mp_cache_opts),
.defaults = &(const struct mp_cache_opts){
.size = -1,
.def_size = 75000,
.initial = 0,
.seek_min = 500,
.back_buffer = 75000,
.file_max = 1024 * 1024,
},
};
#undef OPT_BASE_STRUCT
#define OPT_BASE_STRUCT struct mp_vo_opts
static const m_option_t mp_vo_opt_list[] = {
OPT_SETTINGSLIST("vo", video_driver_list, 0, &vo_obj_list, ),
OPT_SETTINGSLIST("vo-defaults", vo_defs, 0, &vo_obj_list,
.deprecation_message = "deprecated, use global options"),
OPT_CHOICE_C("hwdec-preload", hwdec_preload_api, 0, mp_hwdec_names),
OPT_SUBSTRUCT("sws", sws_opts, sws_conf, 0),
OPT_FLAG("taskbar-progress", taskbar_progress, 0),
OPT_FLAG("ontop", ontop, 0),
OPT_FLAG("border", border, 0),
OPT_FLAG("fit-border", fit_border, 0),
OPT_FLAG("on-all-workspaces", all_workspaces, 0),
OPT_GEOMETRY("geometry", geometry, 0),
OPT_SIZE_BOX("autofit", autofit, 0),
OPT_SIZE_BOX("autofit-larger", autofit_larger, 0),
OPT_SIZE_BOX("autofit-smaller", autofit_smaller, 0),
OPT_DOUBLE("window-scale", window_scale, CONF_RANGE, .min = 0.001, .max = 100),
OPT_FLAG("force-window-position", force_window_position, 0),
OPT_STRING("x11-name", winname, 0),
OPT_FLOATRANGE("monitoraspect", force_monitor_aspect, 0, 0.0, 9.0),
OPT_FLOATRANGE("monitorpixelaspect", monitor_pixel_aspect, 0, 0.2, 9.0),
OPT_FLAG("fullscreen", fullscreen, 0),
OPT_ALIAS("fs", "fullscreen"),
OPT_FLAG("native-keyrepeat", native_keyrepeat, 0),
OPT_FLOATRANGE("panscan", panscan, UPDATE_VIDEOPOS, 0.0, 1.0),
OPT_FLOATRANGE("video-zoom", zoom, UPDATE_VIDEOPOS, -20.0, 20.0),
OPT_FLOATRANGE("video-pan-x", pan_x, UPDATE_VIDEOPOS, -3.0, 3.0),
OPT_FLOATRANGE("video-pan-y", pan_y, UPDATE_VIDEOPOS, -3.0, 3.0),
OPT_FLOATRANGE("video-align-x", align_x, UPDATE_VIDEOPOS, -1.0, 1.0),
OPT_FLOATRANGE("video-align-y", align_y, UPDATE_VIDEOPOS, -1.0, 1.0),
OPT_CHOICE("video-unscaled", unscaled, UPDATE_VIDEOPOS,
({"no", 0}, {"yes", 1}, {"downscale-big", 2})),
OPT_INT64("wid", WinID, 0),
OPT_CHOICE_OR_INT("screen", screen_id, 0, 0, 32,
({"default", -1})),
OPT_CHOICE_OR_INT("fs-screen", fsscreen_id, 0, 0, 32,
({"all", -2}, {"current", -1})),
OPT_FLAG("fs-black-out-screens", fs_black_out_screens, 0),
OPT_FLAG("keepaspect", keepaspect, UPDATE_VIDEOPOS),
OPT_FLAG("keepaspect-window", keepaspect_window, 0),
#if HAVE_X11
OPT_CHOICE("x11-netwm", x11_netwm, 0,
({"auto", 0}, {"no", -1}, {"yes", 1})),
OPT_CHOICE("x11-bypass-compositor", x11_bypass_compositor, 0,
({"no", 0}, {"yes", 1}, {"fs-only", 2}, {"never", 3})),
#endif
#if HAVE_WIN32
OPT_STRING("vo-mmcss-profile", mmcss_profile, 0),
#endif
#if HAVE_DRM
OPT_STRING_VALIDATE("drm-connector", drm_connector_spec,
0, drm_validate_connector_opt),
OPT_INT("drm-mode", drm_mode_id, 0),
#endif
{0}
};
const struct m_sub_options vo_sub_opts = {
.opts = mp_vo_opt_list,
.size = sizeof(struct mp_vo_opts),
.defaults = &(const struct mp_vo_opts){
.video_driver_list = NULL,
.monitor_pixel_aspect = 1.0,
.screen_id = -1,
.fsscreen_id = -1,
.panscan = 0.0f,
.keepaspect = 1,
.keepaspect_window = 1,
.taskbar_progress = 1,
.border = 1,
.fit_border = 1,
.WinID = -1,
.window_scale = 1.0,
.x11_bypass_compositor = 2,
.mmcss_profile = "Playback",
.fullscreen = HAVE_RPI ? 1 : 0,
},
};
#undef OPT_BASE_STRUCT
#define OPT_BASE_STRUCT struct dvd_opts
const struct m_sub_options dvd_conf = {
.opts = (const struct m_option[]){
OPT_STRING("dvd-device", device, M_OPT_FILE),
OPT_INT("dvd-speed", speed, 0),
OPT_INTRANGE("dvd-angle", angle, 0, 1, 99),
{0}
},
.size = sizeof(struct dvd_opts),
.defaults = &(const struct dvd_opts){
.angle = 1,
},
};
#undef OPT_BASE_STRUCT
#define OPT_BASE_STRUCT struct MPOpts
const m_option_t mp_opts[] = {
// handled in command line pre-parser (parse_commandline.c)
{"v", CONF_TYPE_STORE, CONF_GLOBAL | CONF_NOCFG, .offset = -1},
{"v", CONF_TYPE_STORE, M_OPT_FIXED | CONF_NOCFG, .offset = -1},
{"playlist", CONF_TYPE_STRING, CONF_NOCFG | M_OPT_MIN | M_OPT_FIXED | M_OPT_FILE,
.min = 1, .offset = -1},
{"{", CONF_TYPE_STORE, CONF_NOCFG | M_OPT_FIXED, .offset = -1},
{"}", CONF_TYPE_STORE, CONF_NOCFG | M_OPT_FIXED, .offset = -1},
// handled in m_config.c
{ "include", CONF_TYPE_STRING, M_OPT_FIXED | M_OPT_FILE, .offset = -1},
{ "profile", CONF_TYPE_STRING_LIST, M_OPT_FIXED, .offset = -1},
{ "include", CONF_TYPE_STRING, M_OPT_FILE, .offset = -1},
{ "profile", CONF_TYPE_STRING_LIST, 0, .offset = -1},
{ "show-profile", CONF_TYPE_STRING, CONF_NOCFG | M_OPT_FIXED, .offset = -1},
{ "list-options", CONF_TYPE_STORE, CONF_NOCFG | M_OPT_FIXED, .offset = -1},
OPT_FLAG("list-properties", property_print_help,
CONF_NOCFG | M_OPT_FIXED | M_OPT_NOPROP),
OPT_CHOICE("player-operation-mode", operation_mode,
M_OPT_FIXED | M_OPT_PRE_PARSE | M_OPT_NOPROP,
({"cplayer", 0}, {"pseudo-gui", 1})),
OPT_FLAG("shuffle", shuffle, 0),
// ------------------------- common options --------------------
OPT_FLAG("quiet", quiet, CONF_GLOBAL),
OPT_FLAG_STORE("really-quiet", verbose, CONF_GLOBAL | CONF_PRE_PARSE, -10),
OPT_FLAG("terminal", use_terminal, CONF_GLOBAL | CONF_PRE_PARSE | M_OPT_TERM),
OPT_GENERAL(char**, "msg-level", msg_levels, CONF_GLOBAL|CONF_PRE_PARSE |
M_OPT_TERM, .type = &m_option_type_msglevels),
OPT_STRING("dump-stats", dump_stats, CONF_GLOBAL | CONF_PRE_PARSE),
OPT_FLAG("msg-color", msg_color, CONF_GLOBAL | CONF_PRE_PARSE | M_OPT_TERM),
OPT_STRING("log-file", log_file, CONF_GLOBAL | CONF_PRE_PARSE | M_OPT_FILE),
OPT_FLAG("msg-module", msg_module, CONF_GLOBAL | M_OPT_TERM),
OPT_FLAG("msg-time", msg_time, CONF_GLOBAL | M_OPT_TERM),
OPT_FLAG("quiet", quiet, 0),
OPT_FLAG_STORE("really-quiet", verbose,
M_OPT_FIXED | CONF_PRE_PARSE | M_OPT_NOPROP, -10),
OPT_FLAG("terminal", use_terminal, CONF_PRE_PARSE | UPDATE_TERM),
OPT_GENERAL(char**, "msg-level", msg_levels, CONF_PRE_PARSE | UPDATE_TERM,
.type = &m_option_type_msglevels),
OPT_STRING("dump-stats", dump_stats, UPDATE_TERM | CONF_PRE_PARSE),
OPT_FLAG("msg-color", msg_color, CONF_PRE_PARSE | UPDATE_TERM),
OPT_STRING("log-file", log_file, CONF_PRE_PARSE | M_OPT_FILE | UPDATE_TERM),
OPT_FLAG("msg-module", msg_module, UPDATE_TERM),
OPT_FLAG("msg-time", msg_time, UPDATE_TERM),
#ifdef _WIN32
OPT_CHOICE("priority", w32_priority, 0,
OPT_CHOICE("priority", w32_priority, UPDATE_PRIORITY,
({"no", 0},
{"realtime", REALTIME_PRIORITY_CLASS},
{"high", HIGH_PRIORITY_CLASS},
@@ -135,68 +289,39 @@ const m_option_t mp_opts[] = {
{"belownormal", BELOW_NORMAL_PRIORITY_CLASS},
{"idle", IDLE_PRIORITY_CLASS})),
#endif
OPT_FLAG("config", load_config, CONF_GLOBAL | CONF_PRE_PARSE),
OPT_FLAG("config", load_config, M_OPT_FIXED | CONF_PRE_PARSE),
OPT_STRING("config-dir", force_configdir,
CONF_GLOBAL | CONF_NOCFG | CONF_PRE_PARSE),
OPT_STRINGLIST("reset-on-next-file", reset_options, M_OPT_GLOBAL),
M_OPT_FIXED | CONF_NOCFG | CONF_PRE_PARSE),
OPT_STRINGLIST("reset-on-next-file", reset_options, 0),
#if HAVE_LUA
OPT_STRINGLIST("script", script_files, CONF_GLOBAL | M_OPT_FILE),
OPT_KEYVALUELIST("script-opts", script_opts, M_OPT_GLOBAL),
OPT_FLAG("osc", lua_load_osc, CONF_GLOBAL),
OPT_FLAG("ytdl", lua_load_ytdl, CONF_GLOBAL),
OPT_STRING("ytdl-format", lua_ytdl_format, CONF_GLOBAL),
OPT_KEYVALUELIST("ytdl-raw-options", lua_ytdl_raw_options, CONF_GLOBAL),
OPT_FLAG("load-scripts", auto_load_scripts, CONF_GLOBAL),
OPT_STRINGLIST("script", script_files, M_OPT_FIXED | M_OPT_FILE),
OPT_KEYVALUELIST("script-opts", script_opts, 0),
OPT_FLAG("osc", lua_load_osc, UPDATE_BUILTIN_SCRIPTS),
OPT_FLAG("ytdl", lua_load_ytdl, UPDATE_BUILTIN_SCRIPTS),
OPT_STRING("ytdl-format", lua_ytdl_format, 0),
OPT_KEYVALUELIST("ytdl-raw-options", lua_ytdl_raw_options, 0),
OPT_FLAG("load-scripts", auto_load_scripts, M_OPT_FIXED),
#endif
// ------------------------- stream options --------------------
OPT_CHOICE_OR_INT("cache", stream_cache.size, 0, 32, 0x7fffffff,
({"no", 0},
{"auto", -1},
{"yes", -2})),
OPT_CHOICE_OR_INT("cache-default", stream_cache.def_size, 0, 32, 0x7fffffff,
({"no", 0})),
OPT_INTRANGE("cache-initial", stream_cache.initial, 0, 0, 0x7fffffff),
OPT_INTRANGE("cache-seek-min", stream_cache.seek_min, 0, 0, 0x7fffffff),
OPT_INTRANGE("cache-backbuffer", stream_cache.back_buffer, 0, 0, 0x7fffffff),
OPT_STRING("cache-file", stream_cache.file, M_OPT_FILE),
OPT_INTRANGE("cache-file-size", stream_cache.file_max, 0, 0, 0x7fffffff),
OPT_SUBSTRUCT("", stream_cache, stream_cache_conf, 0),
#if HAVE_DVDREAD || HAVE_DVDNAV
OPT_STRING("dvd-device", dvd_device, M_OPT_FILE),
OPT_INT("dvd-speed", dvd_speed, 0),
OPT_INTRANGE("dvd-angle", dvd_angle, 0, 1, 99),
OPT_SUBSTRUCT("", dvd_opts, dvd_conf, 0),
#endif /* HAVE_DVDREAD */
OPT_INTPAIR("chapter", chapterrange, 0),
OPT_INTPAIR("chapter", chapterrange, 0, .deprecation_message = "instead of "
"--chapter=A-B use --start=#A --end=#B+1"),
OPT_CHOICE_OR_INT("edition", edition_id, 0, 0, 8190,
({"auto", -1})),
#if HAVE_LIBBLURAY
OPT_STRING("bluray-device", bluray_device, M_OPT_FILE),
OPT_INTRANGE("bluray-angle", bluray_angle, 0, 0, 999),
#endif /* HAVE_LIBBLURAY */
OPT_STRINGLIST("http-header-fields", network_http_header_fields, 0),
OPT_STRING("user-agent", network_useragent, 0),
OPT_STRING("referrer", network_referrer, 0),
OPT_FLAG("cookies", network_cookies_enabled, 0),
OPT_STRING("cookies-file", network_cookies_file, M_OPT_FILE),
OPT_CHOICE("rtsp-transport", network_rtsp_transport, 0,
({"lavf", 0},
{"udp", 1},
{"tcp", 2},
{"http", 3})),
OPT_FLAG("tls-verify", network_tls_verify, 0),
OPT_STRING("tls-ca-file", network_tls_ca_file, M_OPT_FILE),
OPT_STRING("tls-cert-file", network_tls_cert_file, M_OPT_FILE),
OPT_STRING("tls-key-file", network_tls_key_file, M_OPT_FILE),
OPT_DOUBLE("network-timeout", network_timeout, M_OPT_MIN, .min = 0),
// ------------------------- demuxer options --------------------
OPT_CHOICE_OR_INT("frames", play_frames, M_OPT_FIXED, 0, INT_MAX,
({"all", -1})),
OPT_CHOICE_OR_INT("frames", play_frames, 0, 0, INT_MAX, ({"all", -1})),
OPT_REL_TIME("start", play_start, 0),
OPT_REL_TIME("end", play_end, 0),
@@ -207,13 +332,16 @@ const m_option_t mp_opts[] = {
OPT_TIME("ab-loop-a", ab_loop[0], 0, .min = MP_NOPTS_VALUE),
OPT_TIME("ab-loop-b", ab_loop[1], 0, .min = MP_NOPTS_VALUE),
OPT_CHOICE_OR_INT("playlist-pos", playlist_pos, 0, 0, INT_MAX, ({"no", -1})),
OPT_CHOICE_OR_INT("playlist-start", playlist_pos, 0, 0, INT_MAX,
({"auto", -1}, {"no", -1})),
OPT_FLAG("pause", pause, M_OPT_FIXED),
OPT_FLAG("pause", pause, 0),
OPT_CHOICE("keep-open", keep_open, 0,
({"no", 0},
{"yes", 1},
{"always", 2})),
OPT_DOUBLE("image-display-duration", image_display_duration,
M_OPT_RANGE, 0, INFINITY),
OPT_CHOICE("index", index_mode, 0, ({"default", 1}, {"recreate", 0})),
@@ -225,9 +353,9 @@ const m_option_t mp_opts[] = {
OPT_TRACKCHOICE("ff-aid", stream_id_ff[STREAM_AUDIO]),
OPT_TRACKCHOICE("ff-vid", stream_id_ff[STREAM_VIDEO]),
OPT_TRACKCHOICE("ff-sid", stream_id_ff[STREAM_SUB]),
OPT_FLAG_STORE("no-sub", stream_id[0][STREAM_SUB], 0, -2),
OPT_FLAG_STORE("no-video", stream_id[0][STREAM_VIDEO], 0, -2),
OPT_FLAG_STORE("no-audio", stream_id[0][STREAM_AUDIO], 0, -2),
OPT_ALIAS("sub", "sid"),
OPT_ALIAS("video", "vid"),
OPT_ALIAS("audio", "aid"),
OPT_STRINGLIST("alang", stream_lang[STREAM_AUDIO], 0),
OPT_STRINGLIST("slang", stream_lang[STREAM_SUB], 0),
@@ -252,13 +380,6 @@ const m_option_t mp_opts[] = {
OPT_STRING("audio-demuxer", audio_demuxer_name, 0),
OPT_STRING("sub-demuxer", sub_demuxer_name, 0),
OPT_FLAG("demuxer-thread", demuxer_thread, 0),
OPT_DOUBLE("demuxer-readahead-secs", demuxer_min_secs, M_OPT_MIN, .min = 0),
OPT_INTRANGE("demuxer-max-packets", demuxer_max_packs, 0, 0, INT_MAX),
OPT_INTRANGE("demuxer-max-bytes", demuxer_max_bytes, 0, 0, INT_MAX),
OPT_FLAG("force-seekable", force_seekable, 0),
OPT_DOUBLE("cache-secs", demuxer_min_secs_cache, M_OPT_MIN, .min = 0),
OPT_FLAG("cache-pause", cache_pausing, 0),
OPT_DOUBLE("mf-fps", mf_fps, 0),
@@ -278,12 +399,11 @@ const m_option_t mp_opts[] = {
// force video/audio rate:
OPT_DOUBLE("fps", force_fps, CONF_MIN, .min = 0),
OPT_INTRANGE("audio-samplerate", force_srate, 0, 1000, 16*48000),
OPT_CHANNELS("audio-channels", audio_output_channels, 0),
OPT_AUDIOFORMAT("audio-format", audio_output_format, 0),
OPT_FLAG("audio-normalize-downmix", audio_normalize, 0),
OPT_DOUBLE("speed", playback_speed, M_OPT_RANGE | M_OPT_FIXED,
.min = 0.01, .max = 100.0),
OPT_INTRANGE("audio-samplerate", force_srate, UPDATE_AUDIO, 1000, 16*48000),
OPT_CHANNELS("audio-channels", audio_output_channels, UPDATE_AUDIO),
OPT_AUDIOFORMAT("audio-format", audio_output_format, UPDATE_AUDIO),
OPT_FLAG("audio-normalize-downmix", audio_normalize, UPDATE_AUDIO),
OPT_DOUBLE("speed", playback_speed, M_OPT_RANGE, .min = 0.01, .max = 100.0),
OPT_FLAG("audio-pitch-correction", pitch_correction, 0),
@@ -292,10 +412,10 @@ const m_option_t mp_opts[] = {
// ------------------------- codec/vfilter options --------------------
OPT_SETTINGSLIST("af-defaults", af_defs, 0, &af_obj_list),
OPT_SETTINGSLIST("af*", af_settings, 0, &af_obj_list),
OPT_SETTINGSLIST("vf-defaults", vf_defs, 0, &vf_obj_list),
OPT_SETTINGSLIST("vf*", vf_settings, 0, &vf_obj_list),
OPT_SETTINGSLIST("af-defaults", af_defs, 0, &af_obj_list, ),
OPT_SETTINGSLIST("af*", af_settings, 0, &af_obj_list, ),
OPT_SETTINGSLIST("vf-defaults", vf_defs, 0, &vf_obj_list, ),
OPT_SETTINGSLIST("vf*", vf_settings, 0, &vf_obj_list, ),
OPT_CHOICE("deinterlace", deinterlace, 0,
({"auto", -1},
@@ -310,28 +430,24 @@ const m_option_t mp_opts[] = {
OPT_FLAG("ad-spdif-dtshd", dtshd, 0),
OPT_CHOICE_C("hwdec", hwdec_api, 0, mp_hwdec_names),
OPT_CHOICE_C("hwdec-preload", vo.hwdec_preload_api, 0, mp_hwdec_names),
OPT_STRING("hwdec-codecs", hwdec_codecs, 0),
#if HAVE_VIDEOTOOLBOX_HWACCEL
OPT_IMAGEFORMAT("videotoolbox-format", videotoolbox_format, 0),
#endif
OPT_SUBSTRUCT("sws", vo.sws_opts, sws_conf, 0),
// -1 means auto aspect (prefer container size until aspect change)
// 0 means square pixels
OPT_FLOATRANGE("video-aspect", movie_aspect, 0, -1.0, 10.0),
OPT_FLOAT_STORE("no-video-aspect", movie_aspect, 0, 0.0),
OPT_CHOICE("video-aspect-method", aspect_method, 0,
OPT_ASPECT("video-aspect", movie_aspect, UPDATE_IMGPAR, -1.0, 10.0),
OPT_CHOICE("video-aspect-method", aspect_method, UPDATE_IMGPAR,
({"hybrid", 0}, {"bitstream", 1}, {"container", 2})),
OPT_CHOICE("field-dominance", field_dominance, 0,
OPT_CHOICE("field-dominance", field_dominance, UPDATE_IMGPAR,
({"auto", -1}, {"top", 0}, {"bottom", 1})),
OPT_SUBSTRUCT("vd-lavc", vd_lavc_params, vd_lavc_conf, 0),
OPT_SUBSTRUCT("ad-lavc", ad_lavc_params, ad_lavc_conf, 0),
OPT_SUBSTRUCT("demuxer-lavf", demux_lavf, demux_lavf_conf, 0),
OPT_SUBSTRUCT("", demux_lavf, demux_lavf_conf, 0),
OPT_SUBSTRUCT("demuxer-rawaudio", demux_rawaudio, demux_rawaudio_conf, 0),
OPT_SUBSTRUCT("demuxer-rawvideo", demux_rawvideo, demux_rawvideo_conf, 0),
OPT_SUBSTRUCT("demuxer-mkv", demux_mkv, demux_mkv_conf, 0),
@@ -343,82 +459,76 @@ const m_option_t mp_opts[] = {
OPT_PATHLIST("audio-file-paths", audiofile_paths, 0),
OPT_STRING_APPEND_LIST("external-file", external_files, M_OPT_FILE),
OPT_FLAG("autoload-files", autoload_files, 0),
OPT_STRING("sub-codepage", sub_cp, 0),
OPT_FLOAT("sub-delay", sub_delay, 0),
OPT_FLOAT("sub-fps", sub_fps, 0),
OPT_FLOAT("sub-speed", sub_speed, 0),
OPT_FLAG("sub-visibility", sub_visibility, 0),
OPT_FLAG("sub-forced-only", forced_subs_only, 0),
OPT_FLAG("stretch-dvd-subs", stretch_dvd_subs, 0),
OPT_FLAG("stretch-image-subs-to-screen", stretch_image_subs, 0),
OPT_FLOAT("sub-delay", sub_delay, UPDATE_OSD),
OPT_FLOAT("sub-fps", sub_fps, UPDATE_OSD),
OPT_FLOAT("sub-speed", sub_speed, UPDATE_OSD),
OPT_FLAG("sub-visibility", sub_visibility, UPDATE_OSD),
OPT_FLAG("sub-forced-only", forced_subs_only, UPDATE_OSD),
OPT_FLAG("stretch-dvd-subs", stretch_dvd_subs, UPDATE_OSD),
OPT_FLAG("stretch-image-subs-to-screen", stretch_image_subs, UPDATE_OSD),
OPT_FLAG("sub-fix-timing", sub_fix_timing, 0),
OPT_CHOICE("sub-auto", sub_auto, 0,
({"no", -1}, {"exact", 0}, {"fuzzy", 1}, {"all", 2})),
OPT_CHOICE("audio-file-auto", audiofile_auto, 0,
({"no", -1}, {"exact", 0}, {"fuzzy", 1}, {"all", 2})),
OPT_INTRANGE("sub-pos", sub_pos, 0, 0, 100),
OPT_FLOATRANGE("sub-gauss", sub_gauss, 0, 0.0, 3.0),
OPT_FLAG("sub-gray", sub_gray, 0),
OPT_INTRANGE("sub-pos", sub_pos, UPDATE_OSD, 0, 100),
OPT_FLOATRANGE("sub-gauss", sub_gauss, UPDATE_OSD, 0.0, 3.0),
OPT_FLAG("sub-gray", sub_gray, UPDATE_OSD),
OPT_FLAG("sub-ass", ass_enabled, 0),
OPT_FLOATRANGE("sub-scale", sub_scale, 0, 0, 100),
OPT_FLOATRANGE("ass-line-spacing", ass_line_spacing, 0, -1000, 1000),
OPT_FLAG("sub-use-margins", sub_use_margins, 0),
OPT_FLAG("ass-force-margins", ass_use_margins, 0),
OPT_FLAG("ass-vsfilter-aspect-compat", ass_vsfilter_aspect_compat, 0),
OPT_CHOICE("ass-vsfilter-color-compat", ass_vsfilter_color_compat, 0,
OPT_FLOATRANGE("sub-scale", sub_scale, UPDATE_OSD, 0, 100),
OPT_FLOATRANGE("sub-ass-line-spacing", ass_line_spacing, UPDATE_OSD, -1000, 1000),
OPT_FLAG("sub-use-margins", sub_use_margins, UPDATE_OSD),
OPT_FLAG("sub-ass-force-margins", ass_use_margins, UPDATE_OSD),
OPT_FLAG("sub-ass-vsfilter-aspect-compat", ass_vsfilter_aspect_compat, UPDATE_OSD),
OPT_CHOICE("sub-ass-vsfilter-color-compat", ass_vsfilter_color_compat, UPDATE_OSD,
({"no", 0}, {"basic", 1}, {"full", 2}, {"force-601", 3})),
OPT_FLAG("ass-vsfilter-blur-compat", ass_vsfilter_blur_compat, 0),
OPT_FLAG("sub-ass-vsfilter-blur-compat", ass_vsfilter_blur_compat, UPDATE_OSD),
OPT_FLAG("embeddedfonts", use_embedded_fonts, 0),
OPT_STRINGLIST("ass-force-style", ass_force_style_list, 0),
OPT_STRING("ass-styles", ass_styles_file, M_OPT_FILE),
OPT_CHOICE("ass-hinting", ass_hinting, 0,
OPT_STRINGLIST("sub-ass-force-style", ass_force_style_list, UPDATE_OSD),
OPT_STRING("sub-ass-styles", ass_styles_file, M_OPT_FILE),
OPT_CHOICE("sub-ass-hinting", ass_hinting, UPDATE_OSD,
({"none", 0}, {"light", 1}, {"normal", 2}, {"native", 3})),
OPT_CHOICE("ass-shaper", ass_shaper, 0,
OPT_CHOICE("sub-ass-shaper", ass_shaper, UPDATE_OSD,
({"simple", 0}, {"complex", 1})),
OPT_CHOICE("ass-style-override", ass_style_override, 0,
OPT_CHOICE("sub-ass-style-override", ass_style_override, UPDATE_OSD,
({"no", 0}, {"yes", 1}, {"force", 3}, {"signfs", 4}, {"strip", 5})),
OPT_FLAG("sub-scale-by-window", sub_scale_by_window, 0),
OPT_FLAG("sub-scale-with-window", sub_scale_with_window, 0),
OPT_FLAG("ass-scale-with-window", ass_scale_with_window, 0),
OPT_FLAG("osd-bar", osd_bar_visible, 0),
OPT_FLOATRANGE("osd-bar-align-x", osd_bar_align_x, 0, -1.0, +1.0),
OPT_FLOATRANGE("osd-bar-align-y", osd_bar_align_y, 0, -1.0, +1.0),
OPT_FLOATRANGE("osd-bar-w", osd_bar_w, 0, 1, 100),
OPT_FLOATRANGE("osd-bar-h", osd_bar_h, 0, 0.1, 50),
OPT_FLAG("sub-scale-by-window", sub_scale_by_window, UPDATE_OSD),
OPT_FLAG("sub-scale-with-window", sub_scale_with_window, UPDATE_OSD),
OPT_FLAG("sub-ass-scale-with-window", ass_scale_with_window, UPDATE_OSD),
OPT_FLAG("osd-bar", osd_bar_visible, UPDATE_OSD),
OPT_FLOATRANGE("osd-bar-align-x", osd_bar_align_x, UPDATE_OSD, -1.0, +1.0),
OPT_FLOATRANGE("osd-bar-align-y", osd_bar_align_y, UPDATE_OSD, -1.0, +1.0),
OPT_FLOATRANGE("osd-bar-w", osd_bar_w, UPDATE_OSD, 1, 100),
OPT_FLOATRANGE("osd-bar-h", osd_bar_h, UPDATE_OSD, 0.1, 50),
OPT_SUBSTRUCT("osd", osd_style, osd_style_conf, 0),
OPT_SUBSTRUCT("sub-text", sub_text_style, sub_style_conf, 0),
OPT_SUBSTRUCT("sub", sub_style, sub_style_conf, 0),
OPT_FLAG("sub-clear-on-seek", sub_clear_on_seek, 0),
OPT_INTRANGE("teletext-page", teletext_page, 0, 1, 999),
//---------------------- libao/libvo options ------------------------
OPT_SETTINGSLIST("vo", vo.video_driver_list, 0, &vo_obj_list),
OPT_SETTINGSLIST("vo-defaults", vo.vo_defs, 0, &vo_obj_list),
OPT_SETTINGSLIST("ao", audio_driver_list, 0, &ao_obj_list),
OPT_SETTINGSLIST("ao-defaults", ao_defs, 0, &ao_obj_list),
OPT_STRING("audio-device", audio_device, 0),
OPT_STRING("audio-client-name", audio_client_name, 0),
OPT_SETTINGSLIST("ao", audio_driver_list, 0, &ao_obj_list, ),
OPT_SETTINGSLIST("ao-defaults", ao_defs, 0, &ao_obj_list,
.deprecation_message = "deprecated, use global options"),
OPT_STRING("audio-device", audio_device, UPDATE_AUDIO),
OPT_FLAG("audio-exclusive", audio_exclusive, UPDATE_AUDIO),
OPT_STRING("audio-client-name", audio_client_name, UPDATE_AUDIO),
OPT_FLAG("audio-fallback-to-null", ao_null_fallback, 0),
OPT_FLAG("audio-stream-silence", audio_stream_silence, 0),
OPT_FLOATRANGE("audio-wait-open", audio_wait_open, 0, 0, 60),
OPT_CHOICE("force-window", force_vo, 0,
({"no", 0}, {"yes", 1}, {"immediate", 2})),
OPT_FLAG("taskbar-progress", vo.taskbar_progress, 0),
OPT_FLAG("ontop", vo.ontop, M_OPT_FIXED),
OPT_FLAG("border", vo.border, M_OPT_FIXED),
OPT_FLAG("fit-border", vo.fit_border, M_OPT_FIXED),
OPT_FLAG("on-all-workspaces", vo.all_workspaces, M_OPT_FIXED),
OPT_FLAG("window-dragging", allow_win_drag, CONF_GLOBAL),
OPT_CHOICE("softvol", softvol, 0,
({"no", SOFTVOL_NO},
{"yes", SOFTVOL_YES},
{"auto", SOFTVOL_AUTO})),
{"auto", SOFTVOL_AUTO}),
.deprecation_message = "no replacement"),
OPT_FLOATRANGE("volume-max", softvol_max, 0, 100, 1000),
// values <0 for volume and mute are legacy and ignored
OPT_FLOATRANGE("volume", softvol_volume, 0, -1, 1000),
OPT_CHOICE("mute", softvol_mute, 0,
({"auto", -1},
{"no", 0},
({"no", 0},
{"auto", 0},
{"yes", 1})),
OPT_CHOICE("gapless-audio", gapless_audio, 0,
({"no", 0},
@@ -428,62 +538,24 @@ const m_option_t mp_opts[] = {
.min = 0, .max = 10),
OPT_FLOATRANGE("balance", balance, 0, -1, 1),
OPT_GEOMETRY("geometry", vo.geometry, 0),
OPT_SIZE_BOX("autofit", vo.autofit, 0),
OPT_SIZE_BOX("autofit-larger", vo.autofit_larger, 0),
OPT_SIZE_BOX("autofit-smaller", vo.autofit_smaller, 0),
OPT_FLOATRANGE("window-scale", vo.window_scale, 0, 0.001, 100),
OPT_FLAG("force-window-position", vo.force_window_position, 0),
// vo name (X classname) and window title strings
OPT_STRING("x11-name", vo.winname, 0),
OPT_STRING("title", wintitle, 0),
OPT_STRING("force-media-title", media_title, 0),
// set aspect ratio of monitor - useful for 16:9 TV-out
OPT_FLOATRANGE("monitoraspect", vo.force_monitor_aspect, 0, 0.0, 9.0),
OPT_FLOATRANGE("monitorpixelaspect", vo.monitor_pixel_aspect, 0, 0.2, 9.0),
// start in fullscreen mode:
OPT_FLAG("fullscreen", vo.fullscreen, M_OPT_FIXED),
OPT_FLAG("fs", vo.fullscreen, M_OPT_FIXED),
OPT_FLAG("native-keyrepeat", vo.native_keyrepeat, M_OPT_FIXED),
OPT_FLOATRANGE("panscan", vo.panscan, 0, 0.0, 1.0),
OPT_FLOATRANGE("video-zoom", vo.zoom, 0, -20.0, 20.0),
OPT_FLOATRANGE("video-pan-x", vo.pan_x, 0, -3.0, 3.0),
OPT_FLOATRANGE("video-pan-y", vo.pan_y, 0, -3.0, 3.0),
OPT_FLOATRANGE("video-align-x", vo.align_x, 0, -1.0, 1.0),
OPT_FLOATRANGE("video-align-y", vo.align_y, 0, -1.0, 1.0),
OPT_FLAG("video-unscaled", vo.unscaled, 0),
OPT_FLAG("force-rgba-osd-rendering", force_rgba_osd, 0),
OPT_CHOICE_OR_INT("video-rotate", video_rotate, 0, 0, 359,
OPT_CHOICE_OR_INT("video-rotate", video_rotate, UPDATE_IMGPAR, 0, 359,
({"no", -1})),
OPT_CHOICE_C("video-stereo-mode", video_stereo_mode, 0, mp_stereo3d_names),
OPT_CHOICE_C("video-stereo-mode", video_stereo_mode, UPDATE_IMGPAR,
mp_stereo3d_names),
OPT_CHOICE_OR_INT("cursor-autohide", cursor_autohide_delay, 0,
0, 30000, ({"no", -1}, {"always", -2})),
OPT_FLAG("cursor-autohide-fs-only", cursor_autohide_fs, 0),
OPT_FLAG("stop-screensaver", stop_screensaver, 0),
OPT_INT64("wid", vo.WinID, 0),
#if HAVE_X11
OPT_CHOICE("x11-netwm", vo.x11_netwm, 0,
({"auto", 0}, {"no", -1}, {"yes", 1})),
OPT_CHOICE("x11-bypass-compositor", vo.x11_bypass_compositor, 0,
({"no", 0}, {"yes", 1}, {"fs-only", 2}, {"never", 3})),
#endif
#if HAVE_WIN32
OPT_STRING("vo-mmcss-profile", vo.mmcss_profile, M_OPT_FIXED),
#endif
OPT_FLAG("stop-screensaver", stop_screensaver, UPDATE_SCREENSAVER),
OPT_STRING("heartbeat-cmd", heartbeat_cmd, 0,
.deprecation_message = "use Lua scripting instead"),
OPT_FLOAT("heartbeat-interval", heartbeat_interval, CONF_MIN, 0),
OPT_CHOICE_OR_INT("screen", vo.screen_id, 0, 0, 32,
({"default", -1})),
OPT_CHOICE_OR_INT("fs-screen", vo.fsscreen_id, 0, 0, 32,
({"all", -2}, {"current", -1})),
OPT_FLAG("fs-black-out-screens", vo.fs_black_out_screens, 0),
OPT_INTRANGE("brightness", gamma_brightness, 0, -100, 100),
OPT_INTRANGE("saturation", gamma_saturation, 0, -100, 100),
OPT_INTRANGE("contrast", gamma_contrast, 0, -100, 100),
@@ -491,15 +563,13 @@ const m_option_t mp_opts[] = {
OPT_INTRANGE("gamma", gamma_gamma, 0, -100, 100),
OPT_CHOICE_C("video-output-levels", video_output_levels, 0,
mp_csp_levels_names),
OPT_FLAG("keepaspect", vo.keepaspect, 0),
OPT_FLAG("keepaspect-window", vo.keepaspect_window, 0),
OPT_FLAG("use-filedir-conf", use_filedir_conf, 0),
OPT_CHOICE("osd-level", osd_level, 0,
({"0", 0}, {"1", 1}, {"2", 2}, {"3", 3})),
OPT_INTRANGE("osd-duration", osd_duration, 0, 0, 3600000),
OPT_FLAG("osd-fractions", osd_fractions, 0),
OPT_FLOATRANGE("osd-scale", osd_scale, 0, 0, 100),
OPT_FLOATRANGE("osd-scale", osd_scale, UPDATE_OSD, 0, 100),
OPT_FLAG("osd-scale-by-window", osd_scale_by_window, 0),
OPT_DOUBLE("sstep", step_sec, CONF_MIN, 0),
@@ -532,6 +602,7 @@ const m_option_t mp_opts[] = {
OPT_FLAG("save-position-on-quit", position_save_on_quit, 0),
OPT_FLAG("write-filename-in-watch-later-config", write_filename_in_watch_later_config, 0),
OPT_FLAG("ignore-path-in-watch-later-config", ignore_path_in_watch_later_config, 0),
OPT_STRING("watch-later-directory", watch_later_directory, 0),
OPT_FLAG("ordered-chapters", ordered_chapters, 0),
OPT_STRING("ordered-chapters-files", ordered_chapters_files, M_OPT_FILE),
@@ -585,29 +656,37 @@ const m_option_t mp_opts[] = {
OPT_STRING("osd-msg2", osd_msg[1], 0),
OPT_STRING("osd-msg3", osd_msg[2], 0),
OPT_FLAG("video-osd", video_osd, 0),
OPT_CHOICE("idle", player_idle_mode, 0,
({"no", 0},
{"once", 1},
{"yes", 2})),
OPT_FLAG("input-terminal", consolecontrols, CONF_GLOBAL),
OPT_FLAG("input-terminal", consolecontrols, UPDATE_TERM),
OPT_STRING("input-file", input_file, M_OPT_FILE | M_OPT_GLOBAL),
OPT_STRING("input-ipc-server", ipc_path, M_OPT_FILE),
OPT_STRING("input-file", input_file, M_OPT_FILE | UPDATE_INPUT),
OPT_STRING("input-ipc-server", ipc_path, M_OPT_FILE | UPDATE_INPUT),
OPT_SUBSTRUCT("screenshot", screenshot_image_opts, image_writer_conf, 0),
OPT_SUBSTRUCT("screenshot", screenshot_image_opts, screenshot_conf, 0),
OPT_STRING("screenshot-template", screenshot_template, 0),
OPT_STRING("screenshot-directory", screenshot_directory, 0),
OPT_SUBSTRUCT("input", input_opts, input_config, 0),
OPT_SUBSTRUCT("", input_opts, input_config, 0),
OPT_PRINT("list-properties", property_print_help),
OPT_PRINT("list-protocols", stream_print_proto_list),
OPT_PRINT("help", print_help),
OPT_PRINT("h", print_help),
OPT_PRINT("version", print_version),
OPT_PRINT("V", print_version),
OPT_SUBSTRUCT("", vo, vo_sub_opts, 0),
OPT_SUBSTRUCT("", demux_opts, demux_conf, 0),
#if HAVE_GL
OPT_SUBSTRUCT("", gl_video_opts, gl_video_conf, 0),
#endif
#if HAVE_ENCODING
OPT_SUBSTRUCT("", encode_opts, encode_config, 0),
#endif
@@ -658,7 +737,6 @@ const m_option_t mp_opts[] = {
OPT_REPLACED("ss", "start"),
OPT_REPLACED("stop-xscreensaver", "stop-screensaver"),
OPT_REPLACED("sub-fuzziness", "sub-auto"),
OPT_REPLACED("sub", "sub-file"),
OPT_REPLACED("subcp", "sub-codepage"),
OPT_REPLACED("subdelay", "sub-delay"),
OPT_REPLACED("subfile", "sub-file"),
@@ -690,6 +768,35 @@ const m_option_t mp_opts[] = {
OPT_REPLACED("media-title", "force-media-title"),
OPT_REPLACED("input-unix-socket", "input-ipc-server"),
OPT_REPLACED("softvol-max", "volume-max"),
OPT_REMOVED("bluray-angle", "this didn't do anything for a few releases"),
OPT_REPLACED("playlist-pos", "playlist-start"),
OPT_REPLACED("sub-text-font", "sub-font"),
OPT_REPLACED("sub-text-font-size", "sub-font-size"),
OPT_REPLACED("sub-text-color", "sub-color"),
OPT_REPLACED("sub-text-border-color", "sub-border-color"),
OPT_REPLACED("sub-text-shadow-color", "sub-shadow-color"),
OPT_REPLACED("sub-text-back-color", "sub-back-color"),
OPT_REPLACED("sub-text-border-size", "sub-border-size"),
OPT_REPLACED("sub-text-shadow-offset", "sub-shadow-offset"),
OPT_REPLACED("sub-text-spacing", "sub-spacing"),
OPT_REPLACED("sub-text-margin-x", "sub-margin-x"),
OPT_REPLACED("sub-text-margin-y", "sub-margin-y"),
OPT_REPLACED("sub-text-align-x", "sub-align-x"),
OPT_REPLACED("sub-text-align-y", "sub-align-y"),
OPT_REPLACED("sub-text-blur", "sub-blur"),
OPT_REPLACED("sub-text-bold", "sub-bold"),
OPT_REPLACED("sub-text-italic", "sub-italic"),
OPT_REPLACED("ass-line-spacing", "sub-ass-line-spacing"),
OPT_REPLACED("ass-force-margins", "sub-ass-force-margins"),
OPT_REPLACED("ass-vsfilter-aspect-compat", "sub-ass-vsfilter-aspect-compat"),
OPT_REPLACED("ass-vsfilter-color-compat", "sub-ass-vsfilter-color-compat"),
OPT_REPLACED("ass-vsfilter-blur-compat", "sub-ass-vsfilter-blur-compat"),
OPT_REPLACED("ass-force-style", "sub-ass-force-style"),
OPT_REPLACED("ass-styles", "sub-ass-styles"),
OPT_REPLACED("ass-hinting", "sub-ass-hinting"),
OPT_REPLACED("ass-shaper", "sub-ass-shaper"),
OPT_REPLACED("ass-style-override", "sub-ass-style-override"),
OPT_REPLACED("ass-scale-with-window", "sub-ass-scale-with-window"),
{0}
};
@@ -709,32 +816,16 @@ const struct MPOpts mp_default_opts = {
.audio_buffer = 0.2,
.audio_device = "auto",
.audio_client_name = "mpv",
.vo = {
.video_driver_list = NULL,
.monitor_pixel_aspect = 1.0,
.screen_id = -1,
.fsscreen_id = -1,
.panscan = 0.0f,
.keepaspect = 1,
.keepaspect_window = 1,
.taskbar_progress = 1,
.border = 1,
.fit_border = 1,
.WinID = -1,
.window_scale = 1.0,
.x11_bypass_compositor = 2,
.mmcss_profile = "Playback",
},
.allow_win_drag = 1,
.wintitle = "${?media-title:${media-title}}${!media-title:No file} - mpv",
.heartbeat_interval = 30.0,
.stop_screensaver = 1,
.cursor_autohide_delay = 1000,
.gamma_gamma = 1000,
.gamma_brightness = 1000,
.gamma_contrast = 1000,
.gamma_saturation = 1000,
.gamma_hue = 1000,
.gamma_gamma = 0,
.gamma_brightness = 0,
.gamma_contrast = 0,
.gamma_saturation = 0,
.gamma_hue = 0,
.video_osd = 1,
.osd_level = 1,
.osd_duration = 1000,
.osd_bar_align_y = 0.5,
@@ -747,6 +838,7 @@ const struct MPOpts mp_default_opts = {
.sub_use_margins = 1,
.ass_scale_with_window = 0,
.sub_scale_with_window = 1,
.teletext_page = 100,
#if HAVE_LUA
.lua_load_osc = 1,
.lua_load_ytdl = 1,
@@ -765,22 +857,8 @@ const struct MPOpts mp_default_opts = {
.load_config = 1,
.position_resume = 1,
.autoload_files = 1,
.stream_cache = {
.size = -1,
.def_size = 75000,
.initial = 0,
.seek_min = 500,
.back_buffer = 75000,
.file_max = 1024 * 1024,
},
.demuxer_max_packs = 16000,
.demuxer_max_bytes = 400 * 1024 * 1024,
.demuxer_thread = 1,
.demuxer_min_secs = 1.0,
.network_rtsp_transport = 2,
.network_timeout = 0.0,
.hls_bitrate = INT_MAX,
.demuxer_min_secs_cache = 10.0,
.cache_pausing = 1,
.chapterrange = {-1, -1},
.ab_loop = {MP_NOPTS_VALUE, MP_NOPTS_VALUE},
@@ -796,6 +874,7 @@ const struct MPOpts mp_default_opts = {
.play_frames = -1,
.rebase_start_time = 1,
.keep_open = 0,
.image_display_duration = 1.0,
.stream_id = { { [STREAM_AUDIO] = -1,
[STREAM_VIDEO] = -1,
[STREAM_SUB] = -1, },
@@ -828,16 +907,14 @@ const struct MPOpts mp_default_opts = {
.ass_shaper = 1,
.use_embedded_fonts = 1,
.sub_fix_timing = 1,
.sub_cp = "auto",
.screenshot_template = "mpv-shot%n",
.hwdec_api = HAVE_RPI ? HWDEC_RPI : 0,
.hwdec_codecs = "h264,vc1,wmv3,hevc,mpeg2video,vp9",
.videotoolbox_format = IMGFMT_NV12,
.index_mode = 1,
.dvd_angle = 1,
.mf_fps = 1.0,
.display_tags = (char **)(const char*[]){
Loaded 100 of 233 files, more files were not shown because too many files have changed in this diff. Show more