Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4db470e08a | ||
|
|
cf3819ece9 | ||
|
|
575b631d67 | ||
|
|
4c1b45b5ab | ||
|
|
8932d90ec6 | ||
|
|
fc4da23c64 | ||
|
|
017c2808e4 | ||
|
|
c5a8fc793c | ||
|
|
3dcd3476c6 | ||
|
|
ad119460d7 | ||
|
|
e865543be2 | ||
|
|
e84a00651a | ||
|
|
b17ccd1c43 | ||
|
|
62d922e4f0 | ||
|
|
eaa5393c4a | ||
|
|
50b74bf407 | ||
|
|
414cdc9da6 | ||
|
|
1c4bdfaf9c | ||
|
|
76809e5ef7 | ||
|
|
efc72daea9 | ||
|
|
b414d9a9a7 | ||
|
|
2b737f8bfc | ||
|
|
9e99a0c8b9 | ||
|
|
e22ecb1585 | ||
|
|
6358e9be5c | ||
|
|
d57a48c64e | ||
|
|
22691f2e6a | ||
|
|
623a259eee | ||
|
|
fa81e835bc | ||
|
|
46cc45223c | ||
|
|
0e160123fd | ||
|
|
710979e0e8 | ||
|
|
18d3c2ab85 | ||
|
|
f84ca3a516 | ||
|
|
324a40d2e1 | ||
|
|
83e98d3ada | ||
|
|
a424fe1296 | ||
|
|
e09803ae6b | ||
|
|
80669188d6 | ||
|
|
1a3a3aba63 | ||
|
|
0b141eaa82 | ||
|
|
cac071dc23 | ||
|
|
c77f076ae4 | ||
|
|
f4393eaa6c | ||
|
|
bbd6501bd3 | ||
|
|
dc29a21b5c | ||
|
|
4d87844508 | ||
|
|
cced4bf4d6 | ||
|
|
5734cd7063 | ||
|
|
52324a494c | ||
|
|
7ee8237e66 | ||
|
|
6fc0b4e24b | ||
|
|
3d3b1b8bba | ||
|
|
21a90cc49c | ||
|
|
83119f05c4 | ||
|
|
081ddd26b4 | ||
|
|
78349cc188 | ||
|
|
931f614257 | ||
|
|
e682d82527 | ||
|
|
76fd4b4e33 | ||
|
|
623b0a77e1 | ||
|
|
c6c4c3ea9c | ||
|
|
8e5a854374 | ||
|
|
90a0add131 | ||
|
|
443fd456a1 | ||
|
|
910da3af6a | ||
|
|
517f15dc49 | ||
|
|
62cf557b5f | ||
|
|
95e1952377 | ||
|
|
90126b9f88 | ||
|
|
01223a3e0f | ||
|
|
76b0291bf2 | ||
|
|
3fc0c18997 | ||
|
|
7fe9126bba | ||
|
|
22863d6a79 | ||
|
|
5ccd91d639 | ||
|
|
37bf8de258 | ||
|
|
2d3e4fb1b9 | ||
|
|
78cd25388c | ||
|
|
32f0adaeae | ||
|
|
70a7d9d2c5 | ||
|
|
cf14511b1d | ||
|
|
a6d57d654a | ||
|
|
63671a4fbb | ||
|
|
8ace70cfa6 | ||
|
|
1e0edb3e6f | ||
|
|
4ed46bfa25 | ||
|
|
423d47130a | ||
|
|
7a02593dc4 | ||
|
|
220d28b902 | ||
|
|
ff10bd65d6 | ||
|
|
e2895e9684 | ||
|
|
83be06c0ad | ||
|
|
fd7077ade9 | ||
|
|
d40ccc3416 | ||
|
|
57f5ad445d | ||
|
|
a5458a624d | ||
|
|
edf0b93703 | ||
|
|
6bf46eae23 | ||
|
|
774e818371 | ||
|
|
352c00fd08 | ||
|
|
589b38c187 | ||
|
|
62bc8442be | ||
|
|
0edd08a1f6 | ||
|
|
7f5378680b | ||
|
|
4753a92b80 | ||
|
|
584a27e3b8 | ||
|
|
b4abc0a037 | ||
|
|
192318a216 | ||
|
|
822e6e0dd1 | ||
|
|
45b63c78cd | ||
|
|
de47273716 | ||
|
|
7ace4f2115 | ||
|
|
f67dfcbec6 | ||
|
|
6b9f7923af | ||
|
|
c36b1d01c1 | ||
|
|
07222d14f9 | ||
|
|
28fbee7f03 | ||
|
|
b3d2daaa1d | ||
|
|
3437ea23f6 | ||
|
|
16856994e9 | ||
|
|
c22c440c9c | ||
|
|
be42f4c212 | ||
|
|
1b5f127cb0 | ||
|
|
7ea82eb7bc | ||
|
|
3be989dcd0 | ||
|
|
0adc8ee5c1 | ||
|
|
55fe8aab6a | ||
|
|
b2aa388f27 | ||
|
|
fea1dc0cd5 | ||
|
|
8161b47e73 | ||
|
|
f113e03b89 | ||
|
|
630a7b7d82 | ||
|
|
a4e766a77f | ||
|
|
57deaa02d5 | ||
|
|
a6accfdad7 | ||
|
|
8813fe090d | ||
|
|
72ba8515d5 | ||
|
|
21f5d82dc5 | ||
|
|
8c992458c3 | ||
|
|
40149c017c | ||
|
|
0c9f10e0d1 | ||
|
|
5b0d06ca74 | ||
|
|
a410451463 | ||
|
|
3152eed6d8 | ||
|
|
02260882ce | ||
|
|
cd5f0a8612 | ||
|
|
23959eb5b4 | ||
|
|
21a95f5ed9 | ||
|
|
6dc2a23cda | ||
|
|
f94318babc | ||
|
|
b476d21d0a | ||
|
|
16c7de4aab | ||
|
|
8fdd688d48 | ||
|
|
63304b95a1 | ||
|
|
f4263a811f | ||
|
|
a6bf8e7c36 | ||
|
|
6488e77d8a | ||
|
|
34a856f465 | ||
|
|
db218a8d25 | ||
|
|
e3064c3cb7 | ||
|
|
df4d15be7b | ||
|
|
cb5adf4d72 | ||
|
|
440ba33639 | ||
|
|
e4eb9c5469 | ||
|
|
4387919753 | ||
|
|
94123474a4 | ||
|
|
50a7aac4d7 | ||
|
|
2051243a0f | ||
|
|
a21d09d9f8 | ||
|
|
b95a0bfa77 | ||
|
|
43f831b6ba | ||
|
|
b3eba216b7 | ||
|
|
0668c82da5 | ||
|
|
c1e8f3b479 | ||
|
|
64a45f972c | ||
|
|
d4207c64e6 | ||
|
|
abf1fc9a77 | ||
|
|
da8e573b45 | ||
|
|
25c0097c67 | ||
|
|
20d5efb419 | ||
|
|
a18b4b2b19 | ||
|
|
a468e2869d | ||
|
|
cb9975b942 |
No files matched your search
@@ -1,26 +0,0 @@
|
||||
### mpv version and platform
|
||||
|
||||
If you're not using git master or the latest release, update.
|
||||
Releases are listed here: https://github.com/mpv-player/mpv/releases
|
||||
|
||||
### Reproduction steps
|
||||
|
||||
### Expected behavior
|
||||
|
||||
### Actual behavior
|
||||
|
||||
### Log file
|
||||
|
||||
Make a log file made with -v or --log-file=output.txt, paste it to
|
||||
https://0x0.st/ or a similar site, and replace this text with a link to it.
|
||||
|
||||
Providing a log file is strongly encouraged. It is very helpful for reproducing
|
||||
bugs or getting important technical context. Without a log it might not be
|
||||
possible to analyze and fix certain bugs, and your bug report will be closed
|
||||
or ignored.
|
||||
|
||||
### Sample files
|
||||
|
||||
Sample files needed to reproduce this issue can be uploaded to https://0x0.st/
|
||||
or similar sites. (Only needed if the issue cannot be reproduced without it.)
|
||||
Do not use garbage like "cloud storage", especially not Google Drive.
|
||||
@@ -1,5 +0,0 @@
|
||||
Read this before you submit this pull request:
|
||||
https://github.com/mpv-player/mpv/blob/master/DOCS/contribute.md
|
||||
|
||||
Reading this link and following the rules will get your pull request reviewed
|
||||
and merged faster. Nobody wants lazy pull requests.
|
||||
+1
-1
@@ -14,12 +14,12 @@
|
||||
/input/input_conf.h
|
||||
/tags
|
||||
/TAGS
|
||||
/video/out/gl_video_shaders.h
|
||||
/video/out/x11_icon.inc
|
||||
/demux/ebml_defs.c
|
||||
/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
|
||||
|
||||
+30
-54
@@ -1,64 +1,53 @@
|
||||
language: c
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode11
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode10.1
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
compiler: clang
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:stable-deps CI_SCRIPT=ci/build-tumbleweed.sh
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:stable-deps CI_SCRIPT=ci/build-tumbleweed.sh
|
||||
- os: linux
|
||||
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci-mingw64:i686 CI_SCRIPT=ci/build-mingw64.sh TARGET=i686-w64-mingw32
|
||||
- os: linux
|
||||
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci-mingw64:x86_64 CI_SCRIPT=ci/build-mingw64.sh TARGET=x86_64-w64-mingw32
|
||||
|
||||
dist: bionic
|
||||
services:
|
||||
- docker
|
||||
|
||||
sudo: required
|
||||
|
||||
os:
|
||||
- linux
|
||||
# - osx
|
||||
env:
|
||||
matrix:
|
||||
- LIBAV=libav-stable
|
||||
- LIBAV=libav-git
|
||||
- LIBAV=ffmpeg-stable
|
||||
- LIBAV=ffmpeg-git
|
||||
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
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- ci
|
||||
- coverity_scan
|
||||
- /release\/.*$/
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_COMPILER" = "clang" ]; then export CXX="clang++"; fi
|
||||
- if [ "$TRAVIS_COMPILER" = "gcc" ]; then export CXX="g++"; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then docker pull $CONTAINER; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then "$TRAVIS_BUILD_DIR/ci/get_ffmpeg.sh"; fi
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
env: LIBAV=libav-stable
|
||||
- os: osx
|
||||
env: LIBAV=libav-git
|
||||
- os: osx
|
||||
env: LIBAV=ffmpeg-git
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
- os: linux
|
||||
env: LIBAV=ffmpeg-stable
|
||||
- os: linux
|
||||
compiler: clang
|
||||
|
||||
before_install: ./travis-deps libass-stable $LIBAV
|
||||
script:
|
||||
- ./bootstrap.py
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then docker run --env CC --env TARGET -v $TRAVIS_BUILD_DIR:/build $CONTAINER /bin/sh -c "cd /build && $CI_SCRIPT"; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./ci/build-macos.sh; fi
|
||||
after_failure: cat ./build/config.log
|
||||
after_script: TOOLS/travis-rebuild-website
|
||||
- ./waf configure
|
||||
- ./waf build
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.org#mpv-devel"
|
||||
- "irc.freenode.org#mpv-player-dev"
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
||||
@@ -71,16 +60,3 @@ addons:
|
||||
build_command_prepend: "./bootstrap.py && ./waf configure"
|
||||
build_command: "./waf build"
|
||||
branch_pattern: coverity_scan
|
||||
homebrew:
|
||||
packages:
|
||||
- autoconf
|
||||
- automake
|
||||
- freetype
|
||||
- fribidi
|
||||
- libass
|
||||
- libtool
|
||||
- little-cms2
|
||||
- luajit
|
||||
- nasm
|
||||
- pkg-config
|
||||
update: true
|
||||
@@ -1,75 +1,19 @@
|
||||
mpv is a fork of mplayer2, which is a fork of MPlayer.
|
||||
|
||||
mpv as a whole is licensed under the GNU General Public License GPL version 2
|
||||
or later (called GPLv2+ in this document, see LICENSE.GPL for full license
|
||||
text) by default, or the GNU Lesser General Public License LGPL version 2 or
|
||||
later (LGPLv2.1+ in this document, see LICENSE.LGPL for full license text) if
|
||||
built with the --enable-lgpl configure switch.
|
||||
|
||||
Most source files are LGPLv2.1+ or GPLv2+, but some files are available under
|
||||
more liberal licenses, such as BSD, MIT, ISC, and possibly others. Look at the
|
||||
copyright header of each source file, and grep the sources for "Copyright" if
|
||||
you need to know details. C source files without Copyright notice are usually
|
||||
licensed as LGPLv2.1+. Also see the list of files with specific licenses below
|
||||
(not all files can have a standard license header).
|
||||
|
||||
All new contributions must be LGPLv2.1+ licensed. Using a more liberal license
|
||||
compatible to LGPLv2.1+ is also ok.
|
||||
|
||||
Changes done to GPL code must come with the implicit/explicit agreement that the
|
||||
project can relicense the changes to LGPLv2.1+ at a later point without asking
|
||||
the contributor. This is a safeguard for making potential relicensing of
|
||||
remaining GPL code to LGPLv2.1+ easier.
|
||||
|
||||
See DOCS/contribute.md for binding rules wrt. licensing for contributions.
|
||||
mpv as a whole is licensed as GPL version 2 or later (see LICENSE). Most source
|
||||
files are GPLv2+, but some files are available under a more liberal license,
|
||||
such as LGPLv2+, BSD, MIT, ISC, and possibly others. Look at the copyright
|
||||
header of each source file, and grep the sources for "Copyright" if you need
|
||||
to know details. Files without Copyright notice are licensed as LGPLv2+.
|
||||
|
||||
For information about authors and contributors, consult the git log, which
|
||||
contains the complete SVN and CVS history as well.
|
||||
|
||||
"v2.1+" in this context means "version 2.1 or later".
|
||||
Note that mplayer2 as a whole is licensed under GPLv3+. This is because it uses
|
||||
a copy of talloc (part of Samba), which is LGPLv3+, and the next compatible
|
||||
license for this mix is GPLv3+.
|
||||
|
||||
Some libraries are GPLv2+ or GPLv3+ only. Building mpv with Samba support makes
|
||||
it GPLv3+.
|
||||
|
||||
mpv can be built as LGPLv2.1+ with the --enable-lgpl configure option. To add
|
||||
a LGPL mode to mpv, MPlayer code had to be relicensed from GPLv2+ to LGPLv2.1+
|
||||
by asking the MPlayer authors for permission. Since permission could not be
|
||||
obtained from everyone, LGPL mode disables the following features, some of
|
||||
them quite central:
|
||||
- Linux X11 video output
|
||||
- BSD audio output via OSS
|
||||
- NVIDIA/Linux hardware decoding (vdpau, although nvdec usually works)
|
||||
- Linux TV input
|
||||
- minor features: jack, DVD, CDDA, SMB, CACA, legacy direct3d VO
|
||||
Some of these will be fixed in the future. The intended use for LGPL mode is
|
||||
with libmpv, and currently it's not recommended to build mpv CLI in LGPL mode
|
||||
at all.
|
||||
|
||||
The following files are still GPL only (--enable-lgpl disables them):
|
||||
|
||||
audio/out/ao_jack.c will stay GPL
|
||||
audio/out/ao_oss.c will stay GPL
|
||||
stream/dvb* must stay GPL
|
||||
stream/stream_cdda.c unknown
|
||||
stream/stream_dvb.* must stay GPL
|
||||
stream/stream_dvdnav.c unknown
|
||||
stream/stream_smb.c will stay GPLv3
|
||||
video/out/vo_caca.c unknown
|
||||
video/out/vo_direct3d.c unknown
|
||||
video/out/vo_vaapi.c probably impossible (some company's code)
|
||||
video/out/vo_vdpau.c probably impossible (nVidia's code)
|
||||
video/out/vo_x11.c probably impossible
|
||||
video/out/vo_xv.c probably impossible
|
||||
video/out/x11_common.* probably impossible
|
||||
video/vdpau.c hard (GPL-only parts must be ifdefed)
|
||||
video/vdpau.h unknown
|
||||
video/vdpau_mixer.* actual code must be rewritten
|
||||
DOCS/man/ GPLv2+
|
||||
bootstrap.py unknown license, probably GPLv2+ or LGPLv2+
|
||||
etc/mplayer-input.conf unknown license, probably GPLv2+
|
||||
mpv.desktop unknown license, probably GPLv2+
|
||||
etc/restore-old-bindings.conf unknown license, probably GPLv2+
|
||||
|
||||
None of the cases listed above affect the final binary if it's built as
|
||||
LGPL. Linked libraries still can affect the final license (for example if
|
||||
FFmpeg was built as GPL).
|
||||
MPlayer as a whole is licensed under GPLv2 (incompatible to GPLv3!), because
|
||||
some files are licensed to GPLv2 (and _not_ any later version of the license).
|
||||
In particular, this affects the file libmpdemux/demux_ty_osd.c. It is disabled
|
||||
under mplayer2, and has been removed from mpv.
|
||||
+9
-169
@@ -4,7 +4,9 @@ Introduction
|
||||
This file lists all changes that can cause compatibility issues when using
|
||||
mpv through the client API (libmpv and ``client.h``). Since the client API
|
||||
interfaces to input handling (commands, properties) as well as command line
|
||||
options, you should also look at ``interface-changes.rst``.
|
||||
options, this list is interesting for other uses of mpv, such as the Lua
|
||||
scripting interface, key bindings in ``input.rst``, or plain command line
|
||||
usage.
|
||||
|
||||
Normally, changes to the C API that are incompatible to previous iterations
|
||||
receive a major version bump (i.e. the first version number is increased),
|
||||
@@ -16,176 +18,14 @@ The version number is the same as used for MPV_CLIENT_API_VERSION (see
|
||||
``client.h`` how to convert between major/minor version numbers and the flat
|
||||
32 bit integer).
|
||||
|
||||
Also, read the section ``Compatibility`` in ``client.h``, and compatibility.rst.
|
||||
|
||||
Options, commands, properties
|
||||
=============================
|
||||
|
||||
Changes to these are not listed here, but in ``interface-changes.rst``. (Before
|
||||
client API version 1.17, they were listed here partially.)
|
||||
|
||||
This listing includes changes to the bare C API and behavior only, not what
|
||||
you can access with them.
|
||||
Also, read the section ``Compatibility`` in ``client.h``.
|
||||
|
||||
API changes
|
||||
===========
|
||||
|
||||
::
|
||||
|
||||
--- mpv 0.30.0 ---
|
||||
1.106 - Add cancel_fn to mpv_stream_cb_info
|
||||
1.105 - Fix deadlock problems with MPV_RENDER_PARAM_ADVANCED_CONTROL and if
|
||||
the "vd-lavc-dr" option is enabled (which it is by default).
|
||||
There were no actual API changes.
|
||||
API users on older API versions and mpv releases should set
|
||||
"vd-lavc-dr" to "no" to avoid these issues.
|
||||
API users must still adhere to the tricky rules documented in render.h
|
||||
to avoid other deadlocks.
|
||||
1.104 - Deprecate struct mpv_opengl_drm_params. Replaced by mpv_opengl_drm_params_v2
|
||||
- Deprecate MPV_RENDER_PARAM_DRM_DISPLAY. Replaced by MPV_RENDER_PARAM_DRM_DISPLAY_V2.
|
||||
1.103 - redo handling of async commands
|
||||
- add mpv_event_command and make it possible to return values from
|
||||
commands issued with mpv_command_async() or mpv_command_node_async()
|
||||
- add mpv_abort_async_command()
|
||||
1.102 - rename struct mpv_opengl_drm_osd_size to mpv_opengl_drm_draw_surface_size
|
||||
- rename MPV_RENDER_PARAM_DRM_OSD_SIZE to MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE
|
||||
|
||||
--- mpv 0.29.0 ---
|
||||
1.101 - add MPV_RENDER_PARAM_ADVANCED_CONTROL and related API
|
||||
- add MPV_RENDER_PARAM_NEXT_FRAME_INFO and related symbols
|
||||
- add MPV_RENDER_PARAM_BLOCK_FOR_TARGET_TIME
|
||||
- add MPV_RENDER_PARAM_SKIP_RENDERING
|
||||
- add mpv_render_context_get_info()
|
||||
1.100 - bump API number to avoid confusion with mpv release versions
|
||||
- actually apply the GL_MP_MPGetNativeDisplay change for the new render
|
||||
API. This also means compatibility for anything but x11 and wayland
|
||||
through the old opengl-cb GL_MP_MPGetNativeDisplay method is now
|
||||
unsupported.
|
||||
- deprecate mpv_get_wakeup_pipe(). It's complex, but easy to replace
|
||||
using normal API (just set a wakeup callback to a function which
|
||||
writes to a pipe).
|
||||
- add a 1st class hook API, which replaces the hacky mpv_command()
|
||||
based one. The old API is deprecated and will be removed soon. The
|
||||
old API was never meant to be stable, while the new API is.
|
||||
1.29 - the behavior of mpv_terminate_destroy() and mpv_detach_destroy()
|
||||
changes subtly (see documentation in the header file). In particular,
|
||||
mpv_detach_destroy() will not leave the player running in all
|
||||
situations anymore (it gets closer to refcounting).
|
||||
- rename mpv_detach_destroy() to mpv_destroy() (the old function will
|
||||
remain valid as deprecated alias)
|
||||
- add mpv_create_weak_client(), which makes use of above changes
|
||||
- MPV_EVENT_SHUTDOWN is now returned exactly once if a mpv_handle
|
||||
should terminate, instead of spamming the event queue with this event
|
||||
1.28 - deprecate the render opengl_cb API, and replace it with render.h
|
||||
and render_gl.h. The goal is allowing support for APIs other than
|
||||
OpenGL. The old API is emulated with the new API.
|
||||
Likewise, the "opengl-cb" VO is renamed to "libmpv".
|
||||
mpv_get_sub_api() is deprecated along the opengl_cb API.
|
||||
The new API is relatively similar, but not the same. The rough
|
||||
equivalents are:
|
||||
mpv_opengl_cb_init_gl => mpv_render_context_create
|
||||
mpv_opengl_cb_set_update_callback => mpv_render_context_set_update_callback
|
||||
mpv_opengl_cb_draw => mpv_render_context_render
|
||||
mpv_opengl_cb_report_flip => mpv_render_context_report_swap
|
||||
mpv_opengl_cb_uninit_gl => mpv_render_context_free
|
||||
The VO opengl-cb is also renamed to "libmpv".
|
||||
Also, the GL_MP_MPGetNativeDisplay pseudo extension is not used by the
|
||||
render API anymore, and the old opengl-cb API only handles the "x11"
|
||||
and "wl" names anymore. Support for everything else has been removed.
|
||||
The new render API uses proper API parameters, e.g. for X11 you pass
|
||||
MPV_RENDER_PARAM_X11_DISPLAY directly.
|
||||
- deprecate the qthelper.hpp header file. This provided some C++ helper
|
||||
utility functions for Qt with use of libmpv. There is no reason to
|
||||
keep this in the mpv git repository, nor to make it part of the libmpv
|
||||
API. If you're using this header, you can safely copy it into your
|
||||
project - it uses only libmpv public API. Alternatively, it could be
|
||||
maintained in a separate repository by interested parties.
|
||||
1.27 - make opengl-cb the default VO. This causes a subtle behavior change
|
||||
if the API user called mpv_opengl_cb_init_gl(), but does not set
|
||||
the "vo" option. Before, it would still have used another VO (like
|
||||
on the CLI, e.g. vo=gpu). Now it'll behave as if vo=opengl-cb was
|
||||
used.
|
||||
--- mpv 0.28.0 ---
|
||||
1.26 - remove glMPGetNativeDisplay("drm") support
|
||||
- add mpv_opengl_cb_window_pos and mpv_opengl_cb_drm_params and
|
||||
support via glMPGetNativeDisplay() for using it
|
||||
- make --stop-playback-on-init-failure=no the default in libmpv (just
|
||||
like in mpv CLI)
|
||||
--- mpv 0.27.0 ---
|
||||
1.25 - remove setting "no-" options via mpv_set_option*(). (See corresponding
|
||||
deprecation in 0.23.0.)
|
||||
--- mpv 0.25.0 ---
|
||||
1.24 - add a MPV_ENABLE_DEPRECATED preprocessor symbol, which can be defined
|
||||
by the user to exclude deprecated API symbols from the C headers
|
||||
--- mpv 0.23.0 ---
|
||||
1.24 - the deprecated mpv_suspend() and mpv_resume() APIs now do nothing.
|
||||
--- mpv 0.22.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.23.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,
|
||||
set_option_variant, 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
|
||||
is 100% equivalent to "v". The behavior is still the same, thus no
|
||||
actual API change.
|
||||
--- mpv 0.18.0 ---
|
||||
1.21 - mpv_set_property() changes behavior with MPV_FORMAT_NODE. Before this
|
||||
change it rejected mpv_nodes with format==MPV_FORMAT_STRING if the
|
||||
property was not a string or did not have special mechanisms in place
|
||||
the function failed. Now it always invokes the option string parser,
|
||||
and mpv_node with a basic data type works exactly as if the function
|
||||
is invoked with that type directly. This new behavior is equivalent
|
||||
to mpv_set_option().
|
||||
This also affects the mp.set_property_native() Lua function.
|
||||
- generally, setting choice options/properties with "yes"/"no" options
|
||||
can now be set as MPV_FORMAT_FLAG
|
||||
- reading a choice property as MPV_FORMAT_NODE will now return a
|
||||
MPV_FORMAT_FLAG value if the choice is "yes" (true) or "no" (false)
|
||||
This implicitly affects Lua and JSON IPC interfaces as well.
|
||||
- big changes to vo-cmdline on vo_opengl and vo_opengl_hq (but not
|
||||
vo_opengl_cb): options are now normally not reset, but applied on top
|
||||
of the current options. The special undocumented value "-" still
|
||||
works, but now resets all options to before any vo-cmdline command
|
||||
has been called.
|
||||
--- mpv 0.12.0 ---
|
||||
1.20 - deprecate "GL_MP_D3D_interfaces"/"glMPGetD3DInterface", and introduce
|
||||
"GL_MP_MPGetNativeDisplay"/"glMPGetNativeDisplay" (this is a
|
||||
backwards-compatible rename)
|
||||
--- mpv 0.11.0 ---
|
||||
--- mpv 0.10.0 ---
|
||||
1.19 - add "GL_MP_D3D_interfaces" pseudo extension to make it possible to
|
||||
use DXVA2 in OpenGL fullscreen mode in some situations
|
||||
- mpv_request_log_messages() now accepts "terminal-default" as parameter
|
||||
1.18 - add MPV_END_FILE_REASON_REDIRECT, and change behavior of
|
||||
MPV_EVENT_END_FILE accordingly
|
||||
- a bunch of interface-changes.rst changes
|
||||
1.17 - mpv_initialize() now blocks SIGPIPE (details see client.h)
|
||||
--- mpv 0.9.0 ---
|
||||
1.16 - add mpv_opengl_cb_report_flip()
|
||||
- introduce mpv_opengl_cb_draw() and deprecate mpv_opengl_cb_render()
|
||||
- add MPV_FORMAT_BYTE_ARRAY
|
||||
1.15 - mpv_initialize() will now load config files. This requires setting
|
||||
the "config" and "config-dir" options. In particular, it will load
|
||||
mpv.conf.
|
||||
- minor backwards-compatible change to the "seek" and "screenshot"
|
||||
commands (new flag syntax, old additional args deprecated)
|
||||
--- mpv 0.8.0 ---
|
||||
--- mpv 0.8.0 is released ---
|
||||
1.14 - add mpv_wait_async_requests()
|
||||
- the --msg-level option changes its native type from a flat string to
|
||||
a key-value list (setting/reading the option as string still works)
|
||||
@@ -198,7 +38,7 @@ API changes
|
||||
its own and mpv's OpenGL rendering
|
||||
Warning: this API is not stable yet - anything in opengl_cb.h might
|
||||
be changed in completely incompatible ways in minor API bumps
|
||||
--- mpv 0.7.0 ---
|
||||
--- mpv 0.7.0 is released ---
|
||||
1.10 - deprecate/disable everything directly related to script_dispatch
|
||||
(most likely affects nobody)
|
||||
1.9 - add enum mpv_end_file_reason for mpv_event_end_file.reason
|
||||
@@ -221,7 +61,7 @@ API changes
|
||||
1.6 - modify "core-idle" property behavior
|
||||
- MPV_EVENT_LOG_MESSAGE now always sends complete lines
|
||||
- introduce numeric log levels (mpv_log_level)
|
||||
--- mpv 0.6.0 ---
|
||||
--- mpv 0.6.0 is released ---
|
||||
1.5 - change in X11 and "--wid" behavior again. The previous change didn't
|
||||
work as expected, and now the behavior can be explicitly controlled
|
||||
with the "input-x11-keyboard" option. This is only a temporary
|
||||
@@ -230,7 +70,7 @@ API changes
|
||||
although the old option name still works.
|
||||
1.4 - subtle change in X11 and "--wid" behavior
|
||||
(this change was added to 0.5.2, and broke some things, see #1090)
|
||||
--- mpv 0.5.0 ---
|
||||
--- mpv 0.5.0 is released ---
|
||||
1.3 - add MPV_MAKE_VERSION()
|
||||
1.2 - remove "stream-time-pos" property (no replacement)
|
||||
1.1 - remap dvdnav:// to dvd://
|
||||
@@ -242,6 +82,6 @@ API changes
|
||||
insignificant is now significant
|
||||
- add "cache-free" and "cache-used" properties
|
||||
- OSX: the "coreaudio" AO spdif code is split into a separate AO
|
||||
--- mpv 0.4.0 ---
|
||||
--- mpv 0.4.0 is released ---
|
||||
1.0 - the API is declared stable
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
All examples in this directory and its sub-directories are licensed
|
||||
under one of the following licenses:
|
||||
|
||||
WTFPL, ISC, Ms-PL, AGPLv3, BSD (any)
|
||||
|
||||
Pick any license of your liking, and disregard the others.
|
||||
|
||||
(The full text of each license is available on this website:
|
||||
http://opensource.org/licenses/alphabetical )
|
||||
|
||||
Additionally, you may consider the example code to be public domain.
|
||||
You are free to use any of the example code without further
|
||||
requirements or need for attribution.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
Client API examples
|
||||
===================
|
||||
|
||||
All these examples use the mpv client API through libmpv.
|
||||
|
||||
cocoa
|
||||
-----
|
||||
|
||||
Shows how to embed the mpv video window in Objective-C/Cocoa.
|
||||
|
||||
qt
|
||||
--
|
||||
|
||||
Shows how to embed the mpv video window in Qt (using normal desktop widgets).
|
||||
|
||||
qml
|
||||
---
|
||||
|
||||
Shows how to use mpv's OpenGL video renderer in QtQuick2 with QML.
|
||||
|
||||
qml_direct
|
||||
----------
|
||||
|
||||
Alternative example, which typically avoids a FBO indirection. Might be
|
||||
slightly faster, but is less flexible and harder to use.
|
||||
|
||||
simple
|
||||
------
|
||||
|
||||
Very primitive terminal-only example. Shows some most basic API usage.
|
||||
@@ -0,0 +1,211 @@
|
||||
// Plays a video from the command line in a window provided by mpv.
|
||||
// You likely want to play the video in your own window instead,
|
||||
// but that's not quite ready yet.
|
||||
// You may need a basic Info.plist and MainMenu.xib to make this work.
|
||||
|
||||
// Build with: clang -o cocoabasic cocoabasic.m `pkg-config --libs --cflags mpv`
|
||||
|
||||
#include <mpv/client.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static inline void check_error(int status)
|
||||
{
|
||||
if (status < 0) {
|
||||
printf("mpv API error: %s\n", mpv_error_string(status));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface CocoaWindow : NSWindow
|
||||
@end
|
||||
|
||||
@implementation CocoaWindow
|
||||
- (BOOL)canBecomeMainWindow { return YES; }
|
||||
- (BOOL)canBecomeKeyWindow { return YES; }
|
||||
@end
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
{
|
||||
mpv_handle *mpv;
|
||||
dispatch_queue_t queue;
|
||||
NSWindow *w;
|
||||
NSView *wrapper;
|
||||
}
|
||||
@end
|
||||
|
||||
static void wakeup(void *);
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (void)createWindow {
|
||||
|
||||
int mask = NSTitledWindowMask|NSClosableWindowMask|
|
||||
NSMiniaturizableWindowMask|NSResizableWindowMask;
|
||||
|
||||
self->w = [[CocoaWindow alloc]
|
||||
initWithContentRect:NSMakeRect(0,0, 1280, 720)
|
||||
styleMask:mask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
|
||||
[self->w setTitle:@"cocoabasic example"];
|
||||
[self->w makeMainWindow];
|
||||
[self->w makeKeyAndOrderFront:nil];
|
||||
|
||||
NSRect frame = [[self->w contentView] bounds];
|
||||
self->wrapper = [[NSView alloc] initWithFrame:frame];
|
||||
[self->wrapper setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
|
||||
[[self->w contentView] addSubview:self->wrapper];
|
||||
[self->wrapper release];
|
||||
|
||||
NSMenu *m = [[NSMenu alloc] initWithTitle:@"AMainMenu"];
|
||||
NSMenuItem *item = [m addItemWithTitle:@"Apple" action:nil keyEquivalent:@""];
|
||||
NSMenu *sm = [[NSMenu alloc] initWithTitle:@"Apple"];
|
||||
[m setSubmenu:sm forItem:item];
|
||||
[sm addItemWithTitle: @"mpv_command('stop')" action:@selector(mpv_stop) keyEquivalent:@""];
|
||||
[sm addItemWithTitle: @"mpv_command('quit')" action:@selector(mpv_quit) keyEquivalent:@""];
|
||||
[sm addItemWithTitle: @"quit" action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
[NSApp setMenu:m];
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
- (void) applicationDidFinishLaunching:(NSNotification *)notification {
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
atexit_b(^{
|
||||
// Because activation policy has just been set to behave like a real
|
||||
// application, that policy must be reset on exit to prevent, among
|
||||
// other things, the menubar created here from remaining on screen.
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
|
||||
});
|
||||
|
||||
// Read filename
|
||||
NSArray *args = [NSProcessInfo processInfo].arguments;
|
||||
if (args.count < 2) {
|
||||
NSLog(@"Expected filename on command line");
|
||||
exit(1);
|
||||
}
|
||||
NSString *filename = args[1];
|
||||
|
||||
[self createWindow];
|
||||
|
||||
// Deal with MPV in the background.
|
||||
queue = dispatch_queue_create("mpv", DISPATCH_QUEUE_SERIAL);
|
||||
dispatch_async(queue, ^{
|
||||
|
||||
mpv = mpv_create();
|
||||
if (!mpv) {
|
||||
printf("failed creating context\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int64_t wid = (intptr_t) self->wrapper;
|
||||
check_error(mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid));
|
||||
|
||||
// Maybe set some options here, like default key bindings.
|
||||
// NOTE: Interaction with the window seems to be broken for now.
|
||||
check_error(mpv_set_option_string(mpv, "input-default-bindings", "yes"));
|
||||
|
||||
// for testing!
|
||||
check_error(mpv_set_option_string(mpv, "input-media-keys", "yes"));
|
||||
check_error(mpv_set_option_string(mpv, "input-cursor", "no"));
|
||||
check_error(mpv_set_option_string(mpv, "input-vo-keyboard", "yes"));
|
||||
|
||||
// request important errors
|
||||
check_error(mpv_request_log_messages(mpv, "warn"));
|
||||
|
||||
check_error(mpv_initialize(mpv));
|
||||
|
||||
// Register to be woken up whenever mpv generates new events.
|
||||
mpv_set_wakeup_callback(mpv, wakeup, (__bridge void *) self);
|
||||
|
||||
// Load the indicated file
|
||||
const char *cmd[] = {"loadfile", filename.UTF8String, NULL};
|
||||
check_error(mpv_command(mpv, cmd));
|
||||
});
|
||||
}
|
||||
|
||||
- (void) handleEvent:(mpv_event *)event
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_SHUTDOWN: {
|
||||
mpv_detach_destroy(mpv);
|
||||
mpv = NULL;
|
||||
printf("event: shutdown\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case MPV_EVENT_LOG_MESSAGE: {
|
||||
struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data;
|
||||
printf("[%s] %s: %s", msg->prefix, msg->level, msg->text);
|
||||
}
|
||||
|
||||
case MPV_EVENT_VIDEO_RECONFIG: {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSArray *subviews = [self->wrapper subviews];
|
||||
if ([subviews count] > 0) {
|
||||
// mpv's events view
|
||||
NSView *eview = [self->wrapper subviews][0];
|
||||
[self->w makeFirstResponder:eview];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
printf("event: %s\n", mpv_event_name(event->event_id));
|
||||
}
|
||||
}
|
||||
|
||||
- (void) readEvents
|
||||
{
|
||||
dispatch_async(queue, ^{
|
||||
while (mpv) {
|
||||
mpv_event *event = mpv_wait_event(mpv, 0);
|
||||
if (event->event_id == MPV_EVENT_NONE)
|
||||
break;
|
||||
[self handleEvent:event];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void wakeup(void *context) {
|
||||
AppDelegate *a = (__bridge AppDelegate *) context;
|
||||
[a readEvents];
|
||||
}
|
||||
|
||||
// Ostensibly, mpv's window would be hooked up to this.
|
||||
- (BOOL) windowShouldClose:(id)sender
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) mpv_stop
|
||||
{
|
||||
if (mpv) {
|
||||
const char *args[] = {"stop", NULL};
|
||||
mpv_command(mpv, args);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) mpv_quit
|
||||
{
|
||||
if (mpv) {
|
||||
const char *args[] = {"quit", NULL};
|
||||
mpv_command(mpv, args);
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
// Delete this if you already have a main.m.
|
||||
int main(int argc, const char * argv[]) {
|
||||
@autoreleasepool {
|
||||
NSApplication *app = [NSApplication sharedApplication];
|
||||
AppDelegate *delegate = [AppDelegate new];
|
||||
app.delegate = delegate;
|
||||
[app run];
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
#include "main.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <clocale>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
#include <QOpenGLContext>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <QtGui/QOpenGLFramebufferObject>
|
||||
|
||||
#include <QtQuick/QQuickWindow>
|
||||
#include <QtQuick/QQuickView>
|
||||
|
||||
class MpvRenderer : public QQuickFramebufferObject::Renderer
|
||||
{
|
||||
static void *get_proc_address(void *ctx, const char *name) {
|
||||
(void)ctx;
|
||||
QOpenGLContext *glctx = QOpenGLContext::currentContext();
|
||||
if (!glctx)
|
||||
return NULL;
|
||||
return (void *)glctx->getProcAddress(QByteArray(name));
|
||||
}
|
||||
|
||||
mpv::qt::Handle mpv;
|
||||
QQuickWindow *window;
|
||||
mpv_opengl_cb_context *mpv_gl;
|
||||
public:
|
||||
MpvRenderer(const MpvObject *obj)
|
||||
: mpv(obj->mpv), window(obj->window()), mpv_gl(obj->mpv_gl)
|
||||
{
|
||||
int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL);
|
||||
if (r < 0)
|
||||
throw std::runtime_error("could not initialize OpenGL");
|
||||
}
|
||||
|
||||
virtual ~MpvRenderer()
|
||||
{
|
||||
// Until this call is done, we need to make sure the player remains
|
||||
// alive. This is done implicitly with the mpv::qt::Handle instance
|
||||
// in this class.
|
||||
mpv_opengl_cb_uninit_gl(mpv_gl);
|
||||
}
|
||||
|
||||
void render()
|
||||
{
|
||||
QOpenGLFramebufferObject *fbo = framebufferObject();
|
||||
int vp[4] = {0, 0, fbo->width(), fbo->height()};
|
||||
window->resetOpenGLState();
|
||||
mpv_opengl_cb_render(mpv_gl, fbo->handle(), vp);
|
||||
window->resetOpenGLState();
|
||||
}
|
||||
};
|
||||
|
||||
MpvObject::MpvObject(QQuickItem * parent)
|
||||
: QQuickFramebufferObject(parent), mpv_gl(0)
|
||||
{
|
||||
mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
|
||||
if (!mpv)
|
||||
throw std::runtime_error("could not create mpv context");
|
||||
|
||||
mpv_set_option_string(mpv, "terminal", "yes");
|
||||
mpv_set_option_string(mpv, "msg-level", "all=v");
|
||||
|
||||
if (mpv_initialize(mpv) < 0)
|
||||
throw std::runtime_error("could not initialize mpv context");
|
||||
|
||||
// Make use of the MPV_SUB_API_OPENGL_CB API.
|
||||
mpv::qt::set_option_variant(mpv, "vo", "opengl-cb");
|
||||
|
||||
// Request hw decoding, just for testing.
|
||||
mpv::qt::set_option_variant(mpv, "hwdec", "auto");
|
||||
|
||||
// Setup the callback that will make QtQuick update and redraw if there
|
||||
// is a new video frame. Use a queued connection: this makes sure the
|
||||
// doUpdate() function is run on the GUI thread.
|
||||
mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
|
||||
if (!mpv_gl)
|
||||
throw std::runtime_error("OpenGL not compiled in");
|
||||
mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this);
|
||||
connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate,
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
MpvObject::~MpvObject()
|
||||
{
|
||||
if (mpv_gl)
|
||||
mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL);
|
||||
}
|
||||
|
||||
void MpvObject::on_update(void *ctx)
|
||||
{
|
||||
MpvObject *self = (MpvObject *)ctx;
|
||||
emit self->onUpdate();
|
||||
}
|
||||
|
||||
// connected to onUpdate(); signal makes sure it runs on the GUI thread
|
||||
void MpvObject::doUpdate()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void MpvObject::command(const QVariant& params)
|
||||
{
|
||||
mpv::qt::command_variant(mpv, params);
|
||||
}
|
||||
|
||||
void MpvObject::setProperty(const QString& name, const QVariant& value)
|
||||
{
|
||||
mpv::qt::set_property_variant(mpv, name, value);
|
||||
}
|
||||
|
||||
QQuickFramebufferObject::Renderer *MpvObject::createRenderer() const
|
||||
{
|
||||
window()->setPersistentOpenGLContext(true);
|
||||
window()->setPersistentSceneGraph(true);
|
||||
return new MpvRenderer(this);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Qt sets the locale in the QGuiApplication constructor, but libmpv
|
||||
// requires the LC_NUMERIC category to be set to "C", so change it back.
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
|
||||
qmlRegisterType<MpvObject>("mpvtest", 1, 0, "MpvObject");
|
||||
|
||||
QQuickView view;
|
||||
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
view.setSource(QUrl("qrc:///mpvtest/main.qml"));
|
||||
view.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef MPVRENDERER_H_
|
||||
#define MPVRENDERER_H_
|
||||
|
||||
#include <QtQuick/QQuickFramebufferObject>
|
||||
|
||||
#include <mpv/client.h>
|
||||
#include <mpv/opengl_cb.h>
|
||||
#include <mpv/qthelper.hpp>
|
||||
|
||||
class MpvRenderer;
|
||||
|
||||
class MpvObject : public QQuickFramebufferObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
mpv::qt::Handle mpv;
|
||||
mpv_opengl_cb_context *mpv_gl;
|
||||
|
||||
friend class MpvRenderer;
|
||||
|
||||
public:
|
||||
MpvObject(QQuickItem * parent = 0);
|
||||
virtual ~MpvObject();
|
||||
virtual Renderer *createRenderer() const;
|
||||
public slots:
|
||||
void command(const QVariant& params);
|
||||
void setProperty(const QString& name, const QVariant& value);
|
||||
signals:
|
||||
void onUpdate();
|
||||
private slots:
|
||||
void doUpdate();
|
||||
private:
|
||||
static void on_update(void *ctx);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.0
|
||||
|
||||
import mpvtest 1.0
|
||||
|
||||
Item {
|
||||
width: 1280
|
||||
height: 720
|
||||
|
||||
MpvObject {
|
||||
id: renderer
|
||||
anchors.fill: parent
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: renderer.command(["loadfile", "../../../test.mkv"])
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: labelFrame
|
||||
anchors.margins: -50
|
||||
radius: 5
|
||||
color: "white"
|
||||
border.color: "black"
|
||||
opacity: 0.8
|
||||
anchors.fill: box
|
||||
}
|
||||
|
||||
Row {
|
||||
id: box
|
||||
anchors.bottom: renderer.bottom
|
||||
anchors.left: renderer.left
|
||||
anchors.right: renderer.right
|
||||
anchors.margins: 100
|
||||
|
||||
Text {
|
||||
anchors.margins: 10
|
||||
wrapMode: Text.WordWrap
|
||||
text: "QtQuick and mpv are both rendering stuff.\n
|
||||
Click to load ../../../test.mkv"
|
||||
}
|
||||
|
||||
// Don't take these controls too seriously. They're for testing.
|
||||
Column {
|
||||
CheckBox {
|
||||
id: checkbox
|
||||
anchors.margins: 10
|
||||
// Heavily filtered means good, right?
|
||||
text: "Make video look like on a Smart TV"
|
||||
onClicked: {
|
||||
if (checkbox.checked) {
|
||||
renderer.command(["vo_cmdline", "scale=sharpen3:scale-param1=5.0"])
|
||||
} else {
|
||||
renderer.command(["vo_cmdline", ""])
|
||||
}
|
||||
}
|
||||
}
|
||||
Slider {
|
||||
id: slider
|
||||
anchors.margins: 10
|
||||
anchors.left: checkbox.left
|
||||
anchors.right: checkbox.right
|
||||
minimumValue: -100
|
||||
maximumValue: 100
|
||||
value: 0
|
||||
onValueChanged: renderer.setProperty("gamma", slider.value | 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
QT += qml quick
|
||||
|
||||
HEADERS += main.h
|
||||
SOURCES += main.cpp
|
||||
|
||||
CONFIG += link_pkgconfig debug
|
||||
PKGCONFIG += mpv
|
||||
|
||||
RESOURCES += mpvtest.qrc
|
||||
|
||||
OTHER_FILES += main.qml
|
||||
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/mpvtest">
|
||||
<file>main.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "main.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <clocale>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QtQuick/QQuickWindow>
|
||||
#include <QtQuick/QQuickView>
|
||||
|
||||
static void *get_proc_address(void *ctx, const char *name) {
|
||||
(void)ctx;
|
||||
QOpenGLContext *glctx = QOpenGLContext::currentContext();
|
||||
if (!glctx)
|
||||
return NULL;
|
||||
return (void *)glctx->getProcAddress(QByteArray(name));
|
||||
}
|
||||
|
||||
MpvRenderer::MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl)
|
||||
: mpv(a_mpv), mpv_gl(a_mpv_gl), window(0), size()
|
||||
{
|
||||
int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL);
|
||||
if (r < 0)
|
||||
throw std::runtime_error("could not initialize OpenGL");
|
||||
}
|
||||
|
||||
MpvRenderer::~MpvRenderer()
|
||||
{
|
||||
// Until this call is done, we need to make sure the player remains
|
||||
// alive. This is done implicitly with the mpv::qt::Handle instance
|
||||
// in this class.
|
||||
mpv_opengl_cb_uninit_gl(mpv_gl);
|
||||
}
|
||||
|
||||
void MpvRenderer::paint()
|
||||
{
|
||||
window->resetOpenGLState();
|
||||
|
||||
// Render to the whole window.
|
||||
int vp[4] = {0, 0, size.width(), -size.height()};
|
||||
|
||||
// This uses 0 as framebuffer, which indicates that mpv will render directly
|
||||
// to the frontbuffer. Note that mpv will always switch framebuffers
|
||||
// explicitly. Some QWindow setups (such as using QQuickWidget) actually
|
||||
// want you to render into a FBO in the beforeRendering() signal, and this
|
||||
// code won't work there.
|
||||
mpv_opengl_cb_render(mpv_gl, 0, vp);
|
||||
|
||||
window->resetOpenGLState();
|
||||
}
|
||||
|
||||
MpvObject::MpvObject(QQuickItem * parent)
|
||||
: QQuickItem(parent), mpv_gl(0), renderer(0)
|
||||
{
|
||||
mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
|
||||
if (!mpv)
|
||||
throw std::runtime_error("could not create mpv context");
|
||||
|
||||
mpv_set_option_string(mpv, "terminal", "yes");
|
||||
mpv_set_option_string(mpv, "msg-level", "all=v");
|
||||
|
||||
if (mpv_initialize(mpv) < 0)
|
||||
throw std::runtime_error("could not initialize mpv context");
|
||||
|
||||
// Make use of the MPV_SUB_API_OPENGL_CB API.
|
||||
mpv::qt::set_option_variant(mpv, "vo", "opengl-cb");
|
||||
|
||||
// Setup the callback that will make QtQuick update and redraw if there
|
||||
// is a new video frame. Use a queued connection: this makes sure the
|
||||
// doUpdate() function is run on the GUI thread.
|
||||
mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
|
||||
if (!mpv_gl)
|
||||
throw std::runtime_error("OpenGL not compiled in");
|
||||
mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this);
|
||||
connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate,
|
||||
Qt::QueuedConnection);
|
||||
|
||||
connect(this, &QQuickItem::windowChanged,
|
||||
this, &MpvObject::handleWindowChanged);
|
||||
}
|
||||
|
||||
MpvObject::~MpvObject()
|
||||
{
|
||||
if (mpv_gl)
|
||||
mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL);
|
||||
}
|
||||
|
||||
void MpvObject::handleWindowChanged(QQuickWindow *win)
|
||||
{
|
||||
if (!win)
|
||||
return;
|
||||
connect(win, &QQuickWindow::beforeSynchronizing,
|
||||
this, &MpvObject::sync, Qt::DirectConnection);
|
||||
connect(win, &QQuickWindow::sceneGraphInvalidated,
|
||||
this, &MpvObject::cleanup, Qt::DirectConnection);
|
||||
win->setClearBeforeRendering(false);
|
||||
}
|
||||
|
||||
void MpvObject::sync()
|
||||
{
|
||||
if (!renderer) {
|
||||
renderer = new MpvRenderer(mpv, mpv_gl);
|
||||
connect(window(), &QQuickWindow::beforeRendering,
|
||||
renderer, &MpvRenderer::paint, Qt::DirectConnection);
|
||||
}
|
||||
renderer->window = window();
|
||||
renderer->size = window()->size() * window()->devicePixelRatio();
|
||||
}
|
||||
|
||||
void MpvObject::cleanup()
|
||||
{
|
||||
if (renderer) {
|
||||
delete renderer;
|
||||
renderer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MpvObject::on_update(void *ctx)
|
||||
{
|
||||
MpvObject *self = (MpvObject *)ctx;
|
||||
emit self->onUpdate();
|
||||
}
|
||||
|
||||
// connected to onUpdate(); signal makes sure it runs on the GUI thread
|
||||
void MpvObject::doUpdate()
|
||||
{
|
||||
window()->update();
|
||||
}
|
||||
|
||||
void MpvObject::command(const QVariant& params)
|
||||
{
|
||||
mpv::qt::command_variant(mpv, params);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Qt sets the locale in the QGuiApplication constructor, but libmpv
|
||||
// requires the LC_NUMERIC category to be set to "C", so change it back.
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
|
||||
qmlRegisterType<MpvObject>("mpvtest", 1, 0, "MpvObject");
|
||||
|
||||
QQuickView view;
|
||||
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
view.setSource(QUrl("qrc:///mpvtest/main.qml"));
|
||||
view.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef MPVRENDERER_H_
|
||||
#define MPVRENDERER_H_
|
||||
|
||||
#include <QtQuick/QQuickItem>
|
||||
|
||||
#include <mpv/client.h>
|
||||
#include <mpv/opengl_cb.h>
|
||||
#include <mpv/qthelper.hpp>
|
||||
|
||||
class MpvRenderer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
mpv::qt::Handle mpv;
|
||||
mpv_opengl_cb_context *mpv_gl;
|
||||
QQuickWindow *window;
|
||||
QSize size;
|
||||
|
||||
friend class MpvObject;
|
||||
public:
|
||||
MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl);
|
||||
virtual ~MpvRenderer();
|
||||
public slots:
|
||||
void paint();
|
||||
};
|
||||
|
||||
class MpvObject : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
mpv::qt::Handle mpv;
|
||||
mpv_opengl_cb_context *mpv_gl;
|
||||
MpvRenderer *renderer;
|
||||
|
||||
public:
|
||||
MpvObject(QQuickItem * parent = 0);
|
||||
virtual ~MpvObject();
|
||||
public slots:
|
||||
void command(const QVariant& params);
|
||||
void sync();
|
||||
void cleanup();
|
||||
signals:
|
||||
void onUpdate();
|
||||
private slots:
|
||||
void doUpdate();
|
||||
void handleWindowChanged(QQuickWindow *win);
|
||||
private:
|
||||
static void on_update(void *ctx);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.0
|
||||
|
||||
import mpvtest 1.0
|
||||
|
||||
Item {
|
||||
width: 1280
|
||||
height: 720
|
||||
|
||||
MpvObject {
|
||||
id: renderer
|
||||
|
||||
// This object isn't real and not visible; it just renders into the
|
||||
// background of the containing Window.
|
||||
width: 0
|
||||
height: 0
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: renderer.command(["loadfile", "../../../test.mkv"])
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: labelFrame
|
||||
anchors.margins: -50
|
||||
radius: 5
|
||||
color: "white"
|
||||
border.color: "black"
|
||||
opacity: 0.8
|
||||
anchors.fill: box
|
||||
}
|
||||
|
||||
Row {
|
||||
id: box
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 100
|
||||
|
||||
Text {
|
||||
anchors.margins: 10
|
||||
wrapMode: Text.WordWrap
|
||||
text: "QtQuick and mpv are both rendering stuff.\n
|
||||
In this example, mpv is always in the background.\n
|
||||
Click to load ../../../test.mkv"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
QT += qml quick
|
||||
|
||||
HEADERS += main.h
|
||||
SOURCES += main.cpp
|
||||
|
||||
CONFIG += link_pkgconfig debug
|
||||
PKGCONFIG += mpv
|
||||
|
||||
RESOURCES += mpvtest.qrc
|
||||
|
||||
OTHER_FILES += main.qml
|
||||
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/mpvtest">
|
||||
<file>main.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,225 @@
|
||||
// This example can be built with: qmake && make
|
||||
|
||||
#include <clocale>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QFileDialog>
|
||||
#include <QStatusBar>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
#include <QGridLayout>
|
||||
#include <QApplication>
|
||||
#include <QTextEdit>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QJsonDocument>
|
||||
#endif
|
||||
|
||||
#include <mpv/qthelper.hpp>
|
||||
|
||||
#include "qtexample.h"
|
||||
|
||||
static void wakeup(void *ctx)
|
||||
{
|
||||
// This callback is invoked from any mpv thread (but possibly also
|
||||
// recursively from a thread that is calling the mpv API). Just notify
|
||||
// the Qt GUI thread to wake up (so that it can process events with
|
||||
// mpv_wait_event()), and return as quickly as possible.
|
||||
MainWindow *mainwindow = (MainWindow *)ctx;
|
||||
emit mainwindow->mpv_events();
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent)
|
||||
{
|
||||
setWindowTitle("Qt embedding demo");
|
||||
setMinimumSize(640, 480);
|
||||
|
||||
QMenu *menu = menuBar()->addMenu(tr("&File"));
|
||||
QAction *on_open = new QAction(tr("&Open"), this);
|
||||
on_open->setShortcuts(QKeySequence::Open);
|
||||
on_open->setStatusTip(tr("Open a file"));
|
||||
connect(on_open, &QAction::triggered, this, &MainWindow::on_file_open);
|
||||
menu->addAction(on_open);
|
||||
|
||||
QAction *on_new = new QAction(tr("&New window"), this);
|
||||
connect(on_new, &QAction::triggered, this, &MainWindow::on_new_window);
|
||||
menu->addAction(on_new);
|
||||
|
||||
statusBar();
|
||||
|
||||
QMainWindow *log_window = new QMainWindow(this);
|
||||
log = new QTextEdit(log_window);
|
||||
log->setReadOnly(true);
|
||||
log_window->setCentralWidget(log);
|
||||
log_window->setWindowTitle("mpv log window");
|
||||
log_window->setMinimumSize(500, 50);
|
||||
log_window->show();
|
||||
|
||||
mpv = mpv_create();
|
||||
if (!mpv)
|
||||
throw std::runtime_error("can't create mpv instance");
|
||||
|
||||
// Create a video child window. Force Qt to create a native window, and
|
||||
// pass the window ID to the mpv wid option. Works on: X11, win32, Cocoa
|
||||
mpv_container = new QWidget(this);
|
||||
setCentralWidget(mpv_container);
|
||||
mpv_container->setAttribute(Qt::WA_DontCreateNativeAncestors);
|
||||
mpv_container->setAttribute(Qt::WA_NativeWindow);
|
||||
// If you have a HWND, use: int64_t wid = (intptr_t)hwnd;
|
||||
int64_t wid = mpv_container->winId();
|
||||
mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid);
|
||||
|
||||
// Enable default bindings, because we're lazy. Normally, a player using
|
||||
// mpv as backend would implement its own key bindings.
|
||||
mpv_set_option_string(mpv, "input-default-bindings", "yes");
|
||||
|
||||
// Enable keyboard input on the X11 window. For the messy details, see
|
||||
// --input-vo-keyboard on the manpage.
|
||||
mpv_set_option_string(mpv, "input-vo-keyboard", "yes");
|
||||
|
||||
// Let us receive property change events with MPV_EVENT_PROPERTY_CHANGE if
|
||||
// this property changes.
|
||||
mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);
|
||||
|
||||
mpv_observe_property(mpv, 0, "track-list", MPV_FORMAT_NODE);
|
||||
mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NODE);
|
||||
|
||||
// Request log messages with level "info" or higher.
|
||||
// They are received as MPV_EVENT_LOG_MESSAGE.
|
||||
mpv_request_log_messages(mpv, "info");
|
||||
|
||||
// From this point on, the wakeup function will be called. The callback
|
||||
// can come from any thread, so we use the QueuedConnection mechanism to
|
||||
// relay the wakeup in a thread-safe way.
|
||||
connect(this, &MainWindow::mpv_events, this, &MainWindow::on_mpv_events,
|
||||
Qt::QueuedConnection);
|
||||
mpv_set_wakeup_callback(mpv, wakeup, this);
|
||||
|
||||
if (mpv_initialize(mpv) < 0)
|
||||
throw std::runtime_error("mpv failed to initialize");
|
||||
}
|
||||
|
||||
void MainWindow::handle_mpv_event(mpv_event *event)
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_PROPERTY_CHANGE: {
|
||||
mpv_event_property *prop = (mpv_event_property *)event->data;
|
||||
if (strcmp(prop->name, "time-pos") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double time = *(double *)prop->data;
|
||||
std::stringstream ss;
|
||||
ss << "At: " << time;
|
||||
statusBar()->showMessage(QString::fromStdString(ss.str()));
|
||||
} else if (prop->format == MPV_FORMAT_NONE) {
|
||||
// The property is unavailable, which probably means playback
|
||||
// was stopped.
|
||||
statusBar()->showMessage("");
|
||||
}
|
||||
} else if (strcmp(prop->name, "chapter-list") == 0 ||
|
||||
strcmp(prop->name, "track-list") == 0)
|
||||
{
|
||||
// Dump the properties as JSON for demo purposes.
|
||||
#if QT_VERSION >= 0x050000
|
||||
if (prop->format == MPV_FORMAT_NODE) {
|
||||
QVariant v = mpv::qt::node_to_variant((mpv_node *)prop->data);
|
||||
// Abuse JSON support for easily printing the mpv_node contents.
|
||||
QJsonDocument d = QJsonDocument::fromVariant(v);
|
||||
append_log("Change property " + QString(prop->name) + ":\n");
|
||||
append_log(d.toJson().data());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_VIDEO_RECONFIG: {
|
||||
// Retrieve the new video size.
|
||||
int64_t w, h;
|
||||
if (mpv_get_property(mpv, "dwidth", MPV_FORMAT_INT64, &w) >= 0 &&
|
||||
mpv_get_property(mpv, "dheight", MPV_FORMAT_INT64, &h) >= 0 &&
|
||||
w > 0 && h > 0)
|
||||
{
|
||||
// Note that the MPV_EVENT_VIDEO_RECONFIG event doesn't necessarily
|
||||
// imply a resize, and you should check yourself if the video
|
||||
// dimensions really changed.
|
||||
// mpv itself will scale/letter box the video to the container size
|
||||
// if the video doesn't fit.
|
||||
std::stringstream ss;
|
||||
ss << "Reconfig: " << w << " " << h;
|
||||
statusBar()->showMessage(QString::fromStdString(ss.str()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_LOG_MESSAGE: {
|
||||
struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data;
|
||||
std::stringstream ss;
|
||||
ss << "[" << msg->prefix << "] " << msg->level << ": " << msg->text;
|
||||
append_log(QString::fromStdString(ss.str()));
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_SHUTDOWN: {
|
||||
mpv_terminate_destroy(mpv);
|
||||
mpv = NULL;
|
||||
break;
|
||||
}
|
||||
default: ;
|
||||
// Ignore uninteresting or unknown events.
|
||||
}
|
||||
}
|
||||
|
||||
// This slot is invoked by wakeup() (through the mpv_events signal).
|
||||
void MainWindow::on_mpv_events()
|
||||
{
|
||||
// Process all events, until the event queue is empty.
|
||||
while (mpv) {
|
||||
mpv_event *event = mpv_wait_event(mpv, 0);
|
||||
if (event->event_id == MPV_EVENT_NONE)
|
||||
break;
|
||||
handle_mpv_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_file_open()
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName(this, "Open file");
|
||||
if (mpv) {
|
||||
const QByteArray c_filename = filename.toUtf8();
|
||||
const char *args[] = {"loadfile", c_filename.data(), NULL};
|
||||
mpv_command_async(mpv, 0, args);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_new_window()
|
||||
{
|
||||
(new MainWindow())->show();
|
||||
}
|
||||
|
||||
void MainWindow::append_log(const QString &text)
|
||||
{
|
||||
QTextCursor cursor = log->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
cursor.insertText(text);
|
||||
log->setTextCursor(cursor);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if (mpv)
|
||||
mpv_terminate_destroy(mpv);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
// Qt sets the locale in the QApplication constructor, but libmpv requires
|
||||
// the LC_NUMERIC category to be set to "C", so change it back.
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef QTEXAMPLE_H
|
||||
#define QTEXAMPLE_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include <mpv/client.h>
|
||||
|
||||
class QTextEdit;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
void on_file_open();
|
||||
void on_new_window();
|
||||
void on_mpv_events();
|
||||
|
||||
signals:
|
||||
void mpv_events();
|
||||
|
||||
private:
|
||||
QWidget *mpv_container;
|
||||
mpv_handle *mpv;
|
||||
QTextEdit *log;
|
||||
|
||||
void append_log(const QString &text);
|
||||
|
||||
void create_player();
|
||||
void handle_mpv_event(mpv_event *event);
|
||||
};
|
||||
|
||||
#endif // QTEXAMPLE_H
|
||||
@@ -0,0 +1,12 @@
|
||||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = qtexample
|
||||
TEMPLATE = app
|
||||
|
||||
CONFIG += link_pkgconfig debug
|
||||
PKGCONFIG += mpv
|
||||
|
||||
SOURCES += qtexample.cpp
|
||||
HEADERS += qtexample.h
|
||||
@@ -0,0 +1,54 @@
|
||||
// Build with: gcc -o simple simple.c `pkg-config --libs --cflags mpv`
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <mpv/client.h>
|
||||
|
||||
static inline void check_error(int status)
|
||||
{
|
||||
if (status < 0) {
|
||||
printf("mpv API error: %s\n", mpv_error_string(status));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("pass a single media file as argument\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mpv_handle *ctx = mpv_create();
|
||||
if (!ctx) {
|
||||
printf("failed creating context\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Enable default key bindings, so the user can actually interact with
|
||||
// the player (and e.g. close the window).
|
||||
check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes"));
|
||||
mpv_set_option_string(ctx, "input-vo-keyboard", "yes");
|
||||
int val = 1;
|
||||
check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val));
|
||||
|
||||
// Done setting up options.
|
||||
check_error(mpv_initialize(ctx));
|
||||
|
||||
// Play this file.
|
||||
const char *cmd[] = {"loadfile", argv[1], NULL};
|
||||
check_error(mpv_command(ctx, cmd));
|
||||
|
||||
// Let it play, and wait until the user quits.
|
||||
while (1) {
|
||||
mpv_event *event = mpv_wait_event(ctx, 10000);
|
||||
printf("event: %s\n", mpv_event_name(event->event_id));
|
||||
if (event->event_id == MPV_EVENT_SHUTDOWN)
|
||||
break;
|
||||
}
|
||||
|
||||
mpv_terminate_destroy(ctx);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
CLI and API compatibility policy
|
||||
================================
|
||||
|
||||
Human users and API users rely on the mpv/libmpv/scripting/IPC interface not
|
||||
breaking their use case. On the other hand, active development occasionally
|
||||
requires breaking things, such as removing old options or changing options in
|
||||
a way that may break.
|
||||
|
||||
This document lists rules when, what, and how incompatible changes can be made.
|
||||
It's interesting both for mpv developers, who want to change user-visible parts,
|
||||
and mpv users, who want to know what is guaranteed to remain stable.
|
||||
|
||||
Any of the rules below may be overridden by statements in more specific
|
||||
documentation (for example, if the manpage says that a particular option may be
|
||||
removed any time, it means that, and the option probably won't even go through
|
||||
deprecation).
|
||||
|
||||
Additions
|
||||
---------
|
||||
|
||||
Additions are basically always allowed. API users etc. are supposed to deal with
|
||||
the possibility that for example new API functions are added. Some parts of the
|
||||
API may document how they are extended.
|
||||
|
||||
Options, commands, properties, events, hooks (command interface)
|
||||
----------------------------------------------------------------
|
||||
|
||||
All of these are important for interfacing both with end users and API users
|
||||
(which include Lua scripts, libmpv, and the JSON IPC). As such, they constitute
|
||||
a large part of the user interface and APIs.
|
||||
|
||||
All incompatible changes to this must be declared in interface-changes.rst.
|
||||
(This may also list compatible additions, but it's not a requirement.)
|
||||
|
||||
Degrees of importance and compatibility preservation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Critical and central parts of the command interface have the strictest
|
||||
requirements. It may not be reasonable to break them, and other means to achieve
|
||||
some change have to be found. For example, the "seek" command is a bit of a
|
||||
mess, but since changing it would likely affect almost every user, it may be
|
||||
impossible to break at least the commonly used syntax. If changed anyway, there
|
||||
should be a deprecation period of at least 1 year, during which the command
|
||||
still works, and possibly a warning should remain even after this.
|
||||
|
||||
Important/often used parts must be deprecated for at least 2 releases before
|
||||
they can be broken. There must be at least 1 release where the deprecated
|
||||
functionality still works, and a replacement is available (if technically
|
||||
reasonable). For example, a feature deprecated in mpv 0.30.0 may be removed in
|
||||
mpv 0.32.0. Minor releases do not count towards this.
|
||||
|
||||
Less useful parts can be broken immediately, but must come with some sort of
|
||||
removal warning-
|
||||
|
||||
Parts for debugging and testing may be removed any time, potentially even
|
||||
without any sort of documentation.
|
||||
|
||||
Currently, the importance of a part is not documented and not even well-defined,
|
||||
which is probably a mistake.
|
||||
|
||||
Renaming or removing options
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Typically, renaming an option can be done in a compatible way with OPT_REPLACED.
|
||||
You may need to check whether the corresponding properties still work (including
|
||||
messy details like observing properties for changes).
|
||||
|
||||
OPT_REMOVED can be used to inform the user of alternatives or reasons for the
|
||||
removal, which is better than an option not found error. Likewise,
|
||||
m_option.deprecation_message should be set to something helpful.
|
||||
|
||||
Both OPT_REPLACED and OPT_REMOVED can remain in the code for a long time, since
|
||||
they're unintrusive and hopefully make incompatible changes less painful for
|
||||
users.
|
||||
|
||||
Scripting APIs
|
||||
--------------
|
||||
|
||||
This affects internal scripting APIs (currently Lua and JavaScript).
|
||||
|
||||
Vaguely the same rules as with the command interface apply. Since there is a
|
||||
large number of scripts, an effort should be made to provide compatibility
|
||||
for old scripts, but it does not need to be stronger than that of the command
|
||||
interface.
|
||||
|
||||
Undocumented parts of the scripting APIs are _not_ guaranteed for compatibility.
|
||||
This applies especially for internals. Languages like Lua do not have strict
|
||||
access control (nor does the mpv code try to emulate any), so if a script
|
||||
accesses private parts, and breaks on the next mpv release, it's not mpv's
|
||||
problem.
|
||||
|
||||
JSON IPC
|
||||
--------
|
||||
|
||||
The JSON IPC is a thin protocol wrapping the libmpv API and the command
|
||||
interface. Compatibility-wise, it's about the same as the scripting APIs.
|
||||
The JSON protocol commands should remain as compatible as possible, and it
|
||||
should probably accept the current way commands are delimited (line breaks)
|
||||
forever.
|
||||
|
||||
The protocol may accept non-standard JSON extensions, but only standard JSON
|
||||
(possibly with restrictions) is guaranteed for compatibility. Clients which want
|
||||
to remain compatible should not use any extensions.
|
||||
|
||||
CLI
|
||||
---
|
||||
|
||||
Things such as default key bindings do not necessarily require compatibility.
|
||||
However, the release notes should be extremely clear on changes to "important"
|
||||
key bindings. Bindings which restore the old behavior should be added to
|
||||
restore-old-bindings.conf.
|
||||
|
||||
Some option parsing is CLI-only and not available from libmpv or scripting. No
|
||||
compatibility guarantees come with them. However, the rules which mpv uses to
|
||||
distinguish between options and filenames must remain consistent (if the
|
||||
non-deprecated options syntax is used).
|
||||
|
||||
Terminal and log output
|
||||
-----------------------
|
||||
|
||||
There are no compatibility guarantees for the terminal output, or the text
|
||||
logged via ``MPV_EVENT_LOG_MESSAGE`` and similar APIs. In particular, scripts
|
||||
invoking mpv CLI are extremely discouraged from trying to parse text output,
|
||||
and should use other mechanisms such as the JSON IPC.
|
||||
|
||||
Protocols, filters, demuxers, etc.
|
||||
----------------------------------
|
||||
|
||||
Which of these are present is generally not guaranteed, and can even depend
|
||||
on compile time settings.
|
||||
|
||||
The filter list and their sub-options are considered part of the
|
||||
command-interface.
|
||||
|
||||
libmpv C API
|
||||
------------
|
||||
|
||||
The libmpv client API (such as ``<libmpv/client.h>``) mostly gives access to
|
||||
the command interface. The API itself (if looked at as a component separate
|
||||
from the command interface) is intended to be extremely stable.
|
||||
|
||||
All API changes are documented in client-api-changes.rst.
|
||||
|
||||
API compatibility
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The API is *always* compatible. Incompatible changes are only allowed on major
|
||||
API version changes (see ``MPV_CLIENT_API_VERSION``). A major version change is
|
||||
an extremely rare event, which means usually no API symbols are ever removed.
|
||||
|
||||
Essentially removing API functions by making them always return an error, or
|
||||
making it do nothing is allowed in cases where it is unlikely to break most
|
||||
clients, but requires a deprecation period of 2 releases. (This has happened to
|
||||
``mpv_suspend()`` for example.)
|
||||
|
||||
API symbols can be deprecated. This should be clearly marked in the doxygen
|
||||
with ``@deprecated``, and if possible, the affected API symbols should not be
|
||||
visible if the API user defines ``MPV_ENABLE_DEPRECATED`` to 0.
|
||||
|
||||
ABI compatibility
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ABI must never be broken, except on major API version changes. For example,
|
||||
constants don't change their values.
|
||||
|
||||
Structs are tricky. If a struct can be allocated by a user (such as ``mpv_node``),
|
||||
no fields can be added. (Unless it's an union, and the addition does not change
|
||||
the offset or alignment of any of the fields or the struct itself. This has
|
||||
happened to ``mpv_node`` in the past.) If a struct is allocated by libmpv only,
|
||||
new fields can be appended to the end (for example ``mpv_event``).
|
||||
|
||||
The ABI is only backward compatible. This means if a host application is linked
|
||||
to an older libmpv, and libmpv is updated to a newer version, it will still
|
||||
work (as in not causing any undefined behavior).
|
||||
|
||||
Forward compatibility (an application would work with an older libmpv than it
|
||||
was linked to) is not required.
|
||||
+61
-59
@@ -68,7 +68,7 @@ echo "MXE_TARGETS := i686-w64-mingw32.static" >> settings.mk
|
||||
# Build required packages. The following provide a minimum required to build
|
||||
# a reasonable mpv binary (though not an absolute minimum).
|
||||
|
||||
make gcc ffmpeg libass jpeg lua
|
||||
make gcc ffmpeg libass jpeg pthreads lua
|
||||
|
||||
# Add MXE binaries to $PATH
|
||||
export PATH=/opt/mxe/usr/bin/:$PATH
|
||||
@@ -79,7 +79,6 @@ export PATH=/opt/mxe/usr/bin/:$PATH
|
||||
cd ..
|
||||
git clone https://github.com/mpv-player/mpv.git
|
||||
cd mpv
|
||||
python ./bootstrap.py
|
||||
DEST_OS=win32 TARGET=i686-w64-mingw32.static ./waf configure
|
||||
# Or, if 64 bit version,
|
||||
# DEST_OS=win32 TARGET=x86_64-w64-mingw32.static ./waf configure
|
||||
@@ -101,27 +100,25 @@ Installing MSYS2
|
||||
|
||||
1. Download an installer from https://msys2.github.io/
|
||||
|
||||
Both the i686 and the x86_64 version of MSYS2 can build 32-bit and 64-bit
|
||||
mpv binaries when running on a 64-bit version of Windows, but the x86_64
|
||||
version is preferred since the larger address space makes it less prone to
|
||||
fork() errors.
|
||||
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.exe``). **Note:** This is different from
|
||||
the MSYS2 shell that is started from the final installation dialog. You must
|
||||
close that shell and open a new one.
|
||||
2. Add ``C:\msys64\mingw64\bin`` to your ``%PATH%``. mpv will depend on several
|
||||
DLLs in this folder.
|
||||
|
||||
For a 32-bit build, use ``mingw32.exe``.
|
||||
3. Start a MinGW-w64 shell (``mingw64_shell.bat``). For a 32-bit build, use
|
||||
``mingw32_shell.bat``.
|
||||
|
||||
Updating MSYS2
|
||||
--------------
|
||||
|
||||
To prevent errors during post-install, the MSYS2 core runtime must be updated
|
||||
separately.
|
||||
To prevent errors during post-install, ``msys2-runtime`` and ``pacman`` must be
|
||||
updated first.
|
||||
|
||||
```bash
|
||||
# Check for core updates. If instructed, close the shell window and reopen it
|
||||
# before continuing.
|
||||
pacman -Syu
|
||||
# Check for updates to msys2-runtime and pacman. If there were updates, restart
|
||||
# MSYS2 before continuing.
|
||||
pacman -Sy --needed msys2-runtime pacman
|
||||
|
||||
# Update everything else
|
||||
pacman -Su
|
||||
@@ -132,78 +129,83 @@ Installing mpv dependencies
|
||||
|
||||
```bash
|
||||
# Install MSYS2 build dependencies and a MinGW-w64 compiler
|
||||
pacman -S git python $MINGW_PACKAGE_PREFIX-{pkg-config,gcc}
|
||||
pacman -S git pkg-config python3 mingw-w64-x86_64-gcc
|
||||
|
||||
# Install the most important MinGW-w64 dependencies. libass and lcms2 are also
|
||||
# pulled in as dependencies of ffmpeg.
|
||||
pacman -S $MINGW_PACKAGE_PREFIX-{ffmpeg,libjpeg-turbo,lua51}
|
||||
# Install the most important MinGW-w64 dependencies. libass, libbluray and
|
||||
# lcms2 are also pulled in as dependencies of ffmpeg.
|
||||
pacman -S mingw-w64-x86_64-ffmpeg mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-lua
|
||||
|
||||
# Install additional (optional) dependencies
|
||||
pacman -S mingw-w64-x86_64-libdvdnav mingw-w64-x86_64-mpg123 mingw-w64-x86_64-libguess
|
||||
```
|
||||
|
||||
For a 32-bit build, install ``mingw-w64-i686-*`` packages instead.
|
||||
|
||||
Building mpv
|
||||
------------
|
||||
|
||||
Clone the latest mpv from git and install waf. **Note:** ``/usr/bin/python3``
|
||||
is invoked directly here, since an MSYS2 version of Python is required.
|
||||
Clone the latest mpv from git and install waf:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mpv-player/mpv.git && cd mpv
|
||||
/usr/bin/python3 bootstrap.py
|
||||
./bootstrap.py
|
||||
```
|
||||
|
||||
Finally, compile and install mpv. Binaries will be installed to
|
||||
``/mingw64/bin`` or ``/mingw32/bin``.
|
||||
``/mingw64/bin``.
|
||||
|
||||
```bash
|
||||
/usr/bin/python3 waf configure CC=gcc.exe --check-c-compiler=gcc --prefix=$MSYSTEM_PREFIX
|
||||
/usr/bin/python3 waf install
|
||||
# For a 32-bit build, use --prefix=/mingw32 instead
|
||||
./waf configure CC=gcc --prefix=/mingw64
|
||||
./waf install
|
||||
```
|
||||
|
||||
Or, compile and install both libmpv and mpv:
|
||||
|
||||
```bash
|
||||
/usr/bin/python3 waf configure CC=gcc.exe --check-c-compiler=gcc --enable-libmpv-shared --prefix=$MSYSTEM_PREFIX
|
||||
/usr/bin/python3 waf install
|
||||
./waf configure CC=gcc --enable-libmpv-shared --prefix=/mingw64
|
||||
./waf install
|
||||
|
||||
# waf installs libmpv to the wrong directory, so fix it up
|
||||
mv -f /mingw64/bin/pkgconfig/mpv.pc /mingw64/lib/pkgconfig/
|
||||
mv -f /mingw64/bin/libmpv.dll.a /mingw64/lib/
|
||||
sed -i 's_/mingw64/bin_/mingw64/lib_' /mingw64/lib/pkgconfig/mpv.pc
|
||||
rmdir /mingw64/bin/pkgconfig
|
||||
```
|
||||
|
||||
Linking libmpv with MSVC programs
|
||||
---------------------------------
|
||||
Additional dependencies
|
||||
=======================
|
||||
|
||||
You can build C++ programs in Visual Studio and link them with libmpv. To do
|
||||
this, you need a Visual Studio which supports ``stdint.h`` (recent ones do),
|
||||
and you need to create a import library for the mpv DLL:
|
||||
pthreads
|
||||
--------
|
||||
|
||||
mpv will use a pthreads wrapper by default. Either pthreads-win32 or
|
||||
winpthreads should work. The latter is packaged with most MinGW-w64
|
||||
environments, including MSYS2, so it shouldn't be a problem. If you don't have
|
||||
a pthreads wrapper or you want to build mpv without one, configure with:
|
||||
|
||||
```bash
|
||||
lib /def:mpv.def /name:mpv-1.dll /out:mpv.lib /MACHINE:X64
|
||||
./waf configure --enable-win32-internal-pthreads
|
||||
```
|
||||
|
||||
The string in the ``/name:`` parameter must match the filename of the DLL (this
|
||||
is simply the filename the MSVC linker will use). The ``mpv.def`` can be
|
||||
retrieved from the mpv build directory, or can be produced by MingGW's
|
||||
gendef.exe helper from the mpv DLL.
|
||||
libwaio
|
||||
-------
|
||||
|
||||
Static linking is not possible.
|
||||
If you want to use ``--input-file``, you need libwaio. It's available from
|
||||
git://midipix.org/waio
|
||||
|
||||
Running mpv
|
||||
-----------
|
||||
|
||||
If you want to run mpv from the MinGW-w64 shell, you will find the experience
|
||||
much more pleasant if you use the ``winpty`` utility
|
||||
To compile libwaio in MSYS2, run:
|
||||
|
||||
```bash
|
||||
pacman -S winpty
|
||||
winpty mpv.com ToS-4k-1920.mov
|
||||
git clone git://midipix.org/waio && cd waio
|
||||
|
||||
# 32-bit build, run from mingw32_shell.bat
|
||||
./build-mingw-nt32 lib-static CC=gcc AR=ar
|
||||
cp -r include/waio /mingw32/include
|
||||
cp lib32/libwaio.a /mingw32/lib
|
||||
|
||||
# 64-bit build, run from mingw64_shell.bat
|
||||
./build-mingw-nt64 lib-static CC=gcc AR=ar
|
||||
cp -r include/waio /mingw64/include
|
||||
cp lib64/libwaio.a /mingw64/lib
|
||||
```
|
||||
|
||||
If you want to move / copy ``mpv.exe`` and ``mpv.com`` to somewhere other than
|
||||
``/mingw64/bin/`` for use outside the MinGW-w64 shell, they will still depend on
|
||||
DLLs in that folder. The simplest solution is to add ``C:\msys64\mingw64\bin``
|
||||
to the windows system ``%PATH%``. Beware though that this can cause problems or
|
||||
confusion in Cygwin if that is also installed on the machine.
|
||||
|
||||
Use of the ANGLE OpenGL backend requires a copy of the D3D compiler DLL that
|
||||
matches the version of the D3D SDK that ANGLE was built with
|
||||
(``d3dcompiler_43.dll`` in case of MinGW-built ANGLE) in the path or in the
|
||||
same folder as mpv. It must be of the same architecture (x86_64 / i686) as the
|
||||
mpv you compiled. You can find copies here:
|
||||
|
||||
https://mpv.srsfckn.biz/d3dcompiler.7z
|
||||
+27
-119
@@ -4,67 +4,28 @@ How to contribute
|
||||
General
|
||||
-------
|
||||
|
||||
The main contact for mpv development is IRC, specifically #mpv
|
||||
and #mpv-devel on Freenode. Github is used for code review and
|
||||
long term discussions.
|
||||
The main contact for mpv development is IRC, specifically #mpv-player
|
||||
and #mpv-player-dev on Freenode.
|
||||
|
||||
Sending patches
|
||||
---------------
|
||||
|
||||
- Make a github pull request, or send a link to a plaintext patch created with
|
||||
``git format-patch``.
|
||||
- Plain diffs posted as pastebins are not acceptable! (Especially if the http
|
||||
link returns HTML.) They only cause extra work for everyone, because they lack
|
||||
commit message and authorship information.
|
||||
- Never send patches to any of the developers email addresses.
|
||||
- If your changes are not supposed to be merged immediately, mark them as
|
||||
"[RFC]" in the commit message or the pull request title.
|
||||
- Be sure to test your changes. If you didn't, please say so in the commit
|
||||
message and the pull request text.
|
||||
|
||||
Copyright of contributions
|
||||
--------------------------
|
||||
|
||||
- The copyright belongs to contributors. The project is a collaborative work. By
|
||||
sending your changes, you agree to license your contributions according to the
|
||||
requirements of this project.
|
||||
- All new code must be LGPLv2.1+ licensed, or come with the implicit agreement
|
||||
that it will be relicensed to LGPLv2.1+ later (see ``Copyright`` in the
|
||||
repository root directory).
|
||||
- 100% compatible licenses are allowed too.
|
||||
- Changes in files with more liberal licenses (such as BSD, MIT, or ISC) are
|
||||
assumed to be dual-licensed under LGPLv2.1+ and the license indicated in the
|
||||
file header.
|
||||
- You must be either the exclusive author of the patch, or acknowledge all
|
||||
authors involved in the commit message. If you take 3rd party code, authorship
|
||||
and copyright must be properly acknowledged. If you're making changes on
|
||||
behalf of your employer, and the employer owns the copyright, you must mention
|
||||
this. If the license of the code is not LGPLv2.1+, you must mention this.
|
||||
- These license statements are legally binding.
|
||||
- Don't use fake names (something that looks like an actual names, and may be
|
||||
someone else's name, but is not your legal name). Using a pseudonyms is
|
||||
allowed if it can be used to identify or contact you, even if whatever
|
||||
account you used to submit the patch dies.
|
||||
- Do not add your name to the license header. This convention is not used by
|
||||
this project, and neither copyright law nor any of the used licenses require
|
||||
it.
|
||||
|
||||
Write good commit messages
|
||||
--------------------------
|
||||
|
||||
``git format-patch``. diffs posted as pastebins (especially if the http link
|
||||
returns HTML) just cause extra work for everyone, because they lack commit
|
||||
message and authorship information.
|
||||
- Write informative commit messages. Use present tense to describe the
|
||||
situation with the patch applied, and past tense for the situation before
|
||||
the change.
|
||||
- The subject line (the first line in a commit message) should contain a
|
||||
prefix identifying the sub system, followed by a short description what
|
||||
impact this commit has. This subject line and the commit message body
|
||||
shouldn't be longer than 72 characters per line, because it messes up the
|
||||
output of many git tools otherwise.
|
||||
impact this commit has. This subject line shouldn't be longer than 72
|
||||
characters, because it messes up the output of many git tools otherwise.
|
||||
|
||||
For example, you fixed a crash in af_volume.c:
|
||||
|
||||
- Bad: ``fixed the bug (wtf?)``
|
||||
- Good: ``af_volume: fix crash due to null pointer access``
|
||||
Bad: ``fixed the bug (wtf?)``
|
||||
Good: ``af_volume: fix crash due to null pointer access``
|
||||
|
||||
Having a prefix gives context, and is especially useful when trying to find
|
||||
a specific change by looking at the history, or when running ``git blame``.
|
||||
@@ -84,33 +45,12 @@ Write good commit messages
|
||||
|
||||
Important: put an empty line between the subject line and the commit message.
|
||||
If this is missing, it will break display in common git tools.
|
||||
- Another summary of good conventions: https://chris.beams.io/posts/git-commit/
|
||||
|
||||
Split changes into multiple commits
|
||||
-----------------------------------
|
||||
|
||||
- Follow git good practices, and split independent changes into several commits.
|
||||
It's usually OK to put them into a single pull request.
|
||||
- Try to separate cosmetic and functional changes. It's ok to make a few
|
||||
additional cosmetic changes in the same file you're working on. But don't do
|
||||
something like reformatting a whole file, and hiding an actual functional
|
||||
change in the same commit.
|
||||
|
||||
Touching user-visible parts may require updating the mpv docs
|
||||
-------------------------------------------------------------
|
||||
|
||||
- Most user-visible things are normally documented in DOCS/man/. If your commit
|
||||
touches documented behavior, list of sub-options, etc., you need to adjust the
|
||||
documentation.
|
||||
- These changes usually go into the same commit that changes the code.
|
||||
- Changes to command line options (addition/modification/removal) must be
|
||||
documented in options.rst.
|
||||
- Changes to input properties or input commands must be documented in input.rst.
|
||||
- All incompatible changes to the user interface (options, properties, commands)
|
||||
must be documented with a small note in interface-changes.rst. (Additions may
|
||||
be documented there as well, but this isn't required.)
|
||||
- Changes to the libmpv API must be reflected in the libmpv's headers doxygen,
|
||||
and in client-api-changes.rst.
|
||||
- If you add a new command line option, document it in options.rst. If you
|
||||
add a new input property, document it in input.rst.
|
||||
|
||||
Code formatting
|
||||
---------------
|
||||
@@ -153,16 +93,18 @@ mpv uses C99 with K&R formatting, with some exceptions.
|
||||
do_something();
|
||||
}
|
||||
```
|
||||
- If the if has an else branch, both branches should use braces, even if they're
|
||||
technically redundant.
|
||||
- If the body of an if statement uses braces, the else branch should also
|
||||
use braces (and reverse).
|
||||
|
||||
Example:
|
||||
|
||||
```C
|
||||
if (a) {
|
||||
one_line();
|
||||
// do something
|
||||
something();
|
||||
something_else();
|
||||
} else {
|
||||
one_other_line();
|
||||
one_line();
|
||||
}
|
||||
```
|
||||
- If an if condition spans multiple physical lines, then put the opening brace
|
||||
@@ -180,62 +122,28 @@ mpv uses C99 with K&R formatting, with some exceptions.
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
(If the if body is simple enough, this rule can be skipped.)
|
||||
- Remove any trailing whitespace.
|
||||
- Do not make stray whitespaces changes.
|
||||
- If the file you're editing uses formatting different from from what is
|
||||
described here, it's probably an old file from times when nobody followed a
|
||||
consistent style. You're free to use the existing style, or the new style, or
|
||||
to send a patch to reformat the file to the new style before making functional
|
||||
changes.
|
||||
|
||||
General coding
|
||||
--------------
|
||||
|
||||
- Use C99. Also freely make use of C99 features if it's appropriate, such as
|
||||
stdbool.h. (Except VLA and complex number types.)
|
||||
- Don't use non-standard language (such as GNU C-only features). In some cases
|
||||
they may be warranted, if they are optional (such as attributes enabling
|
||||
printf-like format string checks). "#pragma once" is allowed as an exception.
|
||||
stdbool.h.
|
||||
- Don't use GNU-only features. In some cases they may be warranted, if they
|
||||
are optional (such as attributes enabling printf-like format string checks).
|
||||
But in general, standard C99 should be used.
|
||||
- The same applies to libc functions. We have to be Windows-compatible too. Use
|
||||
functions guaranteed by C99 or POSIX only, unless your use is guarded by a
|
||||
configure check. There is some restricted use of C11 (ask on IRC for details).
|
||||
configure check.
|
||||
- Prefer fusing declaration and initialization, rather than putting declarations
|
||||
on the top of a block. Obvious data flow is more important than avoiding
|
||||
mixing declarations and statements, which is just a C90 artifact.
|
||||
- tech-overview.txt might help to get an overview how mpv is structured.
|
||||
- If you add features that require intrusive changes, discuss them on the dev
|
||||
channel first. There might be a better way to add a feature and it can avoid
|
||||
wasted work.
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
|
||||
We have one, but the document describing it got lost accidentally.
|
||||
|
||||
Rules for git push access
|
||||
-------------------------
|
||||
|
||||
Push access to the main git repository is handed out on an arbitrary basis. If
|
||||
you got access, the following rules must be followed:
|
||||
|
||||
- You are expected to follow the general development rules as outlined in this
|
||||
whole document.
|
||||
- You must be present on the IRC dev channel when you push something.
|
||||
- Anyone can push small fixes: typo corrections, small/obvious/uncontroversial
|
||||
bug fixes, edits to the user documentation or code comments, and so on.
|
||||
- You can freely make changes to parts of the code which you maintain. For
|
||||
larger changes, it's recommended to let others review the changes first.
|
||||
- You automatically maintain code if you wrote or modified most of it before
|
||||
(e.g. you made larger changes to it before, did partial or full rewrites, did
|
||||
major bug fixes, or you're the original author of the code). If there is more
|
||||
than one maintainer, you may need to come to an agreement with the others how
|
||||
to handle this to avoid conflict.
|
||||
- If you make a pull requests (especially if it's to code you maintain), and you
|
||||
want reviews, explicitly ping the people from which you expect reviews.
|
||||
- As a maintainer, you can approve pull requests by others to "your" code.
|
||||
- If you approve or merge 3rd party changes, make sure they follow the general
|
||||
development rules.
|
||||
- Changes to user interface and public API must always be approved by the
|
||||
project leader.
|
||||
- Seasoned project members are allowed to revert commits that broke the build,
|
||||
or broke basic functionality in a catastrophic way, and the developer who
|
||||
broke it is unavailable. (Depending on severity.)
|
||||
- Adhere to the CoC.
|
||||
- The project leader is not bound by these rules.
|
||||
+6
-144
@@ -31,8 +31,9 @@ estimated remaining duration of the source file is used.
|
||||
|
||||
Note::
|
||||
|
||||
Usage of relative or absolute paths as well as any protocol prefixes may be
|
||||
prevented for security reasons.
|
||||
mpv can't use ordered chapter files in EDL entries. Usage of relative or
|
||||
absolute paths as well as any protocol prefixes is prevented for security
|
||||
reasons.
|
||||
|
||||
|
||||
Syntax of mpv EDL files
|
||||
@@ -51,8 +52,7 @@ The rest of the lines belong to one of these classes:
|
||||
1) An empty or commented line. A comment starts with ``#``, which must be the
|
||||
first character in the line. The rest of the line (up until the next line
|
||||
break) is ignored. An empty line has 0 bytes between two line feed bytes.
|
||||
2) A header entry if the line starts with ``!``.
|
||||
3) A segment entry in all other cases.
|
||||
2) A segment entry in all other cases.
|
||||
|
||||
Each segment entry consists of a list of named or unnamed parameters.
|
||||
Parameters are separated with ``,``. Named parameters consist of a name,
|
||||
@@ -64,8 +64,8 @@ Syntax::
|
||||
segment_entry ::= <param> ( <param> ',' )*
|
||||
param ::= [ <name> '=' ] ( <value> | '%' <number> '%' <valuebytes> )
|
||||
|
||||
The ``name`` string can consist of any characters, except ``=%,;\n!``. The
|
||||
``value`` string can consist of any characters except of ``,;\n!``.
|
||||
The ``name`` string can consist of any characters, except ``=%,;\n``. The
|
||||
``value`` string can consist of any characters except of ``,;\n``.
|
||||
|
||||
The construct starting with ``%`` allows defining any value with arbitrary
|
||||
contents inline, where ``number`` is an integer giving the number of bytes in
|
||||
@@ -95,93 +95,6 @@ to ``20``, ``param3`` to ``value,escaped``, ``param4`` to ``value2``.
|
||||
Instead of line breaks, the character ``;`` can be used. Line feed bytes and
|
||||
``;`` are treated equally.
|
||||
|
||||
Header entries start with ``!`` as first character after a line break. Header
|
||||
entries affect all other file entries in the EDL file. Their format is highly
|
||||
implementation specific. They should generally follow the file header, and come
|
||||
before any file entries.
|
||||
|
||||
Disabling chapter generation and copying
|
||||
========================================
|
||||
|
||||
By default, chapters from the source ranges are copied to the virtual file's
|
||||
chapters. Also, a chapter is inserted after each range. This can be disabled
|
||||
with the ``no_chapters`` header.
|
||||
|
||||
Example::
|
||||
|
||||
!no_chapters
|
||||
|
||||
|
||||
MP4 DASH
|
||||
========
|
||||
|
||||
This is a header that helps implementing DASH, although it only provides a low
|
||||
level mechanism.
|
||||
|
||||
If this header is set, the given url designates an mp4 init fragment. It's
|
||||
downloaded, and every URL in the EDL is prefixed with the init fragment on the
|
||||
byte stream level. This is mostly for use by mpv's internal ytdl support. The
|
||||
ytdl script will call youtube-dl, which in turn actually processes DASH
|
||||
manifests. It may work only for this very specific purpose and fail to be
|
||||
useful in other scenarios. It can be removed or changed in incompatible ways
|
||||
at any times.
|
||||
|
||||
Example::
|
||||
|
||||
!mp4_dash,init=url
|
||||
|
||||
The ``url`` is encoded as parameter value as defined in the general EDL syntax.
|
||||
It's expected to point to an "initialization fragment", which will be prefixed
|
||||
to every entry in the EDL on the byte stream level.
|
||||
|
||||
The current implementation will
|
||||
|
||||
- ignore stream start times
|
||||
- use durations as hint for seeking only
|
||||
- not adjust source timestamps
|
||||
- open and close segments (i.e. fragments) as needed
|
||||
- not add segment boundaries as chapter points
|
||||
- require full compatibility between all segments (same codec etc.)
|
||||
|
||||
Another header part of this mechanism is ``no_clip``. This header is similar
|
||||
to ``mp4_dash``, but does not include on-demand opening/closing of segments,
|
||||
and does not support init segments. It also exists solely to support internal
|
||||
ytdl requirements.
|
||||
|
||||
The ``mp4_dash`` and ``no_clip`` headers are not part of the core EDL format.
|
||||
They may be changed or removed at any time, depending on mpv's internal
|
||||
requirements.
|
||||
|
||||
Separate files for tracks
|
||||
=========================
|
||||
|
||||
The special ``new_stream`` header lets you specify separate parts and time
|
||||
offsets for separate tracks. This can for example be used to source audio and
|
||||
video track from separate files.
|
||||
|
||||
Example::
|
||||
|
||||
# mpv EDL v0
|
||||
video.mkv
|
||||
!new_stream
|
||||
audio.mkv
|
||||
|
||||
This adds all tracks from both files to the virtual track list. Upon playback,
|
||||
the tracks will be played at the same time, instead of appending them. The files
|
||||
can contain more than 1 stream; the apparent effect is the same as if the second
|
||||
part after the ``!new_stream`` part were in a separate ``.edl`` file and added
|
||||
with ``--external-file``.
|
||||
|
||||
Note that all metadata between the stream sets created by ``new_stream`` is
|
||||
disjoint. Global metadata is taken from the first part only.
|
||||
|
||||
In context of mpv, this is redundant to the ``--audio-file`` and
|
||||
``--external-file`` options, but (as of this writing) has the advantage that
|
||||
this will use a unified cache for all streams.
|
||||
|
||||
The ``new_stream`` header is not part of the core EDL format. It may be changed
|
||||
or removed at any time, depending on mpv's internal requirements.
|
||||
|
||||
Timestamp format
|
||||
================
|
||||
|
||||
@@ -198,54 +111,6 @@ Example::
|
||||
|
||||
Plays chapter 3 and ends with the start of chapter 7 (4 chapters later).
|
||||
|
||||
Implicit chapters
|
||||
=================
|
||||
|
||||
mpv will add one chapter per segment entry to the virtual timeline.
|
||||
|
||||
By default, the chapter's titles will match the entries' filenames.
|
||||
You can override set the ``title`` option to override the chapter title for
|
||||
that segment.
|
||||
|
||||
Example::
|
||||
|
||||
# mpv EDL v0
|
||||
cap.ts,5,240
|
||||
OP.mkv,0,90,title=Show Opening
|
||||
|
||||
The virtual timeline will have two chapters, one called "cap.ts" from 0-240s
|
||||
and a second one called "Show Opening" from 240-330s.
|
||||
|
||||
Entry which defines the track layout
|
||||
====================================
|
||||
|
||||
Normally, you're supposed to put only files with compatible layouts into an EDL
|
||||
file. However, at least the mpv implementation accepts entries that use
|
||||
different codecs, or even have a different number of audio/video/subtitle
|
||||
tracks. In this case, it's not obvious, which virtual tracks the EDL show should
|
||||
expose when being played.
|
||||
|
||||
Currently, mpv will apply an arbitrary heuristic which tracks the EDL file
|
||||
should expose. (Before mpv 0.30.0, it always used the first source file in the
|
||||
segment list.)
|
||||
|
||||
You can set the ``layout`` option to ``this`` to make a specific entry define
|
||||
the track layout.
|
||||
|
||||
Example::
|
||||
|
||||
# mpv EDL v0
|
||||
file_with_2_streams.ts,5,240
|
||||
file_with_5_streams.mkv,0,90,layout=this
|
||||
|
||||
The way the different virtual EDL tracks are associated with the per-segment
|
||||
ones is highly implementation-defined, and uses a heuristic. If a segment is
|
||||
missing a track, there will be a "hole", and bad behavior may result. Improving
|
||||
this is subject to further development (due to being fringe cases, they don't
|
||||
have a high priority).
|
||||
|
||||
If future versions of mpv change this again, this option may be ignored.
|
||||
|
||||
Syntax of EDL URIs
|
||||
==================
|
||||
|
||||
@@ -254,6 +119,3 @@ header, the syntax is exactly the same. It's far more convenient to use ``;``
|
||||
instead of line breaks, but that is orthogonal.
|
||||
|
||||
Example: ``edl://f1.mkv,length=5,start=10;f2.mkv,30,20;f3.mkv``
|
||||
|
||||
As a quirks, mpv will accept arbitrary paths in EDLs originating from
|
||||
``edl://``, while ``.edl`` does not. This makes no sense.
|
||||
+9
-12
@@ -3,7 +3,8 @@ General usage
|
||||
|
||||
::
|
||||
|
||||
mpv infile -o outfile [-of outfileformat] [-ofopts formatoptions] [-orawts] \
|
||||
mpv infile -o outfile [-of outfileformat] [-ofopts formatoptions] \
|
||||
[-ofps outfps | -oautofps] [-oharddup] [-ocopyts | -orawts] [-oneverdrop] \
|
||||
[(any other mpv options)] \
|
||||
-ovc outvideocodec [-ovcopts outvideocodecoptions] \
|
||||
-oac outaudiocodec [-oacopts outaudiocodecoptions]
|
||||
@@ -59,13 +60,13 @@ for.
|
||||
Typical MPEG-4 Part 2 ("ASP", "DivX") encoding, AVI container::
|
||||
|
||||
mpv infile -o outfile.avi \
|
||||
--vf=fps=25 \
|
||||
-ofps 25 \
|
||||
-ovc mpeg4 -ovcopts qscale=4 \
|
||||
-oac libmp3lame -oacopts ab=128k
|
||||
|
||||
Note: AVI does not support variable frame rate, so the fps filter must be used.
|
||||
The frame rate should ideally match the input (25 for PAL, 24000/1001 or
|
||||
30000/1001 for NTSC)
|
||||
Note: AVI does not support variable frame rate, so -ofps must be used. The
|
||||
frame rate should ideally match the input (25 for PAL, 24000/1001 or 30000/1001
|
||||
for NTSC)
|
||||
|
||||
Typical MPEG-4 Part 10 ("AVC", "H.264") encoding, Matroska (MKV) container::
|
||||
|
||||
@@ -94,16 +95,12 @@ As the options for various devices can get complex, profiles can be used.
|
||||
|
||||
An example profile file for encoding is provided in
|
||||
etc/encoding-profiles.conf in the source tree. This file is installed and loaded
|
||||
by default. If you want to modify it, you can replace and it with your own copy
|
||||
by doing::
|
||||
by default (if libavfilter is enabled at compilation). If you want to modify
|
||||
it, you can replace and it with your own copy by doing::
|
||||
|
||||
mkdir -p ~/.mpv
|
||||
cp /etc/mpv/encoding-profiles.conf ~/.mpv/encoding-profiles.conf
|
||||
|
||||
Keep in mind that the default profile is the playback one. If you want to add
|
||||
options that apply only in encoding mode, put them into a ``[encoding]``
|
||||
section.
|
||||
|
||||
Refer to the top of that file for more comments - in a nutshell, the following
|
||||
options are added by it::
|
||||
|
||||
@@ -128,7 +125,7 @@ What works
|
||||
==========
|
||||
|
||||
* Encoding at variable frame rate (default)
|
||||
* Encoding at constant frame rate using --vf=fps=RATE
|
||||
* Encoding at constant frame rate using -ofps framerate -oharddup
|
||||
* 2-pass encoding (specify flags=+pass1 in the first pass's -ovcopts, specify
|
||||
flags=+pass2 in the second pass)
|
||||
* Hardcoding subtitles using vobsub, ass or srt subtitle rendering (just
|
||||
|
||||
@@ -1,654 +0,0 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
mpv provides access to its internals via the following means:
|
||||
|
||||
- options
|
||||
- commands
|
||||
- properties
|
||||
- events
|
||||
- hooks
|
||||
|
||||
The sum of these mechanisms is sometimes called command interface.
|
||||
|
||||
All of these are important for interfacing both with end users and API users
|
||||
(which include Lua scripts, libmpv, and the JSON IPC). As such, they constitute
|
||||
a large part of the user interface and APIs.
|
||||
|
||||
Also see compatibility.rst.
|
||||
|
||||
This document lists changes to them. New changes are added to the top.
|
||||
|
||||
Interface changes
|
||||
=================
|
||||
|
||||
::
|
||||
|
||||
--- mpv 0.30.0 ---
|
||||
- add `--d3d11-output-format` to enable explicit selection of a D3D11
|
||||
swap chain format.
|
||||
- rewrite DVB channel switching to use an integer value
|
||||
`--dvbin-channel-switch-offset` for switching instead of the old
|
||||
stream controls which are now gone. Cycling this property up or down will
|
||||
change the offset to the channel which was initially tuned to.
|
||||
Example for `input.conf`: `H cycle dvbin-channel-switch-offset up`,
|
||||
`K cycle dvbin-channel-switch-offset down`.
|
||||
- adapt `stream_dvb` to support writing to `dvbin-prog` at runtime
|
||||
and also to consistently use dvbin-configuration over URI parameters
|
||||
when provided
|
||||
- add `--d3d11-adapter` to enable explicit selection of a D3D11 rendering
|
||||
adapter by name.
|
||||
- rename `--drm-osd-plane-id` to `--drm-draw-plane`, `--drm-video-plane-id` to
|
||||
`--drm-drmprime-video-plane` and `--drm-osd-size` to `--drm-draw-surface-size`
|
||||
to better reflect what the options actually control, that the values they
|
||||
accept aren't actually internal DRM ID's (like with similar options in
|
||||
ffmpeg's KMS support), and that the video plane is only used when the drmprime
|
||||
overlay hwdec interop is active, with the video being drawn to the draw plane
|
||||
otherwise.
|
||||
- in addition to the above, the `--drm-draw-plane` and `--drm-drmprime-video-plane`
|
||||
options now accept either an integer index, or the values primary or overlay.
|
||||
`--drm-draw-plane` now defaults to primary and `--drm-drmprime-video-plane`
|
||||
defaults to overlay. This should be similar to previous behavior on most drivers
|
||||
due to how planes are usually sorted.
|
||||
- rename --opensles-frames-per-buffer to --opensles-frames-per-enqueue to
|
||||
better reflect its purpose. In the past it overrides the buffer size the AO
|
||||
requests (but not the default/value of the generic --audio-buffer option).
|
||||
Now it only guarantees that the soft buffer size will not be smaller than
|
||||
itself while setting the size per Enqueue.
|
||||
- add --opensles-buffer-size-in-ms, allowing user to tune the soft buffer size.
|
||||
It overrides the --audio-buffer option unless it's set to 0 (with the default
|
||||
being 250).
|
||||
- remove `--linear-scaling`, replaced by `--linear-upscaling` and
|
||||
`--linear-downscaling`. This means that `--sigmoid-upscaling` no longer
|
||||
implies linear light downscaling as well, which was confusing.
|
||||
- the built-in `gpu-hq` profile now includes` --linear-downscaling`.
|
||||
- support for `--spirv-compiler=nvidia` has been removed, leaving `shaderc`
|
||||
as the only option. The `--spirv-compiler` option itself has been marked
|
||||
as deprecated, and may be removed in the future.
|
||||
- split up `--tone-mapping-desaturate`` into strength + exponent, instead of
|
||||
only using a single value (which previously just controlled the exponent).
|
||||
The strength now linearly blends between the linear and nonlinear tone
|
||||
mapped versions of a color.
|
||||
- add --hdr-peak-decay-rate and --hdr-scene-threshold-low/high
|
||||
- add --tone-mapping-max-boost
|
||||
- ipc: require that "request_id" fields are integers. Other types are still
|
||||
accepted for compatibility, but this will stop in the future. Also, if no
|
||||
request_id is provided, 0 will be assumed.
|
||||
- mpv_command_node() and mp.command_native() now support named arguments
|
||||
(see manpage). If you want to use them, use a new version of the manpage
|
||||
as reference, which lists the definitive names.
|
||||
- edition and disc title switching will now fully reload playback (may have
|
||||
consequences for scripts, client API, or when using file-local options)
|
||||
- with the removal of the stream cache, the following properties and options were
|
||||
dropped: `cache`, `cache-size`, `cache-free`, `cache-used`, `--cache-default`,
|
||||
`--cache-initial`, `--cache-seek-min`, `--cache-backbuffer`, `--cache-file`,
|
||||
`--cache-file-size`
|
||||
- the --cache option does not take a number value anymore
|
||||
- remove async playback abort hack. This may make it impossible to abort
|
||||
playback if --demuxer-thread=no is forced.
|
||||
- remove `--macos-title-bar-style`, replaced by `--macos-title-bar-material`
|
||||
and `--macos-title-bar-appearance`.
|
||||
- The default for `--vulkan-async-compute` has changed to `yes` from `no`
|
||||
with the move to libplacebo as the back-end for vulkan rendering.
|
||||
- Remove "disc-titles", "disc-title", "disc-title-list", and "angle"
|
||||
properties. dvd:// does not support title ranges anymore.
|
||||
- Remove all "tv-..." options and properties, along with the classic Linux
|
||||
analog TV support.
|
||||
- remove "program" property (no replacement)
|
||||
- always prefer EGL over GLX, which helps with AMD/vaapi, but will break
|
||||
vdpau with --vo=gpu - use --gpu-context=x11 to be able to use vdpau. This
|
||||
does not affect --vo=vdpau or --hwdec=vdpau-copy.
|
||||
- remove deprecated --chapter option
|
||||
- deprecate --record-file
|
||||
- add `--demuxer-cue-codepage`
|
||||
- add ``track-list/N/demux-bitrate``, ``track-list/N/demux-rotation`` and
|
||||
``track-list/N/demux-par`` property
|
||||
- Deprecate ``--video-aspect`` and add ``--video-aspect-override`` to
|
||||
replace it. (The `video-aspect` option remains unchanged.)
|
||||
--- mpv 0.29.0 ---
|
||||
- drop --opensles-sample-rate, as --audio-samplerate should be used if desired
|
||||
- drop deprecated --videotoolbox-format, --ff-aid, --ff-vid, --ff-sid,
|
||||
--ad-spdif-dtshd, --softvol options
|
||||
- fix --external-files: strictly never select any tracks from them, unless
|
||||
explicitly selected (this may or may not be expected)
|
||||
- --ytdl is now always enabled, even for libmpv
|
||||
- add a number of --audio-resample-* options, which should from now on be
|
||||
used instead of --af-defaults=lavrresample:...
|
||||
- deprecate --vf-defaults and --af-defaults. These didn't work with the
|
||||
lavfi bridge, so they have very little use left. The only potential use
|
||||
is with af_lavrresample (going to be deprecated, --audio-resample-... set
|
||||
its defaults), and various hw deinterlacing filters (like vf_vavpp), for
|
||||
which you will have to stop using --deinterlace=yes, and instead use the
|
||||
vf toggle commands and the filter enable/disable flag to customize it.
|
||||
- deprecate --af=lavrresample. Use the ``--audio-resample-...`` options to
|
||||
customize resampling, or the libavfilter ``--af=aresample`` filter.
|
||||
- add --osd-on-seek
|
||||
- remove outfmt sub-parameter from "format" video filter (no replacement)
|
||||
- some behavior changes in the video filter chain, including:
|
||||
- before, using an incompatible filter with hwdec would disable hwdec;
|
||||
now it disables the filter at runtime instead
|
||||
- inserting an incompatible filter with hwdec at runtime would refuse
|
||||
to insert the filter; now it will add it successfully, but disables
|
||||
the filter slightly later
|
||||
- some behavior changes in the audio filter chain, including:
|
||||
- a manually inserted lavrresample filter is not necessarily used for
|
||||
sample format conversion anymore, so it's pretty useless
|
||||
- changing playback speed will not respect --af-defaults anymore
|
||||
- having libavfilter based filters after the scaletempo or rubberband
|
||||
filters is not supported anymore, and may desync if playback speed is
|
||||
changed (libavfilter does not support the metadata for playback speed)
|
||||
- the lavcac3enc filter does not auto detach itself anymore; instead it
|
||||
passes through the data after converting it to the sample rate and
|
||||
channel configuration the ac3 encoder expects; also, if the audio
|
||||
format changes midstream in a way that causes the filter to switch
|
||||
between PCM and AC3 output, the audio output won't be reconfigured,
|
||||
and audio playback will fail due to libswresample being unable to
|
||||
convert between PCM and AC3 (Note: the responsible developer didn't
|
||||
give a shit. Later changes might have improved or worsened this.)
|
||||
- inserting a filter that changes the output sample format will not
|
||||
reconfigure the AO - you need to run an additional "ao-reload"
|
||||
command to force this if you want that
|
||||
- using "strong" gapless audio (--gapless-audio=yes) can fail if the
|
||||
audio formats are not convertible (such as switching between PCM and
|
||||
AC3 passthrough)
|
||||
- if filters do not pass through PTS values correctly, A/V sync can
|
||||
result over time. Some libavfilter filters are known to be affected by
|
||||
this, such as af_loudnorm, which can desync over time, depending on
|
||||
how the audio track was muxed (af_lavfi's fix-pts suboption can help).
|
||||
- remove out-format sub-parameter from "format" audio filter (no replacement)
|
||||
- --lavfi-complex now requires uniquely named filter pads. In addition,
|
||||
unconnected filter pads are not allowed anymore (that means every filter
|
||||
pad must be connected either to another filter, or to a video/audio track
|
||||
or video/audio output). If they are disconnected at runtime, the stream
|
||||
will probably stall.
|
||||
- rename --vo=opengl-cb to --vo=libmpv (goes in hand with the opengl-cb
|
||||
API deprecation, see client-api-changes.rst)
|
||||
- deprecate the OpenGL cocoa backend, option choice --gpu-context=cocoa
|
||||
when used with --gpu-api=opengl (use --vo=libmpv)
|
||||
- make --deinterlace=yes always deinterlace, instead of trying to check
|
||||
certain unreliable video metadata. Also flip the defaults of all builtin
|
||||
HW deinterlace filters to always deinterlace.
|
||||
- change vf_vavpp default to use the best deinterlace algorithm by default
|
||||
- remove a compatibility hack that allowed CLI aliases to be set as property
|
||||
(such as "sub-file"), deprecated in mpv 0.26.0
|
||||
- deprecate the old command based hook API, and introduce a proper C API
|
||||
(the high level Lua API for this does not change)
|
||||
- rename the the lua-settings/ config directory to script-opts/
|
||||
- the way the player waits for scripts getting loaded changes slightly. Now
|
||||
scripts are loaded in parallel, and block the player from continuing
|
||||
playback only in the player initialization phase. It could change again in
|
||||
the future. (This kind of waiting was always a feature to prevent that
|
||||
playback is started while scripts are only half-loaded.)
|
||||
- deprecate --ovoffset, --oaoffset, --ovfirst, --oafirst
|
||||
- remove the following encoding options: --ocopyts (now the default, old
|
||||
timestamp handling is gone), --oneverdrop (now default), --oharddup (you
|
||||
need to use --vf=fps=VALUE), --ofps, --oautofps, --omaxfps
|
||||
- remove --video-stereo-mode. This option was broken out of laziness, and
|
||||
nobody wants to fix it. Automatic 3D down-conversion to 2D is also broken,
|
||||
although you can just insert the stereo3d filter manually. The obscurity
|
||||
of 3D content doesn't justify such an option anyway.
|
||||
- change cycle-values command to use the current value, instead of an
|
||||
internal counter that remembered the current position.
|
||||
- remove deprecated ao/vo auto profiles. Consider using scripts like
|
||||
auto-profiles.lua instead.
|
||||
- --[c]scale-[w]param[1|2] and --tone-mapping-param now accept "default",
|
||||
and if set to that value, reading them as property will also return
|
||||
"default", instead of float nan as in previous versions
|
||||
--- mpv 0.28.0 ---
|
||||
- rename --hwdec=mediacodec option to mediacodec-copy, to reflect
|
||||
conventions followed by other hardware video decoding APIs
|
||||
- drop previously deprecated --heartbeat-cmd and --heartbeat--interval
|
||||
options
|
||||
- rename --vo=opengl to --vo=gpu
|
||||
- rename --opengl-backend to --gpu-context
|
||||
- rename --opengl-shaders to --glsl-shaders
|
||||
- rename --opengl-shader-cache-dir to --gpu-shader-cache-dir
|
||||
- rename --opengl-tex-pad-x/y to --gpu-tex-pad-x/y
|
||||
- rename --opengl-fbo-format to --fbo-format
|
||||
- rename --opengl-gamma to --gamma-factor
|
||||
- rename --opengl-debug to --gpu-debug
|
||||
- rename --opengl-sw to --gpu-sw
|
||||
- rename --opengl-vsync-fences to --swapchain-depth, and the interpretation
|
||||
slightly changed. Now defaults to 3.
|
||||
- rename the built-in profile `opengl-hq` to `gpu-hq`
|
||||
- the semantics of --opengl-es=yes are slightly changed -> now requires GLES
|
||||
- remove the (deprecated) alias --gpu-context=drm-egl
|
||||
- remove the (deprecated) --vo=opengl-hq
|
||||
- remove --opengl-es=force2 (use --opengl-es=yes --opengl-restrict=300)
|
||||
- the --msg-level option now affects --log-file
|
||||
- drop "audio-out-detected-device" property - this was unavailable on all
|
||||
audio output drivers for quite a while (coreaudio used to provide it)
|
||||
- deprecate --videotoolbox-format (use --hwdec-image-format, which affects
|
||||
most other hwaccels)
|
||||
- remove deprecated --demuxer-max-packets
|
||||
- remove most of the deprecated audio and video filters
|
||||
- remove the deprecated --balance option/property
|
||||
- rename the --opengl-hwdec-interop option to --gpu-hwdec-interop, and
|
||||
change some of its semantics: extend it take the strings "auto" and
|
||||
"all". "all" loads all backends. "auto" behaves like "all" for
|
||||
vo_opengl_cb, while on vo_gpu it loads nothing, but allows on demand
|
||||
loading by the decoder. The empty string as option value behaves like
|
||||
"auto". Old --hwdec values do not work anymore.
|
||||
This option is hereby declared as unstable and may change any time - its
|
||||
old use is deprecated, and it has very little use outside of debugging
|
||||
now.
|
||||
- change the --hwdec option from a choice to a plain string (affects
|
||||
introspection of the option/property), also affects some properties
|
||||
- rename --hwdec=rpi to --hwdec=mmal, same for the -copy variant (no
|
||||
backwards compatibility)
|
||||
- deprecate the --ff-aid, --ff-vid, --ff-sid options and properties (there is
|
||||
no replacement, but you can manually query the track property and use the
|
||||
"ff-index" field to find the mpv track ID to imitate this behavior)
|
||||
- rename --no-ometadata to --no-ocopy-metadata
|
||||
--- mpv 0.27.0 ---
|
||||
- drop previously deprecated --field-dominance option
|
||||
- drop previously deprecated "osd" command
|
||||
- remove client API compatibility handling for "script", "sub-file",
|
||||
"audio-file", "external-file" (these cases used to log a deprecation
|
||||
warning)
|
||||
- drop deprecated --video-aspect-method=hybrid option choice
|
||||
- rename --hdr-tone-mapping to --tone-mapping (and generalize it)
|
||||
- --opengl-fbo-format changes from a choice to a string. Also, its value
|
||||
will be checked only on renderer initialization, rather than when the
|
||||
option is set.
|
||||
- Using opengl-cb now always assumes 8 bit per component depth, and dithers
|
||||
to this size. Before, it tried to figure out the depth of the first
|
||||
framebuffer that was ever passed to the renderer. Having GL framebuffers
|
||||
with a size larger than 8 bit per component is quite rare. If you need
|
||||
it, set the --dither-depth option instead.
|
||||
- --lavfi-complex can now be set during runtime. If you set this in
|
||||
expectation it would be applied only after a reload, you might observe
|
||||
weird behavior.
|
||||
- add --track-auto-selection to help with scripts/applications that
|
||||
make exclusive use of --lavfi-complex.
|
||||
- undeprecate --loop, and map it from --loop-playlist to --loop-file (the
|
||||
deprecation was to make sure no API user gets broken by a sudden behavior
|
||||
change)
|
||||
- remove previously deprecated vf_eq
|
||||
- remove that hardware deinterlace filters (vavpp, d3d11vpp, vdpaupp)
|
||||
changed their deinterlacing-enabled setting depending on what the
|
||||
--deinterlace option or property was set to. Now, a filter always does
|
||||
what its filter options and defaults imply. The --deinterlace option and
|
||||
property strictly add/remove its own filters. For example, if you run
|
||||
"mpv --vf=vavpp --deinterlace=yes", this will insert another, redundant
|
||||
filter, which is probably not what you want. For toggling a deinterlace
|
||||
filter manually, use the "vf toggle" command, and do not set the
|
||||
deinterlace option/property. To customize the filter that will be
|
||||
inserted automatically, use --vf-defaults. Details how this works will
|
||||
probably change in the future.
|
||||
- remove deinterlace=auto (this was not deprecated, but had only a very
|
||||
obscure use that stopped working with the change above. It was also
|
||||
prone to be confused with a feature not implemented by it: auto did _not_
|
||||
mean that deinterlacing was enabled on demand.)
|
||||
- add shortened mnemonic names for mouse button bindings, eg. mbtn_left
|
||||
the old numeric names (mouse_btn0) are deprecated
|
||||
- remove mouse_btn3_dbl and up, since they are only generated for buttons
|
||||
0-2 (these now print an error when sent from the 'mouse' command)
|
||||
- rename the axis bindings to wheel_up/down/etc. axis scrolling and mouse
|
||||
wheel scrolling are now conceptually the same thing
|
||||
the old axis_up/down names remain as deprecated aliases
|
||||
--- mpv 0.26.0 ---
|
||||
- remove remaining deprecated audio device options, like --alsa-device
|
||||
Some of them were removed in earlier releases.
|
||||
- introduce --replaygain... options, which replace the same functionality
|
||||
provided by the deprecated --af=volume:replaygain... mechanism.
|
||||
- drop the internal "mp-rawvideo" codec (used by --demuxer=rawvideo)
|
||||
- rename --sub-ass-style-override to --sub-ass-override, and rename the
|
||||
`--sub-ass-override=signfs` setting to `--sub-ass-override=scale`.
|
||||
- change default of --video-aspect-method to "bitstream". The "hybrid"
|
||||
method (old default) is deprecated.
|
||||
- remove property "video-params/nom-peak"
|
||||
- remove option --target-brightness
|
||||
- replace vf_format's `peak` suboption by `sig-peak`, which is relative to
|
||||
the reference white level instead of in cd/m^2
|
||||
- renamed the TRCs `st2084` and `std-b67` to `pq` and `hlg` respectively
|
||||
- the "osd" command is deprecated (use "cycle osd-level")
|
||||
- --field-dominance is deprecated (use --vf=setfield=bff or tff)
|
||||
- --really-quiet subtle behavior change
|
||||
- the deprecated handling of setting "no-" options via client API is dropped
|
||||
- the following options change to append-by-default (and possibly separator):
|
||||
--script
|
||||
also, the following options are deprecated:
|
||||
--sub-paths => --sub-file-paths
|
||||
the following options are deprecated for setting via API:
|
||||
"script" (use "scripts")
|
||||
"sub-file" (use "sub-files")
|
||||
"audio-file" (use "audio-files")
|
||||
"external-file" (use "external-files")
|
||||
(the compatibility hacks for this will be removed after this release)
|
||||
- remove property `vo-performance`, and add `vo-passes` as a more general
|
||||
replacement
|
||||
- deprecate passing multiple arguments to -add/-pre options (affects the
|
||||
vf/af commands too)
|
||||
- remove --demuxer-lavf-cryptokey. Use --demux-lavf-o=cryptokey=<hex> or
|
||||
--demux-lavf-o=decryption_key=<hex> instead (whatever fits your situation).
|
||||
- rename --opengl-dumb-mode=no to --opengl-dumb-mode=auto, and make `no`
|
||||
always disable it (unless forced on by hardware limitation).
|
||||
- generalize --scale-clamp, --cscale-clamp etc. to accept a float between
|
||||
0.0 and 1.0 instead of just being a flag. A value of 1.0 corresponds to
|
||||
the old `yes`, and a value of 0.0 corresponds to the old `no`.
|
||||
--- mpv 0.25.0 ---
|
||||
- remove opengl-cb dxva2 dummy hwdec interop
|
||||
(see git "vo_opengl: remove dxva2 dummy hwdec backend")
|
||||
- remove ppm, pgm, pgmyuv, tga choices from the --screenshot-format and
|
||||
--vo-image-format options
|
||||
- the "jpeg" choice in the option above now leads to a ".jpg" file extension
|
||||
- --af=drc is gone (you can use e.g. lavfi/acompressor instead)
|
||||
- remove image_size predefined uniform from OpenGL user shaders. Use
|
||||
input_size instead
|
||||
- add --sub-filter-sdh
|
||||
- add --sub-filter-sdh-harder
|
||||
- remove --input-app-events option (macOS)
|
||||
- deprecate most --vf and --af filters. Only some filters not in libavfilter
|
||||
will be kept.
|
||||
Also, you can use libavfilter filters directly (e.g. you can use
|
||||
--vf=name=opts instead of --vf=lavfi=[name=opts]), as long as the
|
||||
libavfilter filter's name doesn't clash with a mpv builtin filter.
|
||||
In the long term, --vf/--af syntax might change again, but if it does, it
|
||||
will switch to libavfilter's native syntax. (The above mentioned direct
|
||||
support for lavfi filters still has some differences, such as how strings
|
||||
are escaped.) If this happens, the non-deprecated builtin filters might be
|
||||
moved to "somewhere else" syntax-wise.
|
||||
- deprecate --loop - after a deprecation period, it will be undeprecated,
|
||||
but changed to alias --loop-file
|
||||
- add --keep-open-pause=no
|
||||
- deprecate --demuxer-max-packets
|
||||
- change --audio-file-auto default from "exact" to "no" (mpv won't load
|
||||
files with the same filename as the video, but different extension, as
|
||||
audio track anymore)
|
||||
--- mpv 0.24.0 ---
|
||||
- deprecate --hwdec-api and replace it with --opengl-hwdec-interop.
|
||||
The new option accepts both --hwdec values, as well as named backends.
|
||||
A minor difference is that --hwdec-api=no (which used to be the default)
|
||||
now actually does not preload any interop layer, while the new default
|
||||
("") uses the value of --hwdec.
|
||||
- drop deprecated --ad/--vd features
|
||||
- drop deprecated --sub-codepage syntax
|
||||
- rename properties:
|
||||
- "drop-frame-count" to "decoder-frame-drop-count"
|
||||
- "vo-drop-frame-count" to "frame-drop-count"
|
||||
The old names still work, but are deprecated.
|
||||
- remove the --stream-capture option and property. No replacement.
|
||||
(--record-file might serve as alternative)
|
||||
- add --sub-justify
|
||||
- add --sub-ass-justify
|
||||
- internally there's a different way to enable the demuxer cache now
|
||||
it can be auto-enabled even if the stream cache remains disabled
|
||||
--- mpv 0.23.0 ---
|
||||
- remove deprecated vf_vdpaurb (use "--hwdec=vdpau-copy" instead)
|
||||
- the following properties now have new semantics:
|
||||
- "demuxer" (use "current-demuxer")
|
||||
- "fps" (use "container-fps")
|
||||
- "idle" (use "idle-active")
|
||||
- "cache" (use "cache-percent")
|
||||
- "audio-samplerate" (use "audio-params/samplerate")
|
||||
- "audio-channels" (use "audio-params/channel-count")
|
||||
- "audio-format" (use "audio-codec-name")
|
||||
(the properties equivalent to the old semantics are in parentheses)
|
||||
- remove deprecated --vo and --ao sub-options (like --vo=opengl:...), and
|
||||
replace them with global options. A somewhat complete list can be found
|
||||
here: https://github.com/mpv-player/mpv/wiki/Option-replacement-list#mpv-0210
|
||||
- remove --vo-defaults and --ao-defaults as well
|
||||
- remove deprecated global sub-options (like -demuxer-rawaudio format=...),
|
||||
use flat options (like --demuxer-rawaudio-format=...)
|
||||
- the --sub-codepage option changes in incompatible ways:
|
||||
- detector-selection and fallback syntax is deprecated
|
||||
- enca/libguess are removed and deprecated (behaves as if they hadn't
|
||||
been compiled-in)
|
||||
- --sub-codepage=<codepage> does not force the codepage anymore
|
||||
(this requires different and new syntax)
|
||||
- remove --fs-black-out-screens option for macOS
|
||||
- change how spdif codecs are selected. You can't enable spdif passthrough
|
||||
with --ad anymore. This was deprecated; use --audio-spdif instead.
|
||||
- deprecate the "family" selection with --ad/--vd
|
||||
forcing/excluding codecs with "+", "-", "-" is deprecated as well
|
||||
- explicitly mark --ad-spdif-dtshd as deprecated (it was done so a long time
|
||||
ago, but it didn't complain when using the option)
|
||||
--- mpv 0.22.0 ---
|
||||
- the "audio-device-list" property now sets empty device description to the
|
||||
device name as a fallback
|
||||
- add --hidpi-window-scale option for macOS
|
||||
- add audiounit audio output for iOS
|
||||
- make --start-time work with --rebase-start-time=no
|
||||
- add --opengl-early-flush=auto mode
|
||||
- add --hwdec=vdpau-copy, deprecate vf_vdpaurb
|
||||
- add tct video output for true-color and 256-color terminals
|
||||
--- mpv 0.21.0 ---
|
||||
- unlike in older versions, setting options at runtime will now take effect
|
||||
immediately (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.23.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.23.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.23.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.23.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.23.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 ---
|
||||
- deprecate --heartbeat-cmd
|
||||
- remove --softvol=no capability:
|
||||
- deprecate --softvol, it now does nothing
|
||||
- --volume, --mute, and the corresponding properties now always control
|
||||
softvol, and behave as expected without surprises (e.g. you can set
|
||||
them normally while no audio is initialized)
|
||||
- rename --softvol-max to --volume-max (deprecated alias is added)
|
||||
- the --volume-restore-data option and property are removed without
|
||||
replacement. They were _always_ internal, and used for watch-later
|
||||
resume/restore. Now --volume/--mute are saved directly instead.
|
||||
- the previous point means resuming files with older watch-later configs
|
||||
will print an error about missing --volume-restore-data (which you can
|
||||
ignore), and will not restore the previous value
|
||||
- as a consequence, volume controls will no longer control PulseAudio
|
||||
per-application value, or use the system mixer's per-application
|
||||
volume processing
|
||||
- system or per-application volume can still be controlled with the
|
||||
ao-volume and ao-mute properties (there are no command line options)
|
||||
--- mpv 0.18.0 ---
|
||||
- now ab-loops are active even if one of the "ab-loop-a"/"-b" properties is
|
||||
unset ("no"), in which case the start of the file is used if the A loop
|
||||
point is unset, and the end of the file for an unset B loop point
|
||||
- deprecate --sub-ass=no option by --ass-style-override=strip
|
||||
(also needs --embeddedfonts=no)
|
||||
- add "hwdec-interop" and "hwdec-current" properties
|
||||
- deprecated "hwdec-active" and "hwdec-detected" properties (to be removed
|
||||
in mpv 0.20.0)
|
||||
- choice option/property values that are "yes" or "no" will now be returned
|
||||
as booleans when using the mpv_node functions in the client API, the
|
||||
"native" property accessors in Lua, and the JSON API. They can be set as
|
||||
such as well.
|
||||
- the VO opengl fbo-format sub-option does not accept "rgb" or "rgba"
|
||||
anymore
|
||||
- all VO opengl prescalers have been removed (replaced by user scripts)
|
||||
--- mpv 0.17.0 ---
|
||||
- deprecate "track-list/N/audio-channels" property (use
|
||||
"track-list/N/demux-channel-count" instead)
|
||||
- remove write access to "stream-pos", and change semantics for read access
|
||||
- Lua scripts now don't suspend mpv by default while script code is run
|
||||
- add "cache-speed" property
|
||||
- rename --input-unix-socket to --input-ipc-server, and make it work on
|
||||
Windows too
|
||||
- change the exact behavior of the "video-zoom" property
|
||||
- --video-unscaled no longer disables --video-zoom and --video-aspect
|
||||
To force the old behavior, set --video-zoom=0 and --video-aspect=0
|
||||
--- mpv 0.16.0 ---
|
||||
- change --audio-channels default to stereo (use --audio-channels=auto to
|
||||
get the old default)
|
||||
- add --audio-normalize-downmix
|
||||
- change the default downmix behavior (--audio-normalize-downmix=yes to get
|
||||
the old default)
|
||||
- VO opengl custom shaders must now use "sample_pixel" as function name,
|
||||
instead of "sample"
|
||||
- change VO opengl scaler-resizes-only default to enabled
|
||||
- add VO opengl "interpolation-threshold" suboption (introduces new default
|
||||
behavior, which can change e.g. ``--video-sync=display-vdrop`` to the
|
||||
worse, but is usually what you want)
|
||||
- make "volume" and "mute" properties changeable even if no audio output is
|
||||
active (this gives not-ideal behavior if --softvol=no is used)
|
||||
- add "volume-max" and "mixer-active" properties
|
||||
- ignore --input-cursor option for events injected by input commands like
|
||||
"mouse", "keydown", etc.
|
||||
--- mpv 0.15.0 ---
|
||||
- change "yadif" video filter defaults
|
||||
--- mpv 0.14.0 ---
|
||||
- vo_opengl interpolation now requires --video-sync=display-... to be set
|
||||
- change some vo_opengl defaults (including changing tscale)
|
||||
- add "vsync-ratio", "estimated-display-fps" properties
|
||||
- add --rebase-start-time option
|
||||
This is a breaking change to start time handling. Instead of making start
|
||||
time handling an aspect of different options and properties (like
|
||||
"time-pos" vs. "playback-time"), make it dependent on the new option. For
|
||||
compatibility, the "time-start" property now always returns 0, so code
|
||||
which attempted to handle rebasing manually will not break.
|
||||
--- mpv 0.13.0 ---
|
||||
- remove VO opengl-cb frame queue suboptions (no replacement)
|
||||
--- mpv 0.12.0 ---
|
||||
- remove --use-text-osd (useless; fontconfig isn't a requirement anymore,
|
||||
and text rendering is also lazily initialized)
|
||||
- some time properties (at least "playback-time", "time-pos",
|
||||
"time-remaining", "playtime-remaining") now are unavailable if the time
|
||||
is unknown, instead of just assuming that the internal playback position
|
||||
is 0
|
||||
- add --audio-fallback-to-null option
|
||||
- replace vf_format outputlevels suboption with "video-output-levels" global
|
||||
property/option; also remove "colormatrix-output-range" property
|
||||
- vo_opengl: remove sharpen3/sharpen5 scale filters, add sharpen sub-option
|
||||
--- mpv 0.11.0 ---
|
||||
- add "af-metadata" property
|
||||
--- mpv 0.10.0 ---
|
||||
- add --video-aspect-method option
|
||||
- add --playlist-pos option
|
||||
- add --video-sync* options
|
||||
"display-sync-active" property
|
||||
"vo-missed-frame-count" property
|
||||
"audio-speed-correction" and "video-speed-correction" properties
|
||||
- remove --demuxer-readahead-packets and --demuxer-readahead-bytes
|
||||
add --demuxer-max-packets and --demuxer-max-bytes
|
||||
(the new options are not replacement and have very different semantics)
|
||||
- change "video-aspect" property: always settable, even if no video is
|
||||
running; always return the override - if no override is set, return
|
||||
the video's aspect ratio
|
||||
- remove disc-nav (DVD, BD) related properties and commands
|
||||
- add "option-info/<name>/set-locally" property
|
||||
- add --cache-backbuffer; change --cache-default default to 75MB
|
||||
the new total cache size is the sum of backbuffer and the cache size
|
||||
specified by --cache-default or --cache
|
||||
- add ``track-list/N/audio-channels`` property
|
||||
- change --screenshot-tag-colorspace default value
|
||||
- add --stretch-image-subs-to-screen
|
||||
- add "playlist/N/title" property
|
||||
- add --video-stereo-mode=no to disable auto-conversions
|
||||
- add --force-seekable, and change default seekability in some cases
|
||||
- add vf yadif/vavpp/vdpaupp interlaced-only suboptions
|
||||
Also, the option is enabled by default (Except vf_yadif, which has
|
||||
it enabled only if it's inserted by the deinterlace property.)
|
||||
- add --hwdec-preload
|
||||
- add ao coreaudio exclusive suboption
|
||||
- add ``track-list/N/forced`` property
|
||||
- add audio-params/channel-count and ``audio-params-out/channel-count props.
|
||||
- add af volume replaygain-fallback suboption
|
||||
- add video-params/stereo-in property
|
||||
- add "keypress", "keydown", and "keyup" commands
|
||||
- deprecate --ad-spdif-dtshd and enabling passthrough via --ad
|
||||
add --audio-spdif as replacement
|
||||
- remove "get_property" command
|
||||
- remove --slave-broken
|
||||
- add vo opengl custom shader suboptions (source-shader, scale-shader,
|
||||
pre-shaders, post-shaders)
|
||||
- completely change how the hwdec properties work:
|
||||
- "hwdec" now reflects the --hwdec option
|
||||
- "hwdec-detected" does partially what the old "hwdec" property did
|
||||
(and also, "detected-hwdec" is removed)
|
||||
- "hwdec-active" is added
|
||||
- add protocol-list property
|
||||
- deprecate audio-samplerate and audio-channels properties
|
||||
(audio-params sub-properties are the replacement)
|
||||
- add audio-params and audio-out-params properties
|
||||
- deprecate "audio-format" property, replaced with "audio-codec-name"
|
||||
- deprecate --media-title, replaced with --force-media-title
|
||||
- deprecate "length" property, replaced with "duration"
|
||||
- change volume property:
|
||||
- the value 100 is now always "unchanged volume" - with softvol, the
|
||||
range is 0 to --softvol-max, without it is 0-100
|
||||
- the minimum value of --softvol-max is raised to 100
|
||||
- remove vo opengl npot suboption
|
||||
- add relative seeking by percentage to "seek" command
|
||||
- add playlist_shuffle command
|
||||
- add --force-window=immediate
|
||||
- add ao coreaudio change-physical-format suboption
|
||||
- remove vo opengl icc-cache suboption, add icc-cache-dir suboption
|
||||
- add --screenshot-directory
|
||||
- add --screenshot-high-bit-depth
|
||||
- add --screenshot-jpeg-source-chroma
|
||||
- default action for "rescan_external_files" command changes
|
||||
--- mpv 0.9.0 ---
|
||||
+472
-76
@@ -4,27 +4,66 @@ AUDIO FILTERS
|
||||
Audio filters allow you to modify the audio stream and its properties. The
|
||||
syntax is:
|
||||
|
||||
``--af=...``
|
||||
Setup a chain of audio filters. See ``--vf`` (`VIDEO FILTERS`_) for the
|
||||
full syntax.
|
||||
``--af=<filter1[=parameter1:parameter2:...],filter2,...>``
|
||||
Setup a chain of audio filters.
|
||||
|
||||
.. note::
|
||||
|
||||
To get a full list of available audio filters, see ``--af=help``.
|
||||
|
||||
Also, keep in mind that most actual filters are available via the ``lavfi``
|
||||
wrapper, which gives you access to most of libavfilter's filters. This
|
||||
includes all filters that have been ported from MPlayer to libavfilter.
|
||||
You can also set defaults for each filter. The defaults are applied before the
|
||||
normal filter parameters.
|
||||
|
||||
The ``--vf`` description describes how libavfilter can be used and how to
|
||||
workaround deprecated mpv filters.
|
||||
``--af-defaults=<filter1[=parameter1:parameter2:...],filter2,...>``
|
||||
Set defaults for each filter.
|
||||
|
||||
See ``--vf`` group of options for info on how ``--af-defaults``, ``--af-add``,
|
||||
``--af-pre``, ``--af-del``, ``--af-clr``, and possibly others work.
|
||||
Audio filters are managed in lists. There are a few commands to manage the
|
||||
filter list:
|
||||
|
||||
``--af-add=<filter1[,filter2,...]>``
|
||||
Appends the filters given as arguments to the filter list.
|
||||
|
||||
``--af-pre=<filter1[,filter2,...]>``
|
||||
Prepends the filters given as arguments to the filter list.
|
||||
|
||||
``--af-del=<index1[,index2,...]>``
|
||||
Deletes the filters at the given indexes. Index numbers start at 0,
|
||||
negative numbers address the end of the list (-1 is the last).
|
||||
|
||||
``--af-clr``
|
||||
Completely empties the filter list.
|
||||
|
||||
Available filters are:
|
||||
|
||||
``lavcac3enc[=options]``
|
||||
``lavrresample[=option1:option2:...]``
|
||||
This filter uses libavresample (or libswresample, depending on the build)
|
||||
to change sample rate, sample format, or channel layout of the audio stream.
|
||||
This filter is automatically enabled if the audio output does not support
|
||||
the audio configuration of the file being played.
|
||||
|
||||
It supports only the following sample formats: u8, s16, s32, float.
|
||||
|
||||
``filter-size=<length>``
|
||||
Length of the filter with respect to the lower sampling rate. (default:
|
||||
16)
|
||||
``phase-shift=<count>``
|
||||
Log2 of the number of polyphase entries. (..., 10->1024, 11->2048,
|
||||
12->4096, ...) (default: 10->1024)
|
||||
``cutoff=<cutoff>``
|
||||
Cutoff frequency (0.0-1.0), default set depending upon filter length.
|
||||
``linear``
|
||||
If set then filters will be linearly interpolated between polyphase
|
||||
entries. (default: no)
|
||||
``no-detach``
|
||||
Do not detach if input and output audio format/rate/channels match.
|
||||
(If you just want to set defaults for this filter that will be used
|
||||
even by automatically inserted lavrresample instances, you should
|
||||
prefer setting them with ``--af-defaults=lavrresample:...``.)
|
||||
``o=<string>``
|
||||
Set AVOptions on the SwrContext or AVAudioResampleContext. These should
|
||||
be documented by FFmpeg or Libav.
|
||||
|
||||
``lavcac3enc[=tospdif[:bitrate[:minchn]]]``
|
||||
Encode multi-channel audio to AC-3 at runtime using libavcodec. Supports
|
||||
16-bit native-endian input format, maximum 6 channels. The output is
|
||||
big-endian when outputting a raw AC-3 stream, native-endian when
|
||||
@@ -53,30 +92,147 @@ Available filters are:
|
||||
:5ch: 448
|
||||
:6ch: 448
|
||||
|
||||
``minch=<n>``
|
||||
If the input channel number is less than ``<minch>``, the filter will
|
||||
``minchn=<n>``
|
||||
If the input channel number is less than ``<minchn>``, the filter will
|
||||
detach itself (default: 3).
|
||||
|
||||
``encoder=<name>``
|
||||
Select the libavcodec encoder used. Currently, this should be an AC-3
|
||||
encoder, and using another codec will fail horribly.
|
||||
``sweep[=speed]``
|
||||
Produces a sine sweep.
|
||||
|
||||
``format=format:srate:channels:out-srate:out-channels``
|
||||
Does not do any format conversion itself. Rather, it may cause the
|
||||
filter system to insert necessary conversion filters before or after this
|
||||
filter if needed. It is primarily useful for controlling the audio format
|
||||
going into other filters. To specify the format for audio output, see
|
||||
``--audio-format``, ``--audio-samplerate``, and ``--audio-channels``. This
|
||||
filter is able to force a particular format, whereas ``--audio-*``
|
||||
may be overridden by the ao based on output compatibility.
|
||||
``<0.0-1.0>``
|
||||
Sine function delta, use very low values to hear the sweep.
|
||||
|
||||
``sinesuppress[=freq:decay]``
|
||||
Remove a sine at the specified frequency. Useful to get rid of the 50/60 Hz
|
||||
noise on low quality audio equipment. It only works on mono input.
|
||||
|
||||
``<freq>``
|
||||
The frequency of the sine which should be removed (in Hz) (default:
|
||||
50)
|
||||
``<decay>``
|
||||
Controls the adaptivity (a larger value will make the filter adapt to
|
||||
amplitude and phase changes quicker, a smaller value will make the
|
||||
adaptation slower) (default: 0.0001). Reasonable values are around
|
||||
0.001.
|
||||
|
||||
``bs2b[=option1:option2:...]``
|
||||
Bauer stereophonic to binaural transformation using libbs2b. Improves the
|
||||
headphone listening experience by making the sound similar to that from
|
||||
loudspeakers, allowing each ear to hear both channels and taking into
|
||||
account the distance difference and the head shadowing effect. It is
|
||||
applicable only to 2-channel audio.
|
||||
|
||||
``fcut=<300-1000>``
|
||||
Set cut frequency in Hz.
|
||||
``feed=<10-150>``
|
||||
Set feed level for low frequencies in 0.1*dB.
|
||||
``profile=<value>``
|
||||
Several profiles are available for convenience:
|
||||
|
||||
:default: will be used if nothing else was specified (fcut=700,
|
||||
feed=45)
|
||||
:cmoy: Chu Moy circuit implementation (fcut=700, feed=60)
|
||||
:jmeier: Jan Meier circuit implementation (fcut=650, feed=95)
|
||||
|
||||
If ``fcut`` or ``feed`` options are specified together with a profile, they
|
||||
will be applied on top of the selected profile.
|
||||
|
||||
``hrtf[=flag]``
|
||||
Head-related transfer function: Converts multichannel audio to 2-channel
|
||||
output for headphones, preserving the spatiality of the sound.
|
||||
|
||||
==== ===================================
|
||||
Flag Meaning
|
||||
==== ===================================
|
||||
m matrix decoding of the rear channel
|
||||
s 2-channel matrix decoding
|
||||
0 no matrix decoding (default)
|
||||
==== ===================================
|
||||
|
||||
``equalizer=g1:g2:g3:...:g10``
|
||||
10 octave band graphic equalizer, implemented using 10 IIR band-pass
|
||||
filters. This means that it works regardless of what type of audio is
|
||||
being played back. The center frequencies for the 10 bands are:
|
||||
|
||||
=== ==========
|
||||
No. frequency
|
||||
=== ==========
|
||||
0 31.25 Hz
|
||||
1 62.50 Hz
|
||||
2 125.00 Hz
|
||||
3 250.00 Hz
|
||||
4 500.00 Hz
|
||||
5 1.00 kHz
|
||||
6 2.00 kHz
|
||||
7 4.00 kHz
|
||||
8 8.00 kHz
|
||||
9 16.00 kHz
|
||||
=== ==========
|
||||
|
||||
If the sample rate of the sound being played is lower than the center
|
||||
frequency for a frequency band, then that band will be disabled. A known
|
||||
bug with this filter is that the characteristics for the uppermost band
|
||||
are not completely symmetric if the sample rate is close to the center
|
||||
frequency of that band. This problem can be worked around by upsampling
|
||||
the sound using a resampling filter before it reaches this filter.
|
||||
|
||||
``<g1>:<g2>:<g3>:...:<g10>``
|
||||
floating point numbers representing the gain in dB for each frequency
|
||||
band (-12-12)
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mpv --af=equalizer=11:11:10:5:0:-12:0:5:12:12 media.avi``
|
||||
Would amplify the sound in the upper and lower frequency region
|
||||
while canceling it almost completely around 1 kHz.
|
||||
|
||||
``channels=nch[:routes]``
|
||||
Can be used for adding, removing, routing and copying audio channels. If
|
||||
only ``<nch>`` is given, the default routing is used. It works as follows:
|
||||
If the number of output channels is greater than the number of input
|
||||
channels, empty channels are inserted (except when mixing from mono to
|
||||
stereo; then the mono channel is duplicated). If the number of output
|
||||
channels is less than the number of input channels, the exceeding
|
||||
channels are truncated.
|
||||
|
||||
``<nch>``
|
||||
number of output channels (1-8)
|
||||
``<routes>``
|
||||
List of ``,`` separated routes, in the form ``from1-to1,from2-to2,...``.
|
||||
Each pair defines where to route each channel. There can be at most
|
||||
8 routes. Without this argument, the default routing is used. Since
|
||||
``,`` is also used to separate filters, you must quote this argument
|
||||
with ``[...]`` or similar.
|
||||
|
||||
.. admonition:: Examples
|
||||
|
||||
``mpv --af=channels=4:[0-1,1-0,0-2,1-3] media.avi``
|
||||
Would change the number of channels to 4 and set up 4 routes that
|
||||
swap channel 0 and channel 1 and leave channel 2 and 3 intact.
|
||||
Observe that if media containing two channels were played back,
|
||||
channels 2 and 3 would contain silence but 0 and 1 would still be
|
||||
swapped.
|
||||
|
||||
``mpv --af=channels=6:[0-0,0-1,0-2,0-3] media.avi``
|
||||
Would change the number of channels to 6 and set up 4 routes that
|
||||
copy channel 0 to channels 0 to 3. Channel 4 and 5 will contain
|
||||
silence.
|
||||
|
||||
.. note::
|
||||
|
||||
You should probably not use this filter. If you want to change the
|
||||
output channel layout, try the ``format`` filter, which can make mpv
|
||||
automatically up- and downmix standard channel layouts.
|
||||
|
||||
``format=format:srate:channels:out-format:out-srate:out-channels``
|
||||
Force a specific audio format/configuration without actually changing the
|
||||
audio data. Keep in mind that the filter system might auto-insert actual
|
||||
conversion filters before or after this filter if needed.
|
||||
|
||||
All parameters are optional. The first 3 parameters restrict what the filter
|
||||
accepts as input. They will therefore cause conversion filters to be
|
||||
inserted before this one. The ``out-`` parameters tell the filters or audio
|
||||
outputs following this filter how to interpret the data without actually
|
||||
doing a conversion. Setting these will probably just break things unless you
|
||||
really know you want this for some reason, such as testing or dealing with
|
||||
broken media.
|
||||
accepts as input. The ``out-`` parameters change the audio format, without
|
||||
actually doing a conversion. The data will be 'reinterpreted' by the
|
||||
filters or audio outputs following this filter.
|
||||
|
||||
``<format>``
|
||||
Force conversion to this format. Use ``--af=format=format=help`` to get
|
||||
@@ -90,13 +246,292 @@ Available filters are:
|
||||
Force mixing to a specific channel layout. See ``--audio-channels`` option
|
||||
for possible values.
|
||||
|
||||
``<out-format>``
|
||||
|
||||
``<out-srate>``
|
||||
|
||||
``<out-channels>``
|
||||
|
||||
*NOTE*: this filter used to be named ``force``. The old ``format`` filter
|
||||
used to do conversion itself, unlike this one which lets the filter system
|
||||
handle the conversion.
|
||||
See also ``--audio-format``, ``--audio-samplerate``, and
|
||||
``--audio-channels`` for related options. Keep in mind that
|
||||
``--audio-channels`` does not actually force the number of
|
||||
channels in most cases, while this filter can do this.
|
||||
|
||||
*NOTE*: this filter used to be named ``force``. Also, unlike the old
|
||||
``format`` filter, this does not do any actual conversion anymore.
|
||||
Conversion is done by other, automatically inserted filters.
|
||||
|
||||
``convert24``
|
||||
Filter for internal use only. Converts between 24-bit and 32-bit sample
|
||||
formats.
|
||||
|
||||
``convertsign``
|
||||
Filter for internal use only. Converts between signed/unsigned formats.
|
||||
|
||||
``volume[=<volumedb>[:...]]``
|
||||
Implements software volume control. Use this filter with caution since it
|
||||
can reduce the signal to noise ratio of the sound. In most cases it is
|
||||
best to use the *Master* volume control of your sound card or the volume
|
||||
knob on your amplifier.
|
||||
|
||||
*NOTE*: This filter is not reentrant and can therefore only be enabled
|
||||
once for every audio stream.
|
||||
|
||||
``<volumedb>``
|
||||
Sets the desired gain in dB for all channels in the stream from -200 dB
|
||||
to +60 dB, where -200 dB mutes the sound completely and +60 dB equals a
|
||||
gain of 1000 (default: 0).
|
||||
``replaygain-track``
|
||||
Adjust volume gain according to the track-gain replaygain value stored
|
||||
in the file metadata.
|
||||
``replaygain-album``
|
||||
Like replaygain-track, but using the album-gain value instead.
|
||||
``replaygain-preamp``
|
||||
Pre-amplification gain in dB to apply to the selected replaygain gain
|
||||
(default: 0).
|
||||
``replaygain-clip=yes|no``
|
||||
Prevent clipping caused by replaygain by automatically lowering the
|
||||
gain (default). Use ``replaygain-clip=no`` to disable this.
|
||||
``softclip``
|
||||
Turns soft clipping on. Soft-clipping can make the
|
||||
sound more smooth if very high volume levels are used. Enable this
|
||||
option if the dynamic range of the loudspeakers is very low.
|
||||
|
||||
*WARNING*: This feature creates distortion and should be considered a
|
||||
last resort.
|
||||
``s16``
|
||||
Force S16 sample format if set. Lower quality, but might be faster
|
||||
in some situations.
|
||||
``detach``
|
||||
Remove the filter if the volume is not changed at audio filter config
|
||||
time. Useful with replaygain: if the current file has no replaygain
|
||||
tags, then the filter will be removed if this option is enabled.
|
||||
(If ``--softvol=yes`` is used and the player volume controls are used
|
||||
during playback, a different volume filter will be inserted.)
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mpv --af=volume=10.1 media.avi``
|
||||
Would amplify the sound by 10.1 dB and hard-clip if the sound level
|
||||
is too high.
|
||||
|
||||
``pan=n:[<matrix>]``
|
||||
Mixes channels arbitrarily. Basically a combination of the volume and the
|
||||
channels filter that can be used to down-mix many channels to only a few,
|
||||
e.g. stereo to mono, or vary the "width" of the center speaker in a
|
||||
surround sound system. This filter is hard to use, and will require some
|
||||
tinkering before the desired result is obtained. The number of options for
|
||||
this filter depends on the number of output channels. An example how to
|
||||
downmix a six-channel file to two channels with this filter can be found
|
||||
in the examples section near the end.
|
||||
|
||||
``<n>``
|
||||
Number of output channels (1-8).
|
||||
``<matrix>``
|
||||
A list of values ``[L00,L01,L02,...,L10,L11,L12,...,Ln0,Ln1,Ln2,...]``,
|
||||
where each element ``Lij`` means how much of input channel i is mixed
|
||||
into output channel j (range 0-1). So in principle you first have n
|
||||
numbers saying what to do with the first input channel, then n numbers
|
||||
that act on the second input channel etc. If you do not specify any
|
||||
numbers for some input channels, 0 is assumed.
|
||||
Note that the values are separated by ``,``, which is already used
|
||||
by the option parser to separate filters. This is why you must quote
|
||||
the value list with ``[...]`` or similar.
|
||||
|
||||
.. admonition:: Examples
|
||||
|
||||
``mpv --af=pan=1:[0.5,0.5] media.avi``
|
||||
Would downmix from stereo to mono.
|
||||
|
||||
``mpv --af=pan=3:[1,0,0.5,0,1,0.5] media.avi``
|
||||
Would give 3 channel output leaving channels 0 and 1 intact, and mix
|
||||
channels 0 and 1 into output channel 2 (which could be sent to a
|
||||
subwoofer for example).
|
||||
|
||||
.. note::
|
||||
|
||||
If you just want to force remixing to a certain output channel layout,
|
||||
it is easier to use the ``format`` filter. For example,
|
||||
``mpv '--af=format=channels=5.1' '--audio-channels=5.1'`` would always force
|
||||
remixing audio to 5.1 and output it like this.
|
||||
|
||||
``sub[=fc:ch]``
|
||||
Adds a subwoofer channel to the audio stream. The audio data used for
|
||||
creating the subwoofer channel is an average of the sound in channel 0 and
|
||||
channel 1. The resulting sound is then low-pass filtered by a 4th order
|
||||
Butterworth filter with a default cutoff frequency of 60Hz and added to a
|
||||
separate channel in the audio stream.
|
||||
|
||||
.. warning::
|
||||
|
||||
Disable this filter when you are playing media with an LFE channel
|
||||
(e.g. 5.1 surround sound), otherwise this filter will disrupt the sound
|
||||
to the subwoofer.
|
||||
|
||||
``<fc>``
|
||||
cutoff frequency in Hz for the low-pass filter (20 Hz to 300 Hz)
|
||||
(default: 60 Hz) For the best result try setting the cutoff frequency
|
||||
as low as possible. This will improve the stereo or surround sound
|
||||
experience.
|
||||
``<ch>``
|
||||
Determines the channel number in which to insert the sub-channel
|
||||
audio. Channel number can be between 0 and 7 (default: 5). Observe
|
||||
that the number of channels will automatically be increased to <ch> if
|
||||
necessary.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mpv --af=sub=100:4 --audio-channels=5 media.avi``
|
||||
Would add a subwoofer channel with a cutoff frequency of 100 Hz to
|
||||
output channel 4.
|
||||
|
||||
``center``
|
||||
Creates a center channel from the front channels. May currently be low
|
||||
quality as it does not implement a high-pass filter for proper extraction
|
||||
yet, but averages and halves the channels instead.
|
||||
|
||||
``<ch>``
|
||||
Determines the channel number in which to insert the center channel.
|
||||
Channel number can be between 0 and 7 (default: 5). Observe that the
|
||||
number of channels will automatically be increased to ``<ch>`` if
|
||||
necessary.
|
||||
|
||||
``surround[=delay]``
|
||||
Decoder for matrix encoded surround sound like Dolby Surround. Some files
|
||||
with 2-channel audio actually contain matrix encoded surround sound.
|
||||
|
||||
``<delay>``
|
||||
delay time in ms for the rear speakers (0 to 1000) (default: 20) This
|
||||
delay should be set as follows: If d1 is the distance from the
|
||||
listening position to the front speakers and d2 is the distance from
|
||||
the listening position to the rear speakers, then the delay should be
|
||||
set to 15ms if d1 <= d2 and to 15 + 5*(d1-d2) if d1 > d2.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mpv --af=surround=15 --audio-channels=4 media.avi``
|
||||
Would add surround sound decoding with 15 ms delay for the sound to
|
||||
the rear speakers.
|
||||
|
||||
``delay[=[ch1,ch2,...]]``
|
||||
Delays the sound to the loudspeakers such that the sound from the
|
||||
different channels arrives at the listening position simultaneously. It is
|
||||
only useful if you have more than 2 loudspeakers.
|
||||
|
||||
``[ch1,ch2,...]``
|
||||
The delay in ms that should be imposed on each channel (floating point
|
||||
number between 0 and 1000).
|
||||
|
||||
To calculate the required delay for the different channels, do as follows:
|
||||
|
||||
1. Measure the distance to the loudspeakers in meters in relation to your
|
||||
listening position, giving you the distances s1 to s5 (for a 5.1
|
||||
system). There is no point in compensating for the subwoofer (you will
|
||||
not hear the difference anyway).
|
||||
|
||||
2. Subtract the distances s1 to s5 from the maximum distance, i.e.
|
||||
``s[i] = max(s) - s[i]; i = 1...5``.
|
||||
|
||||
3. Calculate the required delays in ms as ``d[i] = 1000*s[i]/342; i =
|
||||
1...5``.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mpv --af=delay=[10.5,10.5,0,0,7,0] media.avi``
|
||||
Would delay front left and right by 10.5 ms, the two rear channels
|
||||
and the subwoofer by 0 ms and the center channel by 7 ms.
|
||||
|
||||
``export=mmapped_file:nsamples]``
|
||||
Exports the incoming signal to other processes using memory mapping
|
||||
(``mmap()``). Memory mapped areas contain a header::
|
||||
|
||||
int nch /* number of channels */
|
||||
int size /* buffer size */
|
||||
unsigned long long counter /* Used to keep sync, updated every time
|
||||
new data is exported. */
|
||||
|
||||
The rest is payload (non-interleaved) 16-bit data.
|
||||
|
||||
``<mmapped_file>``
|
||||
File to map data to (required)
|
||||
``<nsamples>``
|
||||
number of samples per channel (default: 512).
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mpv --af=export=/tmp/mpv-af_export:1024 media.avi``
|
||||
Would export 1024 samples per channel to ``/tmp/mpv-af_export``.
|
||||
|
||||
``extrastereo[=mul]``
|
||||
(Linearly) increases the difference between left and right channels which
|
||||
adds some sort of "live" effect to playback.
|
||||
|
||||
``<mul>``
|
||||
Sets the difference coefficient (default: 2.5). 0.0 means mono sound
|
||||
(average of both channels), with 1.0 sound will be unchanged, with
|
||||
-1.0 left and right channels will be swapped.
|
||||
|
||||
``drc[=method:target]``
|
||||
Applies dynamic range compression. This maximizes the volume by compressing
|
||||
the audio signal's dynamic range. (Formerly called ``volnorm``.)
|
||||
|
||||
``<method>``
|
||||
Sets the used method.
|
||||
|
||||
1
|
||||
Use a single sample to smooth the variations via the standard
|
||||
weighted mean over past samples (default).
|
||||
2
|
||||
Use several samples to smooth the variations via the standard
|
||||
weighted mean over past samples.
|
||||
|
||||
``<target>``
|
||||
Sets the target amplitude as a fraction of the maximum for the sample
|
||||
type (default: 0.25).
|
||||
|
||||
.. note::
|
||||
|
||||
This filter can cause distortion with audio signals that have a very
|
||||
large dynamic range.
|
||||
|
||||
``ladspa=file:label:[<control0>,<control1>,...]``
|
||||
Load a LADSPA (Linux Audio Developer's Simple Plugin API) plugin. This
|
||||
filter is reentrant, so multiple LADSPA plugins can be used at once.
|
||||
|
||||
``<file>``
|
||||
Specifies the LADSPA plugin library file.
|
||||
|
||||
.. note::
|
||||
|
||||
See also the note about the ``LADSPA_PATH`` variable in the
|
||||
`ENVIRONMENT VARIABLES`_ section.
|
||||
``<label>``
|
||||
Specifies the filter within the library. Some libraries contain only
|
||||
one filter, but others contain many of them. Entering 'help' here
|
||||
will list all available filters within the specified library, which
|
||||
eliminates the use of 'listplugins' from the LADSPA SDK.
|
||||
``[<control0>,<control1>,...]``
|
||||
Controls are zero or more ``,`` separated floating point values that
|
||||
determine the behavior of the loaded plugin (for example delay,
|
||||
threshold or gain).
|
||||
In verbose mode (add ``-v`` to the mpv command line), all
|
||||
available controls and their valid ranges are printed. This eliminates
|
||||
the use of 'analyseplugin' from the LADSPA SDK.
|
||||
Note that ``,`` is already used by the option parser to separate
|
||||
filters, so you must quote the list of values with ``[...]`` or
|
||||
similar.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mpv --af=ladspa='/usr/lib/ladspa/delay.so':delay_5s:[0.5,0.2] media.avi``
|
||||
Does something.
|
||||
|
||||
``karaoke``
|
||||
Simple voice removal filter exploiting the fact that voice is usually
|
||||
recorded with mono gear and later 'center' mixed onto the final audio
|
||||
stream. Beware that this filter will turn your signal into mono. Works
|
||||
well for 2 channel tracks; do not bother trying it on anything but 2
|
||||
channel stereo.
|
||||
|
||||
``scaletempo[=option1:option2:...]``
|
||||
Scales audio tempo without altering pitch, optionally synced to playback
|
||||
@@ -157,42 +592,15 @@ 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
|
||||
1.2x.
|
||||
|
||||
``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. It can also be used to adjust audio pitch
|
||||
without changing playback speed.
|
||||
|
||||
``<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
|
||||
to learn what each option does:
|
||||
http://breakfastquay.com/rubberband/code-doc/classRubberBand_1_1RubberBandStretcher.html
|
||||
(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``.
|
||||
|
||||
``multiply-pitch <factor>``
|
||||
Multiply the current value of ``<pitch-scale>`` dynamically. For
|
||||
example: 0.5 to go down by an octave, 1.5 to go up by a perfect fifth.
|
||||
If you want to go up or down by semi-tones, use 1.059463094352953 and
|
||||
0.9438743126816935
|
||||
|
||||
``lavfi=graph``
|
||||
Filter audio using FFmpeg's libavfilter.
|
||||
|
||||
@@ -208,15 +616,3 @@ Available filters are:
|
||||
``o=<string>``
|
||||
AVOptions.
|
||||
|
||||
``fix-pts=<yes|no>``
|
||||
Determine PTS based on sample count (default: no). If this is enabled,
|
||||
the player won't rely on libavfilter passing through PTS accurately.
|
||||
Instead, it pass a sample count as PTS to libavfilter, and compute the
|
||||
PTS used by mpv based on that and the input PTS. This helps with filters
|
||||
which output a recomputed PTS instead of the original PTS (including
|
||||
filters which require the PTS to start at 0). mpv normally expects
|
||||
filters to not touch the PTS (or only to the extent of changing frame
|
||||
boundaries), so this is not the default, but it will be needed to use
|
||||
broken filters. In practice, these broken filters will either cause slow
|
||||
A/V desync over time (with some files), or break playback completely if
|
||||
you seek or start playback from the middle of a file.
|
||||
+162
-103
@@ -4,74 +4,141 @@ AUDIO OUTPUT DRIVERS
|
||||
Audio output drivers are interfaces to different audio output facilities. The
|
||||
syntax is:
|
||||
|
||||
``--ao=<driver1,driver2,...[,]>``
|
||||
``--ao=<driver1[:suboption1[=value]:...],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.
|
||||
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.
|
||||
|
||||
``--ao-defaults=<driver1[:parameter1:parameter2:...],driver2,...>``
|
||||
Set defaults for each driver.
|
||||
|
||||
.. note::
|
||||
|
||||
See ``--ao=help`` for a list of compiled-in audio output drivers. The
|
||||
driver ``--ao=alsa`` is preferred. ``--ao=pulse`` is preferred on systems
|
||||
where PulseAudio is used. On BSD systems, ``--ao=oss`` or ``--ao=sndio``
|
||||
may work (the latter being experimental).
|
||||
where PulseAudio is used. On Windows, ``--ao=wasapi`` is preferred,
|
||||
though it might cause trouble sometimes, in which case ``--ao=dsound``
|
||||
should be used. On BSD systems, ``--ao=oss`` or `--ao=sndio`` may work
|
||||
(the latter being experimental). On OS X systems, use ``--ao=coreaudio``.
|
||||
|
||||
.. 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
|
||||
|
||||
See `ALSA audio output options`_ for options specific to this AO.
|
||||
``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.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. warning::
|
||||
|
||||
To get multichannel/surround audio, use ``--audio-channels=auto``. The
|
||||
default for this option is ``auto-safe``, which makes this audio output
|
||||
explicitly reject multichannel output, as there is no way to detect
|
||||
whether a certain channel layout is actually supported.
|
||||
Handling of multichannel/surround audio changed in mpv 0.8.0 from the
|
||||
behavior in MPlayer/mplayer2 and older versions of mpv.
|
||||
|
||||
You can also try `using the upmix plugin <http://git.io/vfuAy>`_.
|
||||
This setup enables multichannel audio on the ``default`` device
|
||||
with automatic upmixing with shared access, so playing stereo
|
||||
and multichannel audio at the same time will work as expected.
|
||||
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).
|
||||
|
||||
You can also try
|
||||
`Using the upmix plugin <https://github.com/mpv-player/mpv/wiki/ALSA:-Surround-Sound-and-Upmixing>`_.
|
||||
|
||||
``oss``
|
||||
OSS audio output driver
|
||||
|
||||
The following global options are supported by this audio output:
|
||||
|
||||
``--oss-mixer-device``
|
||||
``<dsp-device>``
|
||||
Sets the audio output device (default: ``/dev/dsp``).
|
||||
``<mixer-device>``
|
||||
Sets the audio mixer device (default: ``/dev/mixer``).
|
||||
``--oss-mixer-channel``
|
||||
``<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
|
||||
|
||||
The following global options are supported by this audio output:
|
||||
|
||||
``--jack-port=<name>``
|
||||
``port=<name>``
|
||||
Connects to the ports with the given name (default: physical ports).
|
||||
``--jack-name=<client>``
|
||||
``name=<client>``
|
||||
Client name that is passed to JACK (default: ``mpv``). Useful
|
||||
if you want to have certain connections established automatically.
|
||||
``--jack-autostart=<yes|no>``
|
||||
``(no-)autostart``
|
||||
Automatically start jackd if necessary (default: disabled). Note that
|
||||
this tends to be unreliable and will flood stdout with server messages.
|
||||
``--jack-connect=<yes|no>``
|
||||
``(no-)connect``
|
||||
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.
|
||||
``--jack-std-channel-layout=<waveext|any>``
|
||||
Select the standard channel layout (default: waveext). JACK itself has no
|
||||
``std-channel-layout=alsa|waveext|any``
|
||||
Select the standard channel layout (default: alsa). 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
|
||||
outputs, and reroutes it to whatever the user defines. This means the
|
||||
user and the application are in charge of dealing with the channel
|
||||
layout. ``waveext`` uses WAVE_FORMAT_EXTENSIBLE order, which, even
|
||||
layout. ``alsa`` uses the old MPlayer layout, which is inspired by
|
||||
ALSA's standard layouts. In this mode, ao_jack will refuse to play 3
|
||||
or 7 channels (because these do not really have a defined meaning in
|
||||
MPlayer). ``waveext`` uses WAVE_FORMAT_EXTENSIBLE order, which, even
|
||||
though it was defined by Microsoft, is the standard on many systems.
|
||||
The value ``any`` makes JACK accept whatever comes from the audio
|
||||
filter chain, regardless of channel layout and without reordering. This
|
||||
@@ -85,63 +152,33 @@ Available audio output drivers are:
|
||||
Automatically redirects to ``coreaudio_exclusive`` when playing compressed
|
||||
formats.
|
||||
|
||||
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
|
||||
system-wide audio settings. This is equivalent to changing the ``Format``
|
||||
setting in the ``Audio Devices`` dialog in the ``Audio MIDI Setup``
|
||||
utility. Note that this does not affect the selected speaker setup.
|
||||
|
||||
``--coreaudio-spdif-hack=<yes|no>``
|
||||
Try to pass through AC3/DTS data as PCM. This is useful for drivers
|
||||
which do not report AC3 support. It converts the AC3 data to float,
|
||||
and assumes the driver will do the inverse conversion, which means
|
||||
a typical A/V receiver will pick it up as compressed IEC framed AC3
|
||||
stream, ignoring that it's marked as PCM. This disables normal AC3
|
||||
passthrough (even if the device reports it as supported). Use with
|
||||
extreme care.
|
||||
|
||||
|
||||
``coreaudio_exclusive`` (Mac OS X only)
|
||||
Native Mac OS X audio output driver using direct device access and
|
||||
exclusive mode (bypasses the sound server).
|
||||
|
||||
Supports only compressed formats (AC3 and DTS).
|
||||
|
||||
``openal``
|
||||
OpenAL audio output driver
|
||||
Experimental OpenAL audio output driver
|
||||
|
||||
``--openal-num-buffers=<2-128>``
|
||||
Specify the number of audio buffers to use. Lower values are better for
|
||||
lower CPU usage. Default: 4.
|
||||
|
||||
``--openal-num-samples=<256-32768>``
|
||||
Specify the number of complete samples to use for each buffer. Higher
|
||||
values are better for lower CPU usage. Default: 8192.
|
||||
|
||||
``--openal-direct-channels=<yes|no>``
|
||||
Enable OpenAL Soft's direct channel extension when available to avoid
|
||||
tinting the sound with ambisonics or HRTF.
|
||||
Channels are dropped when when they are not available as downmixing
|
||||
will be disabled. Default: no.
|
||||
.. note:: This driver is not very useful. Playing multi-channel audio with
|
||||
it is slow.
|
||||
|
||||
``pulse``
|
||||
PulseAudio audio output driver
|
||||
|
||||
The following global options are supported by this audio output:
|
||||
``[<host>][:<output 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).
|
||||
|
||||
``--pulse-host=<host>``
|
||||
Specify the host to use. An empty <host> string uses a local connection,
|
||||
"localhost" uses network transfer (most likely not what you want).
|
||||
|
||||
``--pulse-buffer=<1-2000|native>``
|
||||
``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.
|
||||
changes. Default: 250.
|
||||
|
||||
``--pulse-latency-hacks=<yes|no>``
|
||||
``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
|
||||
@@ -150,11 +187,19 @@ Available audio output drivers are:
|
||||
(it used to be required to get good behavior on old PulseAudio versions).
|
||||
|
||||
If you have stuttering video when using pulse, try to enable this
|
||||
option. (Or try to update PulseAudio.)
|
||||
option. (Or alternatively, try to update PulseAudio.)
|
||||
|
||||
``--pulse-allow-suspended=<yes|no>``
|
||||
Allow mpv to use PulseAudio even if the sink is suspended (default: no).
|
||||
Can be useful if PulseAudio is running as a bridge to jack and mpv has its sink-input set to the one jack is using.
|
||||
``dsound`` (Windows only)
|
||||
DirectX DirectSound audio output driver
|
||||
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
``device=<devicenum>``
|
||||
Sets the device number to use. Playing a file with ``-v`` will show a
|
||||
list of available devices.
|
||||
|
||||
``buffersize=<ms>``
|
||||
DirectSound buffer size in milliseconds (default: 200).
|
||||
|
||||
``sdl``
|
||||
SDL 1.2+ audio output driver. Should work on any platform supported by SDL
|
||||
@@ -165,82 +210,76 @@ Available audio output drivers are:
|
||||
environments, such as systems where none of the other drivers
|
||||
are available.
|
||||
|
||||
The following global options are supported by this audio output:
|
||||
|
||||
``--sdl-buflen=<length>``
|
||||
``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.
|
||||
|
||||
``--sdl-bufcnt=<count>``
|
||||
``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. You can use
|
||||
``--ao=null --ao-null-untimed`` for benchmarking.
|
||||
Produces no audio output but maintains video playback speed. Use
|
||||
``--ao=null:untimed`` for benchmarking.
|
||||
|
||||
The following global options are supported by this audio output:
|
||||
|
||||
``--ao-null-untimed``
|
||||
``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.
|
||||
|
||||
``--ao-null-buffer``
|
||||
``buffer``
|
||||
Simulated buffer length in seconds.
|
||||
|
||||
``--ao-null-outburst``
|
||||
``outburst``
|
||||
Simulated chunk size in samples.
|
||||
|
||||
``--ao-null-speed``
|
||||
``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.
|
||||
just a little, and this option helps simulating this.
|
||||
|
||||
``--ao-null-latency``
|
||||
``latency``
|
||||
Simulated device latency. This is additional to EOF.
|
||||
|
||||
``--ao-null-broken-eof``
|
||||
``broken-eof``
|
||||
Simulate broken audio drivers, which always add the fixed device
|
||||
latency to the reported audio playback position.
|
||||
|
||||
``--ao-null-broken-delay``
|
||||
``broken-delay``
|
||||
Simulate broken audio drivers, which don't report latency correctly.
|
||||
|
||||
``--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.
|
||||
|
||||
``--ao-null-format``
|
||||
Force the audio output format the AO will accept. If unset accepts any.
|
||||
|
||||
``pcm``
|
||||
Raw PCM/WAVE file writer audio output
|
||||
|
||||
The following global options are supported by this audio output:
|
||||
|
||||
``--ao-pcm-waveheader=<yes|no>``
|
||||
``(no-)waveheader``
|
||||
Include or do not include the WAVE header (default: included). When
|
||||
not included, raw PCM will be generated.
|
||||
``--ao-pcm-file=<filename>``
|
||||
``file=<filename>``
|
||||
Write the sound to ``<filename>`` instead of the default
|
||||
``audiodump.wav``. If ``no-waveheader`` is specified, the default is
|
||||
``audiodump.pcm``.
|
||||
``--ao-pcm-append=<yes|no>``
|
||||
``(no-)append``
|
||||
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.
|
||||
|
||||
``rsound``
|
||||
Audio output to an RSound daemon. Use ``--audio-device=rsound/<hostname>``
|
||||
to set the host name (with ``<hostname>`` replaced, without the ``< >``).
|
||||
Audio output to an RSound daemon
|
||||
|
||||
.. note:: Completely useless, unless you intend to run RSound. Not to be
|
||||
confused with RoarAudio, which is something completely
|
||||
different.
|
||||
|
||||
``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>``
|
||||
Set the TCP port used for connecting to the server (default: 12345).
|
||||
Not used if connecting to a Unix domain socket.
|
||||
|
||||
``sndio``
|
||||
Audio output to the OpenBSD sndio sound system
|
||||
|
||||
@@ -249,5 +288,25 @@ Available audio output drivers are:
|
||||
(Note: only supports mono, stereo, 4.0, 5.1 and 7.1 channel
|
||||
layouts.)
|
||||
|
||||
``device=<device>``
|
||||
sndio device to use (default: ``$AUDIODEVICE``, resp. ``snd0``).
|
||||
|
||||
``wasapi``
|
||||
Audio output to the Windows Audio Session API.
|
||||
|
||||
``device=<id>``
|
||||
Uses the requested endpoint instead of the system's default audio
|
||||
endpoint. Both the number and the ID String are valid; the ID String
|
||||
is guaranteed to not change unless the driver is uninstalled.
|
||||
|
||||
Also supports searching active devices by name. If more than one
|
||||
device matches the name, refuses loading it.
|
||||
|
||||
To get a list of the valid devices, give ``help`` as the id. The
|
||||
list is the same as the ``list`` suboption, but stops the player
|
||||
initialization.
|
||||
``exclusive``
|
||||
Requests exclusive, direct hardware access. By definition prevents
|
||||
sound playback of any other program until mpv exits.
|
||||
``list``
|
||||
Lists all audio endpoints (output devices) present in the system.
|
||||
@@ -8,11 +8,6 @@ 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. (Not updated
|
||||
anymore.)
|
||||
changes that happened since mplayer2 forked off MPlayer.
|
||||
+75
-39
@@ -8,8 +8,9 @@ You can encode files from one format/codec to another using this facility.
|
||||
|
||||
``--of=<format>``
|
||||
Specifies the output format (overrides autodetection by the file name
|
||||
extension of the file specified by ``-o``). See ``--of=help`` for a full
|
||||
list of supported formats.
|
||||
extension of the file specified by ``-o``). This can be a comma separated
|
||||
list of possible formats to try. See ``--of=help`` for a full list of
|
||||
supported formats.
|
||||
|
||||
``--ofopts=<options>``
|
||||
Specifies the output format options for libavformat.
|
||||
@@ -21,16 +22,50 @@ You can encode files from one format/codec to another using this facility.
|
||||
``--ofopts-add=<options1[,options2,...]>``
|
||||
Appends the options given as arguments to the options list.
|
||||
|
||||
``--ofopts=""``
|
||||
``--ofopts-pre=<options1[,options2,...]>``
|
||||
Prepends the options given as arguments to the options list.
|
||||
|
||||
``--ofopts-del=<index1[,index2,...]>``
|
||||
Deletes the options at the given indexes. Index numbers start at 0,
|
||||
negative numbers address the end of the list (-1 is the last).
|
||||
|
||||
``--ofopts-clr``
|
||||
Completely empties the options list.
|
||||
|
||||
``--ofps=<float value>``
|
||||
Specifies the output format time base (default: 24000). Low values like 25
|
||||
limit video fps by dropping frames.
|
||||
|
||||
``--oautofps``
|
||||
Sets the output format time base to the guessed frame rate of the input
|
||||
video (simulates MEncoder behavior, useful for AVI; may cause frame drops).
|
||||
Note that not all codecs and not all formats support VFR encoding, and some
|
||||
which do have bugs when a target bitrate is specified - use ``--ofps`` or
|
||||
``--oautofps`` to force CFR encoding in these cases.
|
||||
|
||||
``--omaxfps=<float value>``
|
||||
Specifies the minimum distance of adjacent frames (default: 0, which means
|
||||
unset). Content of lower frame rate is not readjusted to this frame rate;
|
||||
content of higher frame rate is decimated to this frame rate.
|
||||
|
||||
``--oharddup``
|
||||
If set, the frame rate given by ``--ofps`` is attained not by skipping time
|
||||
codes, but by duplicating frames (constant frame rate mode).
|
||||
|
||||
``--oneverdrop``
|
||||
If set, frames are never dropped. Instead, time codes of video are
|
||||
readjusted to always increase. This may cause AV desync, though; to work
|
||||
around this, use a high-fps time base using ``--ofps`` and absolutely
|
||||
avoid ``--oautofps``.
|
||||
|
||||
``--oac=<codec>``
|
||||
Specifies the output audio codec. See ``--oac=help`` for a full list of
|
||||
supported codecs.
|
||||
Specifies the output audio codec. This can be a comma separated list of
|
||||
possible codecs to try. See ``--oac=help`` for a full list of supported
|
||||
codecs.
|
||||
|
||||
``--oaoffset=<value>``
|
||||
Shifts audio data by the given time (in seconds) by adding/removing
|
||||
samples at the start. Deprecated.
|
||||
samples at the start.
|
||||
|
||||
``--oacopts=<options>``
|
||||
Specifies the output audio codec options for libavcodec.
|
||||
@@ -47,28 +82,36 @@ You can encode files from one format/codec to another using this facility.
|
||||
``--oacopts-add=<options1[,options2,...]>``
|
||||
Appends the options given as arguments to the options list.
|
||||
|
||||
``--oacopts=""``
|
||||
``--oacopts-pre=<options1[,options2,...]>``
|
||||
Prepends the options given as arguments to the options list.
|
||||
|
||||
``--oacopts-del=<index1[,index2,...]>``
|
||||
Deletes the options at the given indexes. Index numbers start at 0,
|
||||
negative numbers address the end of the list (-1 is the last).
|
||||
|
||||
``--oacopts-clr``
|
||||
Completely empties the options list.
|
||||
|
||||
``--oafirst``
|
||||
Force the audio stream to become the first stream in the output.
|
||||
By default, the order is unspecified. Deprecated.
|
||||
Force the audio stream to become the first stream in the output. By default
|
||||
the order is unspecified.
|
||||
|
||||
``--ovc=<codec>``
|
||||
Specifies the output video codec. See ``--ovc=help`` for a full list of
|
||||
supported codecs.
|
||||
Specifies the output video codec. This can be a comma separated list of
|
||||
possible codecs to try. See ``--ovc=help`` for a full list of supported
|
||||
codecs.
|
||||
|
||||
``--ovoffset=<value>``
|
||||
Shifts video data by the given time (in seconds) by shifting the pts
|
||||
values. Deprecated.
|
||||
values.
|
||||
|
||||
``--ovcopts=<options>``
|
||||
``--ovcopts <options>``
|
||||
Specifies the output video codec options for libavcodec.
|
||||
See --ovcopts=help for a full list of supported options.
|
||||
|
||||
.. admonition:: Examples
|
||||
|
||||
``"--ovc=mpeg4 --ovcopts=qscale=5"``
|
||||
``"--ovc=mpeg4 --oacopts=qscale=5"``
|
||||
selects constant quantizer scale 5 for MPEG-4 encoding.
|
||||
|
||||
``"--ovc=libx264 --ovcopts=crf=23"``
|
||||
@@ -80,12 +123,26 @@ You can encode files from one format/codec to another using this facility.
|
||||
``--ovcopts-add=<options1[,options2,...]>``
|
||||
Appends the options given as arguments to the options list.
|
||||
|
||||
``--ovcopts=""``
|
||||
``--ovcopts-pre=<options1[,options2,...]>``
|
||||
Prepends the options given as arguments to the options list.
|
||||
|
||||
``--ovcopts-del=<index1[,index2,...]>``
|
||||
Deletes the options at the given indexes. Index numbers start at 0,
|
||||
negative numbers address the end of the list (-1 is the last).
|
||||
|
||||
``--ovcopts-clr``
|
||||
Completely empties the options list.
|
||||
|
||||
``--ovfirst``
|
||||
Force the video stream to become the first stream in the output.
|
||||
By default, the order is unspecified. Deprecated.
|
||||
Force the video stream to become the first stream in the output. By default
|
||||
the order is unspecified.
|
||||
|
||||
``--ocopyts``
|
||||
Copies input pts to the output video (not supported by some output
|
||||
container formats, e.g. AVI). Discontinuities are still fixed.
|
||||
By default, audio pts are set to playback time and video pts are
|
||||
synchronized to match audio pts, as some output formats do not support
|
||||
anything else.
|
||||
|
||||
``--orawts``
|
||||
Copies input pts to the output video (not supported by some output
|
||||
@@ -93,27 +150,6 @@ You can encode files from one format/codec to another using this facility.
|
||||
and all pts are passed through as-is. Never seek backwards or use multiple
|
||||
input files in this mode!
|
||||
|
||||
``--no-ocopy-metadata``
|
||||
``--no-ometadata``
|
||||
Turns off copying of metadata from input files to output files when
|
||||
encoding (which is enabled by default).
|
||||
|
||||
``--oset-metadata=<metadata-tag[,metadata-tag,...]>``
|
||||
Specifies metadata to include in the output file.
|
||||
Supported keys vary between output formats. For example, Matroska (MKV) and
|
||||
FLAC allow almost arbitrary keys, while support in MP4 and MP3 is more
|
||||
limited.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
"``--oset-metadata=title="Output title",comment="Another tag"``"
|
||||
adds a title and a comment to the output file.
|
||||
|
||||
``--oremove-metadata=<metadata-tag[,metadata-tag,...]>``
|
||||
Specifies metadata to exclude from the output file when copying from the
|
||||
input file.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
"``--oremove-metadata=comment,genre``"
|
||||
excludes copying of the the comment and genre tags to the output
|
||||
file.
|
||||
+500
-1383
File diff suppressed because it is too large.
Load diff
+30
-107
@@ -1,10 +1,10 @@
|
||||
JSON IPC
|
||||
========
|
||||
|
||||
mpv can be controlled by external programs using the JSON-based IPC protocol.
|
||||
It can be enabled by specifying the path to a unix socket or a named pipe using
|
||||
the option ``--input-ipc-server``. Clients can connect to this socket and send
|
||||
commands to the player or receive events from it.
|
||||
mpv can be controlled by external programs using the JSON-based IPC protocol. It
|
||||
can be enabled by specifying the path to a unix socket using the option
|
||||
``--input-unix-socket``. Clients can connect to this socket and send commands to
|
||||
the player or receive events from it.
|
||||
|
||||
.. warning::
|
||||
|
||||
@@ -17,12 +17,12 @@ commands to the player or receive events from it.
|
||||
Socat example
|
||||
-------------
|
||||
|
||||
You can use the ``socat`` tool to send commands (and receive replies) from the
|
||||
You can use the ``socat`` tool to send commands (and receive reply) from the
|
||||
shell. Assuming mpv was started with:
|
||||
|
||||
::
|
||||
|
||||
mpv file.mkv --input-ipc-server=/tmp/mpvsocket
|
||||
mpv file.mkv --input-unix-socket=/tmp/mpvsocket
|
||||
|
||||
Then you can control it using socat:
|
||||
|
||||
@@ -41,45 +41,14 @@ It's also possible to send input.conf style text-only commands:
|
||||
|
||||
::
|
||||
|
||||
> echo 'show-text ${playback-time}' | socat - /tmp/mpvsocket
|
||||
> echo 'show_text ${playback-time}' | socat - /tmp/mpvsocket
|
||||
|
||||
But you won't get a reply over the socket. (This particular command shows the
|
||||
playback time on the player's OSD.)
|
||||
|
||||
Command Prompt example
|
||||
----------------------
|
||||
|
||||
Unfortunately, it's not as easy to test the IPC protocol on Windows, since
|
||||
Windows ports of socat (in Cygwin and MSYS2) don't understand named pipes. In
|
||||
the absence of a simple tool to send and receive from bidirectional pipes, the
|
||||
``echo`` command can be used to send commands, but not receive replies from the
|
||||
command prompt.
|
||||
|
||||
Assuming mpv was started with:
|
||||
|
||||
::
|
||||
|
||||
mpv file.mkv --input-ipc-server=\\.\pipe\mpvsocket
|
||||
|
||||
You can send commands from a command prompt:
|
||||
|
||||
::
|
||||
|
||||
echo show-text ${playback-time} >\\.\pipe\mpvsocket
|
||||
|
||||
To be able to simultaneously read and write from the IPC pipe, like on Linux,
|
||||
it's necessary to write an external program that uses overlapped file I/O (or
|
||||
some wrapper like .NET's NamedPipeClientStream.)
|
||||
|
||||
Protocol
|
||||
--------
|
||||
|
||||
The protocol uses UTF-8-only JSON as defined by RFC-8259. Unlike standard JSON,
|
||||
"\u" escape sequences are not allowed to construct surrogate pairs. To avoid
|
||||
getting conflicts, encode all text characters including and above codepoint
|
||||
U+0020 as UTF-8. mpv might output broken UTF-8 in corner cases (see "UTF-8"
|
||||
section below).
|
||||
|
||||
Clients can execute commands on the player by sending JSON messages of the
|
||||
following form:
|
||||
|
||||
@@ -110,38 +79,9 @@ mpv will also send events to clients with JSON messages of the following form:
|
||||
where ``event_name`` is the name of the event. Additional event-specific fields
|
||||
can also be present. See `List of events`_ for a list of all supported events.
|
||||
|
||||
Because events can occur at any time, it may be difficult at times to determine
|
||||
which response goes with which command. Commands may optionally include a
|
||||
``request_id`` which, if provided in the command request, will be copied
|
||||
verbatim into the response. mpv does not intrepret the ``request_id`` in any
|
||||
way; it is solely for the use of the requester. The only requirement is that
|
||||
the ``request_id`` field must be an integer (a number without fractional parts
|
||||
in the range ``-2^63..2^63-1``). Using other types is deprecated and will
|
||||
currently show a warning. In the future, this will raise an error.
|
||||
|
||||
For example, this request:
|
||||
|
||||
::
|
||||
|
||||
{ "command": ["get_property", "time-pos"], "request_id": 100 }
|
||||
|
||||
Would generate this response:
|
||||
|
||||
::
|
||||
|
||||
{ "error": "success", "data": 1.468135, "request_id": 100 }
|
||||
|
||||
If you don't specify a ``request_id``, command replies will set it to 0.
|
||||
|
||||
Commands may run asynchronously in the future, instead of blocking the socket
|
||||
until a reply is sent.
|
||||
|
||||
All commands, replies, and events are separated from each other with a line
|
||||
break character (``\n``).
|
||||
|
||||
If the first character (after skipping whitespace) is not ``{``, the command
|
||||
will be interpreted as non-JSON text command, as they are used in input.conf
|
||||
(or ``mpv_command_string()`` in the client API). Additionally, lines starting
|
||||
(or ``mpv_command_string()`` in the client API). Additionally, line starting
|
||||
with ``#`` and empty lines are ignored.
|
||||
|
||||
Currently, embedded 0 bytes terminate the current line, but you should not
|
||||
@@ -150,7 +90,7 @@ rely on this.
|
||||
Commands
|
||||
--------
|
||||
|
||||
In addition to the commands described in `List of Input Commands`_, a few
|
||||
Additionally to the commands described in `List of Input Commands`_, a few
|
||||
extra commands can also be used as part of the protocol:
|
||||
|
||||
``client_name``
|
||||
@@ -194,7 +134,14 @@ extra commands can also be used as part of the protocol:
|
||||
{ "error": "success" }
|
||||
|
||||
``set_property_string``
|
||||
Alias for ``set_property``. Both commands accept native values and strings.
|
||||
Like ``set_property``, but the argument value must be passed as string.
|
||||
|
||||
Example:
|
||||
|
||||
::
|
||||
|
||||
{ "command": ["set_property_string", "pause", "yes"] }
|
||||
{ "error": "success" }
|
||||
|
||||
``observe_property``
|
||||
Watch a property for changes. If the given property is changed, then an
|
||||
@@ -208,14 +155,6 @@ extra commands can also be used as part of the protocol:
|
||||
{ "error": "success" }
|
||||
{ "event": "property-change", "id": 1, "data": 52.0, "name": "volume" }
|
||||
|
||||
.. warning::
|
||||
|
||||
If the connection is closed, the IPC client is destroyed internally,
|
||||
and the observed properties are unregistered. This happens for example
|
||||
when sending commands to a socket with separate ``socat`` invocations.
|
||||
This can make it seem like property observation does not work. You must
|
||||
keep the IPC connection open to make it work.
|
||||
|
||||
``observe_property_string``
|
||||
Like ``observe_property``, but the resulting data will always be a string.
|
||||
|
||||
@@ -229,7 +168,7 @@ extra commands can also be used as part of the protocol:
|
||||
|
||||
``unobserve_property``
|
||||
Undo ``observe_property`` or ``observe_property_string``. This requires the
|
||||
numeric id passed to the observed command as argument.
|
||||
numeric id passed to the observe command as argument.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -256,11 +195,19 @@ extra commands can also be used as part of the protocol:
|
||||
By default, most events are enabled, and there is not much use for this
|
||||
command.
|
||||
|
||||
``suspend``
|
||||
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``
|
||||
Undo one ``suspend`` call. ``suspend`` increments an internal counter, and
|
||||
``resume`` decrements it. When 0 is reached, the player is actually resumed.
|
||||
|
||||
``get_version``
|
||||
Returns the client API version the C API of the remote mpv instance
|
||||
provides.
|
||||
|
||||
See also: ``DOCS/client-api-changes.rst``.
|
||||
provides. (Also see ``DOCS/client-api-changes.rst``.)
|
||||
|
||||
UTF-8
|
||||
-----
|
||||
@@ -272,28 +219,4 @@ sometimes sends invalid JSON. If that is a problem for the client application's
|
||||
parser, it should filter the raw data for invalid UTF-8 sequences and perform
|
||||
the desired replacement, before feeding the data to its JSON parser.
|
||||
|
||||
mpv will not attempt to construct invalid UTF-8 with broken "\u" escape
|
||||
sequences. This includes surrogate pairs.
|
||||
|
||||
JSON extensions
|
||||
---------------
|
||||
|
||||
The following non-standard extensions are supported:
|
||||
|
||||
- a list or object item can have a trailing ","
|
||||
- object syntax accepts "=" in addition of ":"
|
||||
- object keys can be unquoted, if they start with a character in "A-Za-z\_"
|
||||
and contain only characters in "A-Za-z0-9\_"
|
||||
- byte escapes with "\xAB" are allowed (with AB being a 2 digit hex number)
|
||||
|
||||
Example:
|
||||
|
||||
::
|
||||
|
||||
{ objkey = "value\x0A" }
|
||||
|
||||
Is equivalent to:
|
||||
|
||||
::
|
||||
|
||||
{ "objkey": "value\n" }
|
||||
mpv will not attempt to construct invalid UTF-8 with broken escape sequences.
|
||||
@@ -1,359 +0,0 @@
|
||||
JAVASCRIPT
|
||||
==========
|
||||
|
||||
JavaScript support in mpv is near identical to its Lua support. Use this section
|
||||
as reference on differences and availability of APIs, but otherwise you should
|
||||
refer to the Lua documentation for API details and general scripting in mpv.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
JavaScript code which leaves fullscreen mode when the player is paused:
|
||||
|
||||
::
|
||||
|
||||
function on_pause_change(name, value) {
|
||||
if (value == true)
|
||||
mp.set_property("fullscreen", "no");
|
||||
}
|
||||
mp.observe_property("pause", "bool", on_pause_change);
|
||||
|
||||
|
||||
Similarities with Lua
|
||||
---------------------
|
||||
|
||||
mpv tries to load a script file as JavaScript if it has a ``.js`` extension, but
|
||||
otherwise, the documented Lua options, script directories, loading, etc apply to
|
||||
JavaScript files too.
|
||||
|
||||
Script initialization and lifecycle is the same as with Lua, and most of the Lua
|
||||
functions at the modules ``mp``, ``mp.utils``, ``mp.msg`` and ``mp.options`` are
|
||||
available to JavaScript with identical APIs - including running commands,
|
||||
getting/setting properties, registering events/key-bindings/hooks, etc.
|
||||
|
||||
Differences from Lua
|
||||
--------------------
|
||||
|
||||
No need to load modules. ``mp``, ``mp.utils``, ``mp.msg`` and ``mp.options``
|
||||
are preloaded, and you can use e.g. ``var cwd = mp.utils.getcwd();`` without
|
||||
prior setup.
|
||||
|
||||
Errors are slightly different. Where the Lua APIs return ``nil`` for error,
|
||||
the JavaScript ones return ``undefined``. Where Lua returns ``something, error``
|
||||
JavaScript returns only ``something`` - and makes ``error`` available via
|
||||
``mp.last_error()``. Note that only some of the functions have this additional
|
||||
``error`` value - typically the same ones which have it in Lua.
|
||||
|
||||
Standard APIs are preferred. For instance ``setTimeout`` and ``JSON.stringify``
|
||||
are available, but ``mp.add_timeout`` and ``mp.utils.format_json`` are not.
|
||||
|
||||
No standard library. This means that interaction with anything outside of mpv is
|
||||
limited to the available APIs, typically via ``mp.utils``. However, some file
|
||||
functions were added, and CommonJS ``require`` is available too - where the
|
||||
loaded modules have the same privileges as normal scripts.
|
||||
|
||||
Language features - ECMAScript 5
|
||||
--------------------------------
|
||||
|
||||
The scripting backend which mpv currently uses is MuJS - a compatible minimal
|
||||
ES5 interpreter. As such, ``String.substring`` is implemented for instance,
|
||||
while the common but non-standard ``String.substr`` is not. Please consult the
|
||||
MuJS pages on language features and platform support - http://mujs.com .
|
||||
|
||||
Unsupported Lua APIs and their JS alternatives
|
||||
----------------------------------------------
|
||||
|
||||
``mp.add_timeout(seconds, fn)`` JS: ``id = setTimeout(fn, ms)``
|
||||
|
||||
``mp.add_periodic_timer(seconds, fn)`` JS: ``id = setInterval(fn, ms)``
|
||||
|
||||
``utils.parse_json(str [, trail])`` JS: ``JSON.parse(str)``
|
||||
|
||||
``utils.format_json(v)`` JS: ``JSON.stringify(v)``
|
||||
|
||||
``utils.to_string(v)`` see ``dump`` below.
|
||||
|
||||
``mp.suspend()`` JS: none (deprecated).
|
||||
|
||||
``mp.resume()`` JS: none (deprecated).
|
||||
|
||||
``mp.resume_all()`` JS: none (deprecated).
|
||||
|
||||
``mp.get_next_timeout()`` see event loop below.
|
||||
|
||||
``mp.dispatch_events([allow_wait])`` see event loop below.
|
||||
|
||||
Scripting APIs - identical to Lua
|
||||
---------------------------------
|
||||
|
||||
(LE) - Last-Error, indicates that ``mp.last_error()`` can be used after the
|
||||
call to test for success (empty string) or failure (non empty reason string).
|
||||
Where the Lua APIs use ``nil`` to indicate error, JS APIs use ``undefined``.
|
||||
|
||||
``mp.command(string)`` (LE)
|
||||
|
||||
``mp.commandv(arg1, arg2, ...)`` (LE)
|
||||
|
||||
``mp.command_native(table [,def])`` (LE)
|
||||
|
||||
``id = mp.command_native_async(table [,fn])`` (LE) Notes: ``id`` is true-thy on
|
||||
success, ``fn`` is called always a-sync, ``error`` is empty string on success.
|
||||
|
||||
``mp.abort_async_command(id)``
|
||||
|
||||
``mp.get_property(name [,def])`` (LE)
|
||||
|
||||
``mp.get_property_osd(name [,def])`` (LE)
|
||||
|
||||
``mp.get_property_bool(name [,def])`` (LE)
|
||||
|
||||
``mp.get_property_number(name [,def])`` (LE)
|
||||
|
||||
``mp.get_property_native(name [,def])`` (LE)
|
||||
|
||||
``mp.set_property(name, value)`` (LE)
|
||||
|
||||
``mp.set_property_bool(name, value)`` (LE)
|
||||
|
||||
``mp.set_property_number(name, value)`` (LE)
|
||||
|
||||
``mp.set_property_native(name, value)`` (LE)
|
||||
|
||||
``mp.get_time()``
|
||||
|
||||
``mp.add_key_binding(key, name|fn [,fn [,flags]])``
|
||||
|
||||
``mp.add_forced_key_binding(...)``
|
||||
|
||||
``mp.remove_key_binding(name)``
|
||||
|
||||
``mp.register_event(name, fn)``
|
||||
|
||||
``mp.unregister_event(fn)``
|
||||
|
||||
``mp.observe_property(name, type, fn)``
|
||||
|
||||
``mp.unobserve_property(fn)``
|
||||
|
||||
``mp.get_opt(key)``
|
||||
|
||||
``mp.get_script_name()``
|
||||
|
||||
``mp.osd_message(text [,duration])``
|
||||
|
||||
``mp.get_wakeup_pipe()``
|
||||
|
||||
``mp.register_idle(fn)``
|
||||
|
||||
``mp.unregister_idle(fn)``
|
||||
|
||||
``mp.enable_messages(level)``
|
||||
|
||||
``mp.register_script_message(name, fn)``
|
||||
|
||||
``mp.unregister_script_message(name)``
|
||||
|
||||
``mp.msg.log(level, ...)``
|
||||
|
||||
``mp.msg.fatal(...)``
|
||||
|
||||
``mp.msg.error(...)``
|
||||
|
||||
``mp.msg.warn(...)``
|
||||
|
||||
``mp.msg.info(...)``
|
||||
|
||||
``mp.msg.verbose(...)``
|
||||
|
||||
``mp.msg.debug(...)``
|
||||
|
||||
``mp.msg.trace(...)``
|
||||
|
||||
``mp.utils.getcwd()`` (LE)
|
||||
|
||||
``mp.utils.readdir(path [, filter])`` (LE)
|
||||
|
||||
``mp.utils.file_info(path)`` (LE)
|
||||
|
||||
``mp.utils.split_path(path)``
|
||||
|
||||
``mp.utils.join_path(p1, p2)``
|
||||
|
||||
``mp.utils.subprocess(t)``
|
||||
|
||||
``mp.utils.subprocess_detached(t)``
|
||||
|
||||
``mp.utils.getpid()`` (LE)
|
||||
|
||||
``mp.add_hook(type, priority, fn)``
|
||||
|
||||
``mp.options.read_options(obj [, identifier])`` (types: string/boolean/number)
|
||||
|
||||
Additional utilities
|
||||
--------------------
|
||||
|
||||
``mp.last_error()``
|
||||
If used after an API call which updates last error, returns an empty string
|
||||
if the API call succeeded, or a non-empty error reason string otherwise.
|
||||
|
||||
``Error.stack`` (string)
|
||||
When using ``try { ... } catch(e) { ... }``, then ``e.stack`` is the stack
|
||||
trace of the error - if it was created using the ``Error(...)`` constructor.
|
||||
|
||||
``print`` (global)
|
||||
A convenient alias to ``mp.msg.info``.
|
||||
|
||||
``dump`` (global)
|
||||
Like ``print`` but also expands objects and arrays recursively.
|
||||
|
||||
``mp.utils.getenv(name)``
|
||||
Returns the value of the host environment variable ``name``, or
|
||||
``undefined`` if the variable is not defined.
|
||||
|
||||
``mp.utils.get_user_path(path)``
|
||||
Expands (mpv) meta paths like ``~/x``, ``~~/y``, ``~~desktop/z`` etc.
|
||||
``read_file``, ``write_file`` and ``require`` already use this internaly.
|
||||
|
||||
``mp.utils.read_file(fname [,max])``
|
||||
Returns the content of file ``fname`` as string. If ``max`` is provided and
|
||||
not negative, limit the read to ``max`` bytes.
|
||||
|
||||
``mp.utils.write_file(fname, str)``
|
||||
(Over)write file ``fname`` with text content ``str``. ``fname`` must be
|
||||
prefixed with ``file://`` as simple protection against accidental arguments
|
||||
switch, e.g. ``mp.utils.write_file("file://~/abc.txt", "hello world")``.
|
||||
|
||||
Note: ``read_file`` and ``write_file`` throw on errors, allow text content only.
|
||||
|
||||
``mp.get_time_ms()``
|
||||
Same as ``mp.get_time()`` but in ms instead of seconds.
|
||||
|
||||
``mp.get_script_file()``
|
||||
Returns the file name of the current script.
|
||||
|
||||
``exit()`` (global)
|
||||
Make the script exit at the end of the current event loop iteration.
|
||||
Note: please remove added key bindings before calling ``exit()``.
|
||||
|
||||
``mp.utils.compile_js(fname, content_str)``
|
||||
Compiles the JS code ``content_str`` as file name ``fname`` (without loading
|
||||
anything from the filesystem), and returns it as a function. Very similar
|
||||
to a ``Function`` constructor, but shows at stack traces as ``fname``.
|
||||
|
||||
Timers (global)
|
||||
---------------
|
||||
|
||||
The standard HTML/node.js timers are available:
|
||||
|
||||
``id = setTimeout(fn [,duration [,arg1 [,arg2...]]])``
|
||||
|
||||
``id = setTimeout(code_string [,duration])``
|
||||
|
||||
``clearTimeout(id)``
|
||||
|
||||
``id = setInterval(fn [,duration [,arg1 [,arg2...]]])``
|
||||
|
||||
``id = setInterval(code_string [,duration])``
|
||||
|
||||
``clearInterval(id)``
|
||||
|
||||
``setTimeout`` and ``setInterval`` return id, and later call ``fn`` (or execute
|
||||
``code_string``) after ``duration`` ms. Interval also repeat every ``duration``.
|
||||
|
||||
``duration`` has a minimum and default value of 0, ``code_string`` is
|
||||
a plain string which is evaluated as JS code, and ``[,arg1 [,arg2..]]`` are used
|
||||
as arguments (if provided) when calling back ``fn``.
|
||||
|
||||
The ``clear...(id)`` functions cancel timer ``id``, and are irreversible.
|
||||
|
||||
Note: timers always call back asynchronously, e.g. ``setTimeout(fn)`` will never
|
||||
call ``fn`` before returning. ``fn`` will be called either at the end of this
|
||||
event loop iteration or at a later event loop iteration. This is true also for
|
||||
intervals - which also never call back twice at the same event loop iteration.
|
||||
|
||||
Additionally, timers are processed after the event queue is empty, so it's valid
|
||||
to use ``setTimeout(fn)`` as a one-time idle observer.
|
||||
|
||||
CommonJS modules and ``require(id)``
|
||||
------------------------------------
|
||||
|
||||
CommonJS Modules are a standard system where scripts can export common functions
|
||||
for use by other scripts. A module is a script which adds properties (functions,
|
||||
etc) to its invisible ``exports`` object, which another script can access by
|
||||
loading it with ``require(module-id)`` - which returns that ``exports`` object.
|
||||
|
||||
Modules and ``require`` are supported, standard compliant, and generally similar
|
||||
to node.js. However, most node.js modules won't run due to missing modules such
|
||||
as ``fs``, ``process``, etc, but some node.js modules with minimal dependencies
|
||||
do work. In general, this is for mpv modules and not a node.js replacement.
|
||||
|
||||
A ``.js`` file extension is always added to ``id``, e.g. ``require("./foo")``
|
||||
will load the file ``./foo.js`` and return its ``exports`` object.
|
||||
|
||||
An id is relative (to the script which ``require``'d it) if it starts with
|
||||
``./`` or ``../``. Otherwise, it's considered a "top-level id" (CommonJS term).
|
||||
|
||||
Top level id is evaluated as absolute filesystem path if possible (e.g. ``/x/y``
|
||||
or ``~/x``). Otherwise, it's searched at ``scripts/modules.js/`` in mpv config
|
||||
dirs - in normal config search order. E.g. ``require("x")`` is searched as file
|
||||
``x.js`` at those dirs, and id ``foo/x`` is searched as file ``foo/x.js``.
|
||||
|
||||
No ``global`` variable, but a module's ``this`` at its top lexical scope is the
|
||||
global object - also in strict mode. If you have a module which needs ``global``
|
||||
as the global object, you could do ``this.global = this;`` before ``require``.
|
||||
|
||||
Functions and variables declared at a module don't pollute the global object.
|
||||
|
||||
The event loop
|
||||
--------------
|
||||
|
||||
The event loop poll/dispatch mpv events as long as the queue is not empty, then
|
||||
processes the timers, then waits for the next event, and repeats this forever.
|
||||
|
||||
You could put this code at your script to replace the built-in event loop, and
|
||||
also print every event which mpv sends to your script:
|
||||
|
||||
::
|
||||
|
||||
function mp_event_loop() {
|
||||
var wait = 0;
|
||||
do {
|
||||
var e = mp.wait_event(wait);
|
||||
dump(e); // there could be a lot of prints...
|
||||
if (e.event != "none") {
|
||||
mp.dispatch_event(e);
|
||||
wait = 0;
|
||||
} else {
|
||||
wait = mp.process_timers() / 1000;
|
||||
if (wait != 0) {
|
||||
mp.notify_idle_observers();
|
||||
wait = mp.peek_timers_wait() / 1000;
|
||||
}
|
||||
}
|
||||
} while (mp.keep_running);
|
||||
}
|
||||
|
||||
|
||||
``mp_event_loop`` is a name which mpv tries to call after the script loads.
|
||||
The internal implementation is similar to this (without ``dump`` though..).
|
||||
|
||||
``e = mp.wait_event(wait)`` returns when the next mpv event arrives, or after
|
||||
``wait`` seconds if positive and no mpv events arrived. ``wait`` value of 0
|
||||
returns immediately (with ``e.event == "none"`` if the queue is empty).
|
||||
|
||||
``mp.dispatch_event(e)`` calls back the handlers registered for ``e.event``,
|
||||
if there are such (event handlers, property observers, script messages, etc).
|
||||
|
||||
``mp.process_timers()`` calls back the already-added, non-canceled due timers,
|
||||
and returns the duration in ms till the next due timer (possibly 0), or -1 if
|
||||
there are no pending timers. Must not be called recursively.
|
||||
|
||||
``mp.notify_idle_observers()`` calls back the idle observers, which we do when
|
||||
we're about to sleep (wait != 0), but the observers may add timers or take
|
||||
non-negligible duration to complete, so we re-calculate ``wait`` afterwards.
|
||||
|
||||
``mp.peek_timers_wait()`` returns the same values as ``mp.process_timers()``
|
||||
but without doing anything. Invalid result if called from a timer callback.
|
||||
|
||||
Note: ``exit()`` is also registered for the ``shutdown`` event, and its
|
||||
implementation is a simple ``mp.keep_running = false``.
|
||||
@@ -1,75 +0,0 @@
|
||||
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
|
||||
|
||||
C PLUGINS
|
||||
=========
|
||||
|
||||
You can write C plugins for mpv. These use the libmpv API, although they do not
|
||||
use the libmpv library itself.
|
||||
|
||||
Currently, they must be explicitly enabled at build time with
|
||||
``--enable-cplugins``. They are available on Linux/BSD platforms only.
|
||||
|
||||
C plugins location
|
||||
------------------
|
||||
|
||||
C plugins are put into the mpv scripts directory in its config directory
|
||||
(see the `FILES`_ section for details). They must have a ``.so`` file extension.
|
||||
They can also be explicitly loaded with the ``--script`` option.
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
A C plugin must export the following function::
|
||||
|
||||
int mpv_open_cplugin(mpv_handle *handle)
|
||||
|
||||
The plugin function will be called on loading time. This function does not
|
||||
return as long as your plugin is loaded (it runs in its own thread). The
|
||||
``handle`` will be deallocated as soon as the plugin function returns.
|
||||
|
||||
The return value is interpreted as error status. A value of ``0`` is
|
||||
interpreted as success, while ``-1`` signals an error. In the latter case,
|
||||
the player prints an uninformative error message that loading failed.
|
||||
|
||||
Return values other than ``0`` and ``-1`` are reserved, and trigger undefined
|
||||
behavior.
|
||||
|
||||
Within the plugin function, you can call libmpv API functions. The ``handle``
|
||||
is created by ``mpv_create_client()`` (or actually an internal equivalent),
|
||||
and belongs to you. You can call ``mpv_wait_event()`` to wait for things
|
||||
happening, and so on.
|
||||
|
||||
Note that the player might block until your plugin calls ``mpv_wait_event()``
|
||||
for the first time. This gives you a chance to install initial hooks etc.
|
||||
before playback begins.
|
||||
|
||||
The details are quite similar to Lua scripts.
|
||||
|
||||
Linkage to libmpv
|
||||
-----------------
|
||||
|
||||
The current implementation requires that your plugins are **not** linked against
|
||||
libmpv. What your plugins uses are not symbols from a libmpv binary, but
|
||||
symbols from the mpv host binary.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
See:
|
||||
|
||||
- https://github.com/mpv-player/mpv-examples/tree/master/cplugins
|
||||
+76
-209
@@ -39,15 +39,13 @@ option. Some scripts are loaded internally (like ``--osc``). Each script runs in
|
||||
its own thread. Your script is first run "as is", and once that is done, the event loop
|
||||
is entered. This event loop will dispatch events received by mpv and call your
|
||||
own event handlers which you have registered with ``mp.register_event``, or
|
||||
timers added with ``mp.add_timeout`` or similar. Note that since the
|
||||
script starts execution concurrently with player initialization, some properties
|
||||
may not be populated with meaningful values until the relevant subsystems have
|
||||
initialized.
|
||||
timers added with ``mp.add_timeout`` or similar.
|
||||
|
||||
When the player quits, all scripts will be asked to terminate. This happens via
|
||||
a ``shutdown`` event, which by default will make the event loop return. If your
|
||||
script got into an endless loop, mpv will probably behave fine during playback,
|
||||
but it won't terminate when quitting, because it's waiting on your script.
|
||||
script got into an endless loop, mpv will probably behave fine during playback
|
||||
(unless the player is suspended, see ``mp.suspend``), but it won't terminate
|
||||
when quitting, because it's waiting on your script.
|
||||
|
||||
Internally, the C code will call the Lua function ``mp_event_loop`` after
|
||||
loading a Lua script. This function is normally defined by the default prelude
|
||||
@@ -63,10 +61,7 @@ the player will more or less hang until the script returns from the main chunk
|
||||
(and ``mp_event_loop`` is called), or the script calls ``mp_event_loop`` or
|
||||
``mp.dispatch_events`` directly. This is done to make it possible for a script
|
||||
to fully setup event handlers etc. before playback actually starts. In older
|
||||
mpv versions, this happened asynchronously. With mpv 0.29.0, this changes
|
||||
slightly, and it merely waits for scripts to be loaded in this manner before
|
||||
starting playback as part of the player initialization phase. Scripts run though
|
||||
initialization in parallel. This might change again.
|
||||
mpv versions, this happened asynchronously.
|
||||
|
||||
mp functions
|
||||
------------
|
||||
@@ -78,10 +73,6 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
Run the given command. This is similar to the commands used in input.conf.
|
||||
See `List of Input Commands`_.
|
||||
|
||||
By default, this will show something on the OSD (depending on the command),
|
||||
as if it was used in ``input.conf``. See `Input Command Prefixes`_ how
|
||||
to influence OSD usage per command.
|
||||
|
||||
Returns ``true`` on success, or ``nil, error`` on error.
|
||||
|
||||
``mp.commandv(arg1, arg2, ...)``
|
||||
@@ -103,49 +94,15 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
the ``expand-properties`` prefix, or the ``mp.get_property`` family of
|
||||
functions.
|
||||
|
||||
Unlike ``mp.command``, this will not use OSD by default either (except
|
||||
for some OSD-specific commands).
|
||||
|
||||
``mp.command_native(table [,def])``
|
||||
Similar to ``mp.commandv``, but pass the argument list as table. This has
|
||||
the advantage that in at least some cases, arguments can be passed as
|
||||
native types. It also allows you to use named argument.
|
||||
|
||||
If the table is an array, each array item is like an argument in
|
||||
``mp.commandv()`` (but can be a native type instead of a string).
|
||||
|
||||
If the table contains string keys, it's interpreted as command with named
|
||||
arguments. This requires at least an entry with the key ``name`` to be
|
||||
present, which must be a string, and contains the command name. The special
|
||||
entry ``_flags`` is optional, and if present, must be an array of
|
||||
`Input Command Prefixes`_ to apply. All other entries are interpreted as
|
||||
arguments.
|
||||
native types.
|
||||
|
||||
Returns a result table on success (usually empty), or ``def, error`` on
|
||||
error. ``def`` is the second parameter provided to the function, and is
|
||||
nil if it's missing.
|
||||
|
||||
``mp.command_native_async(table [,fn])``
|
||||
Like ``mp.command_native()``, but the command is ran asynchronously (as far
|
||||
as possible), and upon completion, fn is called. fn has two arguments:
|
||||
``fn(success, result, error)``. ``success`` is always a Boolean and is true
|
||||
if the command was successful, otherwise false. The second parameter is
|
||||
the result value (can be nil) in case of success, nil otherwise (as returned
|
||||
by ``mp.command_native()``). The third parameter is the error string in case
|
||||
of an error, nil otherwise.
|
||||
|
||||
Returns a table with undefined contents, which can be used as argument for
|
||||
``mp.abort_async_command``.
|
||||
|
||||
If starting the command failed for some reason, ``nil, error`` is returned,
|
||||
and ``fn`` is called indicating failure, using the same error value.
|
||||
|
||||
``mp.abort_async_command(t)``
|
||||
Abort a ``mp.command_native_async`` call. The argument is the return value
|
||||
of that command (which starts asynchronous execution of the command).
|
||||
Whether this works and how long it takes depends on the command and the
|
||||
situation. The abort call itself is asynchronous. Does not return anything.
|
||||
|
||||
``mp.get_property(name [,def])``
|
||||
Return the value of the given property as string. These are the same
|
||||
properties as used in input.conf. See `Properties`_ for a list of
|
||||
@@ -211,7 +168,7 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
Similar to ``mp.set_property``, but set the given property using its native
|
||||
type.
|
||||
|
||||
Since there are several data types which cannot represented natively in
|
||||
Since there are several data types which can not represented natively in
|
||||
Lua, this might not always work as expected. For example, while the Lua
|
||||
wrapper can do some guesswork to decide whether a Lua table is an array
|
||||
or a map, this would fail with empty tables. Also, there are not many
|
||||
@@ -228,14 +185,13 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
Register callback to be run on a key binding. The binding will be mapped to
|
||||
the given ``key``, which is a string describing the physical key. This uses
|
||||
the same key names as in input.conf, and also allows combinations
|
||||
(e.g. ``ctrl+a``). If the key is empty or ``nil``, no physical key is
|
||||
registered, but the user still can create own bindings (see below).
|
||||
(e.g. ``ctrl+a``).
|
||||
|
||||
After calling this function, key presses will cause the function ``fn`` to
|
||||
be called (unless the user remapped the key with another binding).
|
||||
|
||||
The ``name`` argument should be a short symbolic string. It allows the user
|
||||
to remap the key binding via input.conf using the ``script-message``
|
||||
to remap the key binding via input.conf using the ``script_message``
|
||||
command, and the name of the key binding (see below for
|
||||
an example). The name should be unique across other bindings in the same
|
||||
script - if not, the previous binding with the same name will be
|
||||
@@ -257,8 +213,8 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
has an ``is_mouse`` entry, which tells whether the event was caused
|
||||
by a mouse button.
|
||||
|
||||
Internally, key bindings are dispatched via the ``script-message-to`` or
|
||||
``script-binding`` input commands and ``mp.register_script_message``.
|
||||
Internally, key bindings are dispatched via the ``script_message_to`` or
|
||||
``script_binding`` input commands and ``mp.register_script_message``.
|
||||
|
||||
Trying to map multiple commands to a key will essentially prefer a random
|
||||
binding, while the other bindings are not called. It is guaranteed that
|
||||
@@ -277,11 +233,11 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
This will print the message ``the key was pressed`` when ``x`` was pressed.
|
||||
|
||||
The user can remap these key bindings. Then the user has to put the
|
||||
following into their input.conf to remap the command to the ``y`` key:
|
||||
following into his input.conf to remap the command to the ``y`` key:
|
||||
|
||||
::
|
||||
|
||||
y script-binding something
|
||||
y script_binding something
|
||||
|
||||
|
||||
This will print the message when the key ``y`` is pressed. (``x`` will
|
||||
@@ -292,11 +248,11 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
|
||||
::
|
||||
|
||||
y script-binding fooscript/something
|
||||
y script_binding fooscript.something
|
||||
|
||||
``mp.add_forced_key_binding(...)``
|
||||
This works almost the same as ``mp.add_key_binding``, but registers the
|
||||
key binding in a way that will overwrite the user's custom bindings in their
|
||||
key binding in a way that will overwrite the user's custom bindings in his
|
||||
input.conf. (``mp.add_key_binding`` overwrites default key bindings only,
|
||||
but not those by the user's input.conf.)
|
||||
|
||||
@@ -344,16 +300,12 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
exact behavior depends on timing and other things.)
|
||||
|
||||
In some cases the function is not called even if the property changes.
|
||||
This depends on the property, and it's a valid feature request to ask for
|
||||
better update handling of a specific property.
|
||||
Whether this can happen depends on the property.
|
||||
|
||||
If the ``type`` is ``none`` or ``nil``, sporadic property change events are
|
||||
possible. This means the change function ``fn`` can be called even if the
|
||||
property doesn't actually change.
|
||||
|
||||
You always get an initial change notification. This is meant to initialize
|
||||
the user's state to the current value of the property.
|
||||
|
||||
``mp.unobserve_property(fn)``
|
||||
Undo ``mp.observe_property(..., fn)``. This removes all property handlers
|
||||
that are equal to the ``fn`` parameter. This uses normal Lua ``==``
|
||||
@@ -374,6 +326,7 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
the timer is re-added after the function fn is run.
|
||||
|
||||
Returns a timer object. The timer object provides the following methods:
|
||||
|
||||
``stop()``
|
||||
Disable the timer. Does nothing if the timer is already disabled.
|
||||
This will remember the current elapsed time when stopping, so that
|
||||
@@ -390,10 +343,6 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
with ``add_timeout()``), this starts the timer from the beginning,
|
||||
using the initially configured timeout.
|
||||
|
||||
``is_enabled()``
|
||||
Whether the timer is currently enabled or was previously disabled
|
||||
(e.g. by ``stop()`` or ``kill()``).
|
||||
|
||||
``timeout`` (RW)
|
||||
This field contains the current timeout period. This value is not
|
||||
updated as time progresses. It's only used to calculate when the
|
||||
@@ -408,23 +357,6 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
(``true``). This value is used when the timer expires (but before
|
||||
the timer callback function fn is run).
|
||||
|
||||
Note that these are methods, and you have to call them using ``:`` instead
|
||||
of ``.`` (Refer to http://www.lua.org/manual/5.2/manual.html#3.4.9 .)
|
||||
|
||||
Example:
|
||||
|
||||
::
|
||||
|
||||
seconds = 0
|
||||
timer = mp.add_periodic_timer(1, function()
|
||||
print("called every second")
|
||||
# stop it after 10 seconds
|
||||
seconds = seconds + 1
|
||||
if seconds >= 10 then
|
||||
timer:kill()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
``mp.get_opt(key)``
|
||||
Return a setting from the ``--script-opts`` option. It's up to the user and
|
||||
@@ -434,7 +366,7 @@ The ``mp`` module is preloaded, although it can be loaded manually with
|
||||
``mp.get_script_name()``
|
||||
Return the name of the current script. The name is usually made of the
|
||||
filename of the script, with directory and file extension removed. If
|
||||
there are several scripts which would have the same name, it's made unique
|
||||
there are several script which would have the same name, it's made unique
|
||||
by appending a number.
|
||||
|
||||
.. admonition:: Example
|
||||
@@ -452,20 +384,29 @@ 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 and does nothing starting
|
||||
with mpv 0.23.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
|
||||
trying to access the player.
|
||||
|
||||
This is automatically called by the event handler.
|
||||
|
||||
``mp.resume()``
|
||||
This function has been deprecated in mpv 0.21.0 and does nothing starting
|
||||
with mpv 0.23.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 and does nothing starting
|
||||
with mpv 0.23.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.)
|
||||
|
||||
You might want to call this if you're about to do something that takes a
|
||||
long time, but doesn't really need access to the player (like a network
|
||||
operation). Note that you still can access the player at any time.
|
||||
|
||||
``mp.get_wakeup_pipe()``
|
||||
Calls ``mpv_get_wakeup_pipe()`` and returns the read end of the wakeup
|
||||
pipe. This is deprecated, but still works. (See ``client.h`` for details.)
|
||||
pipe. (See ``client.h`` for details.)
|
||||
|
||||
``mp.get_next_timeout()``
|
||||
Return the relative time in seconds when the next timer (``mp.add_timeout``
|
||||
@@ -485,17 +426,7 @@ 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.unregister_idle(fn)``
|
||||
Undo ``mp.register_idle(fn)``. This removes all idle handlers that
|
||||
are equal to the ``fn`` parameter. This uses normal Lua ``==`` comparison,
|
||||
so be careful when dealing with closures.
|
||||
This function calls ``mp.suspend()`` and ``mp.resume_all()`` on its own.
|
||||
|
||||
``mp.enable_messages(level)``
|
||||
Set the minimum log level of which mpv message output to receive. These
|
||||
@@ -505,9 +436,9 @@ are useful only in special situations.
|
||||
The level is a string, see ``msg.log`` for allowed log levels.
|
||||
|
||||
``mp.register_script_message(name, fn)``
|
||||
This is a helper to dispatch ``script-message`` or ``script-message-to``
|
||||
invocations to Lua functions. ``fn`` is called if ``script-message`` or
|
||||
``script-message-to`` (with this script as destination) is run
|
||||
This is a helper to dispatch ``script_message`` or ``script_message_to``
|
||||
invocations to Lua functions. ``fn`` is called if ``script_message`` or
|
||||
``script_message_to`` (with this script as destination) is run
|
||||
with ``name`` as first parameter. The other parameters are passed to ``fn``.
|
||||
If a message with the given name is already registered, it's overwritten.
|
||||
|
||||
@@ -525,17 +456,16 @@ with ``require 'mp.msg'``.
|
||||
|
||||
``msg.log(level, ...)``
|
||||
The level parameter is the message priority. It's a string and one of
|
||||
``fatal``, ``error``, ``warn``, ``info``, ``v``, ``debug``, ``trace``. The
|
||||
user's settings will determine which of these messages will be
|
||||
visible. Normally, all messages are visible, except ``v``, ``debug`` and
|
||||
``trace``.
|
||||
``fatal``, ``error``, ``warn``, ``info``, ``v``, ``debug``. The user's
|
||||
settings will determine which of these messages will be visible. Normally,
|
||||
all messages are visible, except ``v`` and ``debug``.
|
||||
|
||||
The parameters after that are all converted to strings. Spaces are inserted
|
||||
to separate multiple parameters.
|
||||
|
||||
You don't need to add newlines.
|
||||
|
||||
``msg.fatal(...)``, ``msg.error(...)``, ``msg.warn(...)``, ``msg.info(...)``, ``msg.verbose(...)``, ``msg.debug(...)``, ``msg.trace(...)``
|
||||
``msg.fatal(...)``, ``msg.error(...)``, ``msg.warn(...)``, ``msg.info(...)``, ``msg.verbose(...)``, ``msg.debug(...)``
|
||||
All of these are shortcuts and equivalent to the corresponding
|
||||
``msg.log(level, ...)`` call.
|
||||
|
||||
@@ -566,10 +496,10 @@ Example implementation::
|
||||
optionC = true,
|
||||
}
|
||||
read_options(options, "myscript")
|
||||
print(options.optionA)
|
||||
print(option.optionA)
|
||||
|
||||
|
||||
The config file will be stored in ``script-opts/identifier.conf`` in mpv's user
|
||||
The config file will be stored in ``lua-settings/identifier.conf`` in mpv's user
|
||||
folder. Comment lines can be started with # and stray spaces are not removed.
|
||||
Boolean values will be represented with yes/no.
|
||||
|
||||
@@ -589,8 +519,8 @@ Example command-line::
|
||||
--script-opts=myscript-optionA=TEST,myscript-optionB=0,myscript-optionC=yes
|
||||
|
||||
|
||||
mp.utils functions
|
||||
------------------
|
||||
mp.utils options
|
||||
----------------
|
||||
|
||||
This built-in module provides generic helper functions for Lua, and have
|
||||
strictly speaking nothing to do with mpv or video/audio playback. They are
|
||||
@@ -630,34 +560,6 @@ strictly part of the guaranteed API.
|
||||
|
||||
On error, ``nil, error`` is returned.
|
||||
|
||||
``utils.file_info(path)``
|
||||
Stats the given path for information and returns a table with the
|
||||
following entries:
|
||||
|
||||
``mode``
|
||||
protection bits (on Windows, always 755 (octal) for directories
|
||||
and 644 (octal) for files)
|
||||
``size``
|
||||
size in bytes
|
||||
``atime``
|
||||
time of last access
|
||||
``mtime``
|
||||
time of last modification
|
||||
``ctime``
|
||||
time of last metadata change (Linux) / time of creation (Windows)
|
||||
``is_file``
|
||||
Whether ``path`` is a regular file (boolean)
|
||||
``is_dir``
|
||||
Whether ``path`` is a directory (boolean)
|
||||
|
||||
``mode`` and ``size`` are integers.
|
||||
Timestamps (``atime``, ``mtime`` and ``ctime``) are integer seconds since
|
||||
the Unix epoch (Unix time).
|
||||
The booleans ``is_file`` and ``is_dir`` are provided as a convenience;
|
||||
they can be and are derived from ``mode``.
|
||||
|
||||
On error (eg. path does not exist), ``nil, error`` is returned.
|
||||
|
||||
``utils.split_path(path)``
|
||||
Split a path into directory component and filename component, and return
|
||||
them. The first return value is always the directory. The second return
|
||||
@@ -669,43 +571,43 @@ strictly part of the guaranteed API.
|
||||
|
||||
``utils.subprocess(t)``
|
||||
Runs an external process and waits until it exits. Returns process status
|
||||
and the captured output. This is a legacy wrapper around calling the
|
||||
``subprocess`` command with ``mp.command_native``. It does the following
|
||||
things:
|
||||
|
||||
- copy the table ``t``
|
||||
- rename ``cancellable`` field to ``playback_only``
|
||||
- rename ``max_size`` to ``capture_size``
|
||||
- set ``capture_stdout`` field to ``true`` if unset
|
||||
- set ``name`` field to ``subprocess``
|
||||
- call ``mp.command_native(copied_t)``
|
||||
- if the command failed, create a dummy result table
|
||||
- copy ``error_string`` to ``error`` field if the string is non-empty
|
||||
- return the result table
|
||||
|
||||
It is recommended to use ``mp.command_native`` or ``mp.command_native_async``
|
||||
directly, instead of calling this legacy wrapper. It is for compatibility
|
||||
only.
|
||||
|
||||
See the ``subprocess`` documentation for semantics and further parameters.
|
||||
|
||||
``utils.subprocess_detached(t)``
|
||||
Runs an external process and detaches it from mpv's control.
|
||||
and the captured output.
|
||||
|
||||
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.
|
||||
Array of strings. The first array entry is the executable. This
|
||||
can be either an absolute path, or a filename with no path
|
||||
components, in which case the ``PATH`` environment variable is
|
||||
used to resolve the executable. The other array elements are
|
||||
passed as command line arguments.
|
||||
|
||||
The function returns ``nil``.
|
||||
``cancellable``
|
||||
Optional. If set to ``true`` (default), then if the user stops
|
||||
playback or goes to the next file while the process is running,
|
||||
the process will be killed.
|
||||
|
||||
This is a legacy wrapper around calling the ``run`` command with
|
||||
``mp.commandv`` and other functions.
|
||||
``max_size``
|
||||
Optional. The maximum size in bytes of the data that can be captured
|
||||
from stdout. (Default: 16 MB.)
|
||||
|
||||
``utils.getpid()``
|
||||
Returns the process ID of the running mpv process. This can be used to identify
|
||||
the calling mpv when launching (detached) subprocesses.
|
||||
The function returns a table as result with the following entries:
|
||||
|
||||
``status``
|
||||
The raw exit status of the process. It will be negative on error.
|
||||
|
||||
``stdout``
|
||||
Captured output stream as string, limited to ``max_size``.
|
||||
|
||||
``error``
|
||||
``nil`` on success. The string ``killed`` if the process was
|
||||
terminated in an unusual way. The string ``init`` if the process
|
||||
could not be started.
|
||||
|
||||
On Windows, ``killed`` is only returned when the process has been
|
||||
killed by mpv as a result of ``cancellable`` being set to ``true``.
|
||||
|
||||
In all cases, ``mp.resume_all()`` is implicitly called.
|
||||
|
||||
``utils.parse_json(str [, trail])``
|
||||
Parses the given string argument as JSON, and returns it as a Lua table. On
|
||||
@@ -721,14 +623,6 @@ strictly part of the guaranteed API.
|
||||
trailing text is returned as 3rd return value. (The 3rd return value is
|
||||
always there, but with ``trail`` set, no error is raised.)
|
||||
|
||||
``utils.format_json(v)``
|
||||
Format the given Lua table (or value) as a JSON string and return it. On
|
||||
error, returns ``nil, error``. (Errors usually only happen on value types
|
||||
incompatible with JSON.)
|
||||
|
||||
The argument value uses similar conventions as ``mp.set_property_native()``
|
||||
to distinguish empty objects and arrays.
|
||||
|
||||
``utils.to_string(v)``
|
||||
Turn the given value into a string. Formats tables and their contents. This
|
||||
doesn't do anything special; it is only needed because Lua is terrible.
|
||||
@@ -765,33 +659,6 @@ List of events
|
||||
Happens after a file was unloaded. Typically, the player will load the
|
||||
next file right away, or quit if this was the last file.
|
||||
|
||||
The event has the ``reason`` field, which takes one of these values:
|
||||
|
||||
``eof``
|
||||
The file has ended. This can (but doesn't have to) include
|
||||
incomplete files or broken network connections under
|
||||
circumstances.
|
||||
|
||||
``stop``
|
||||
Playback was ended by a command.
|
||||
|
||||
``quit``
|
||||
Playback was ended by sending the quit command.
|
||||
|
||||
``error``
|
||||
An error happened. In this case, an ``error`` field is present with
|
||||
the error string.
|
||||
|
||||
``redirect``
|
||||
Happens with playlists and similar. Details see
|
||||
``MPV_END_FILE_REASON_REDIRECT`` in the C API.
|
||||
|
||||
``unknown``
|
||||
Unknown. Normally doesn't happen, unless the Lua API is out of sync
|
||||
with the C API. (Likewise, it could happen that your script gets
|
||||
reason strings that did not exist yet at the time your script was
|
||||
written.)
|
||||
|
||||
``file-loaded``
|
||||
Happens after a file was loaded and begins playback.
|
||||
|
||||
|
||||
+160
-498
File diff suppressed because it is too large.
Load diff
+1045
-3776
File diff suppressed because it is too large.
Load diff
+122
-230
@@ -5,7 +5,7 @@ The On Screen Controller (short: OSC) is a minimal GUI integrated with mpv to
|
||||
offer basic mouse-controllability. It is intended to make interaction easier
|
||||
for new users and to enable precise and direct seeking.
|
||||
|
||||
The OSC is enabled by default if mpv was compiled with Lua support. It can be
|
||||
The OSC is enabled by default if mpv was compiled with lua support. It can be
|
||||
disabled entirely using the ``--osc=no`` option.
|
||||
|
||||
Using the OSC
|
||||
@@ -20,77 +20,37 @@ The Interface
|
||||
|
||||
::
|
||||
|
||||
+---------+----------+------------------------------------------+----------+
|
||||
| pl prev | pl next | title | cache |
|
||||
+------+--+---+------+---------+-----------+------+-------+-----+-----+----+
|
||||
| play | skip | skip | time | seekbar | time | audio | sub | vol | fs |
|
||||
| | back | frwd | elapsed | | left | | | | |
|
||||
+------+------+------+---------+-----------+------+-------+-----+-----+----+
|
||||
+------------------+-----------+--------------------+
|
||||
| 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
|
||||
playlist 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
|
||||
============= ================================================
|
||||
|
||||
title
|
||||
| Displays current media-title, filename, or custom title
|
||||
| Displays current media-title or filename
|
||||
|
||||
============= ================================================
|
||||
left-click show playlist position and length and full title
|
||||
right-click show filename
|
||||
============= ================================================
|
||||
|
||||
cache
|
||||
| Shows current cache fill status
|
||||
|
||||
play
|
||||
playlist next
|
||||
============= ================================================
|
||||
left-click toggle play/pause
|
||||
============= ================================================
|
||||
|
||||
skip back
|
||||
============= ================================================
|
||||
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
|
||||
============= ================================================
|
||||
|
||||
time elapsed
|
||||
| Shows current playback position timestamp
|
||||
|
||||
============= ================================================
|
||||
left-click toggle displaying timecodes with milliseconds
|
||||
============= ================================================
|
||||
|
||||
seekbar
|
||||
| Indicates current playback position and position of chapters
|
||||
|
||||
============= ================================================
|
||||
left-click seek to position
|
||||
============= ================================================
|
||||
|
||||
time left
|
||||
| Shows remaining playback time timestamp
|
||||
|
||||
============= ================================================
|
||||
left-click toggle between total and remaining time
|
||||
left-click play next file in playlist
|
||||
shift+L-click show playlist
|
||||
============= ================================================
|
||||
|
||||
audio and sub
|
||||
@@ -102,17 +62,66 @@ audio and sub
|
||||
shift+L-click show available audio/sub tracks
|
||||
============= ================================================
|
||||
|
||||
vol
|
||||
skip back
|
||||
============= ================================================
|
||||
left-click toggle mute
|
||||
mouse wheel volume up/down
|
||||
left-click go to beginning of chapter / previous chapter
|
||||
shift+L-click show chapters
|
||||
============= ================================================
|
||||
|
||||
fs
|
||||
seek back
|
||||
============= ================================================
|
||||
left-click skip back 5 seconds
|
||||
right-click skip back 30 seconds
|
||||
shift-L-click skip back 1 frame
|
||||
============= ================================================
|
||||
|
||||
play
|
||||
============= ================================================
|
||||
left-click toggle play/pause
|
||||
============= ================================================
|
||||
|
||||
seek frwd
|
||||
============= ================================================
|
||||
left-click skip forward 10 seconds
|
||||
right-click skip forward 60 seconds
|
||||
shift-L-click skip forward 1 frame
|
||||
============= ================================================
|
||||
|
||||
skip frwd
|
||||
============= ================================================
|
||||
left-click go to next chapter
|
||||
shift+L-click show chapters
|
||||
============= ================================================
|
||||
|
||||
fullscreen
|
||||
============= ================================================
|
||||
left-click toggle fullscreen
|
||||
============= ================================================
|
||||
|
||||
seekbar
|
||||
| Indicates current playback position and position of chapters
|
||||
|
||||
============= ================================================
|
||||
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
|
||||
| Shows remaining playback time timestamp
|
||||
|
||||
============= ================================================
|
||||
left-click toggle between total and remaining time
|
||||
============= ================================================
|
||||
|
||||
Key Bindings
|
||||
~~~~~~~~~~~~
|
||||
|
||||
@@ -121,14 +130,14 @@ these keys. In case of collision, the function needs to be bound to a
|
||||
different key. See the `Script Commands`_ section.
|
||||
|
||||
============= ================================================
|
||||
del Cycles visibility between never / auto (mouse-move) / always
|
||||
del Hide the OSC permanently until mpv is restarted.
|
||||
============= ================================================
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The OSC offers limited configuration through a config file
|
||||
``script-opts/osc.conf`` placed in mpv's user dir and through the
|
||||
``lua-settings/osc.conf`` placed in mpv's user dir and through the
|
||||
``--script-opts`` command-line option. Options provided through the command-line
|
||||
will override those from the config file.
|
||||
|
||||
@@ -158,188 +167,72 @@ Example::
|
||||
Configurable Options
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``layout``
|
||||
Default: bottombar
|
||||
|
||||
The layout for the OSC. Currently available are: box, slimbox,
|
||||
bottombar and topbar. Default pre-0.21.0 was 'box'.
|
||||
|
||||
``seekbarstyle``
|
||||
Default: bar
|
||||
|
||||
Sets the style of the playback position marker and overall shape
|
||||
of the seekbar: ``bar``, ``diamond`` or ``knob``.
|
||||
|
||||
``seekbarhandlesize``
|
||||
Default: 0.6
|
||||
|
||||
Size ratio of the seek handle if ``seekbarstyle`` is set to ``dimaond``
|
||||
or ``knob``. This is relative to the full height of the seekbar.
|
||||
|
||||
``seekbarkeyframes``
|
||||
Default: yes
|
||||
|
||||
Controls the mode used to seek when dragging the seekbar. By default,
|
||||
keyframes are used. If set to false, exact seeking on mouse drags
|
||||
will be used instead. Keyframes are preferred, but exact seeks may be
|
||||
useful in cases where keyframes cannot be found. Note that using exact
|
||||
seeks can potentially make mouse dragging much slower.
|
||||
|
||||
``seekrangestyle``
|
||||
Default: inverted
|
||||
|
||||
Display seekable ranges on the seekbar. ``bar`` shows them on the full
|
||||
height of the bar, ``line`` as a thick line and ``inverted`` as a thin
|
||||
line that is inverted over playback position markers. ``none`` will hide
|
||||
them. Additionally, ``slider`` will show a permanent handle inside the seekbar
|
||||
with cached ranges marked inside. Note that these will look differently
|
||||
based on the seekbarstyle option. Also, ``slider`` does not work with
|
||||
``seekbarstyle`` set to ``bar``.
|
||||
|
||||
``seekrangeseparate``
|
||||
Default: yes
|
||||
|
||||
Controls whether to show line-style seekable ranges on top of the
|
||||
seekbar or separately if ``seekbarstyle`` is set to ``bar``.
|
||||
|
||||
``seekrangealpha``
|
||||
Default: 200
|
||||
|
||||
Alpha of the seekable ranges, 0 (opaque) to 255 (fully transparent).
|
||||
|
||||
``deadzonesize``
|
||||
Default: 0.5
|
||||
|
||||
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.0 and 1.0, 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. Default pre-0.21.0 was 0.
|
||||
|
||||
``minmousemove``
|
||||
Default: 0
|
||||
|
||||
Minimum amount of pixels the mouse has to move between ticks to make
|
||||
the OSC show up. Default pre-0.21.0 was 3.
|
||||
|
||||
``showwindowed``
|
||||
Default: yes
|
||||
|
||||
Enable the OSC when windowed
|
||||
| Default: yes
|
||||
| Show OSC when windowed?
|
||||
|
||||
``showfullscreen``
|
||||
Default: yes
|
||||
|
||||
Enable the OSC when fullscreen
|
||||
| Default: yes
|
||||
| Show OSC when fullscreen?
|
||||
|
||||
``scalewindowed``
|
||||
Default: 1.0
|
||||
|
||||
Scale factor of the OSC when windowed.
|
||||
| Default: 1
|
||||
| Scaling of the controller when windowed
|
||||
|
||||
``scalefullscreen``
|
||||
Default: 1.0
|
||||
|
||||
Scale factor of the OSC when fullscreen
|
||||
| Default: 1
|
||||
| Scaling of the controller when fullscreen
|
||||
|
||||
``scaleforcedwindow``
|
||||
Default: 2.0
|
||||
|
||||
Scale factor of the OSC when rendered on a forced (dummy) window
|
||||
| Default: 2
|
||||
| Scaling of the controller when rendered on a forced (dummy) window
|
||||
|
||||
``vidscale``
|
||||
Default: yes
|
||||
|
||||
Scale the OSC with the video
|
||||
``no`` tries to keep the OSC size constant as much as the window size allows
|
||||
| Default: yes
|
||||
| Scale the controller with the video?
|
||||
|
||||
``valign``
|
||||
Default: 0.8
|
||||
|
||||
Vertical alignment, -1 (top) to 1 (bottom)
|
||||
| Default: 0.8
|
||||
| Vertical alignment, -1 (top) to 1 (bottom)
|
||||
|
||||
``halign``
|
||||
Default: 0.0
|
||||
|
||||
Horizontal alignment, -1 (left) to 1 (right)
|
||||
|
||||
``barmargin``
|
||||
Default: 0
|
||||
|
||||
Margin from bottom (bottombar) or top (topbar), in pixels
|
||||
| Default: 0
|
||||
| Horizontal alignment, -1 (left) to 1 (right)
|
||||
|
||||
``boxalpha``
|
||||
Default: 80
|
||||
|
||||
Alpha of the background box, 0 (opaque) to 255 (fully transparent)
|
||||
| Default: 80
|
||||
| Alpha of the background box, 0 (opaque) to 255 (fully transparent)
|
||||
|
||||
``hidetimeout``
|
||||
Default: 500
|
||||
|
||||
Duration in ms until the OSC hides if no mouse movement, must not be
|
||||
negative
|
||||
| Default: 500
|
||||
| Duration in ms until the OSC hides if no mouse movement, negative value
|
||||
disables auto-hide
|
||||
|
||||
``fadeduration``
|
||||
Default: 200
|
||||
| Default: 200
|
||||
| Duration of fade out in ms, 0 = no fade
|
||||
|
||||
Duration of fade out in ms, 0 = no fade
|
||||
``deadzonesize``
|
||||
| Default: 0
|
||||
| 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.
|
||||
|
||||
``title``
|
||||
Default: ${media-title}
|
||||
``minmousemove``
|
||||
| Default: 3
|
||||
| Minimum amount of pixels the mouse has to move between ticks to make
|
||||
the OSC show up
|
||||
|
||||
String that supports property expansion that will be displayed as
|
||||
OSC title.
|
||||
ASS tags are escaped, and newlines and trailing slashes are stripped.
|
||||
``layout``
|
||||
| Default: box
|
||||
| The layout for the OSC. Currently available are: box, slimbox,
|
||||
bottombar and topbar.
|
||||
|
||||
``tooltipborder``
|
||||
Default: 1
|
||||
|
||||
Size of the tooltip outline when using bottombar or topbar layouts
|
||||
|
||||
``timetotal``
|
||||
Default: no
|
||||
|
||||
Show total time instead of time remaining
|
||||
|
||||
``timems``
|
||||
Default: no
|
||||
|
||||
Display timecodes with milliseconds
|
||||
|
||||
``visibility``
|
||||
Default: auto (auto hide/show on mouse move)
|
||||
|
||||
Also supports ``never`` and ``always``
|
||||
|
||||
``boxmaxchars``
|
||||
Default: 80
|
||||
|
||||
Max chars for the osc title at the box layout. mpv does not measure the
|
||||
text width on screen and so it needs to limit it by number of chars. The
|
||||
default is conservative to allow wide fonts to be used without overflow.
|
||||
However, with many common fonts a bigger number can be used. YMMV.
|
||||
|
||||
``boxvideo``
|
||||
Default: no
|
||||
|
||||
Whether to overlay the osc over the video (``no``), or to box the video
|
||||
within the areas not covered by the osc (``yes``). If this option is set,
|
||||
the osc may overwrite the ``--video-margin-ratio-*`` options, even if the
|
||||
user has set them. (It will not overwrite them if all of them are set to
|
||||
default values.)
|
||||
|
||||
Currently, this is supported for the ``bottombar`` layout only. The other
|
||||
layouts do not change if this option is set.
|
||||
|
||||
The border is static and appears even if the OSC is configured to appear
|
||||
only on mouse interaction. If the OSC is invisible, the border is simply
|
||||
filled with the background color (black by default).
|
||||
|
||||
This currently still makes the OSC overlap with subtitles (if the
|
||||
``--sub-use-margins`` option is set to ``yes``, the default). This may be
|
||||
fixed later.
|
||||
``seekbarstyle``
|
||||
| Default: slider
|
||||
| Sets the style of the seekbar, slider (diamond marker) or bar (fill)
|
||||
|
||||
Script Commands
|
||||
~~~~~~~~~~~~~~~
|
||||
@@ -347,23 +240,22 @@ Script Commands
|
||||
The OSC script listens to certain script commands. These commands can bound
|
||||
in ``input.conf``, or sent by other scripts.
|
||||
|
||||
``enable-osc``
|
||||
Undoes ``disable-osc`` or the effect of the ``del`` key.
|
||||
|
||||
``disable-osc``
|
||||
Hide the OSC permanently. This is also what the ``del`` key does.
|
||||
|
||||
``osc-message``
|
||||
Show a message on screen using the OSC. First argument is the message,
|
||||
second the duration in seconds.
|
||||
|
||||
``osc-visibility``
|
||||
Controls visibility mode ``never`` / ``auto`` (on mouse move) / ``always``
|
||||
and also ``cycle`` to cycle between the modes
|
||||
|
||||
Example
|
||||
|
||||
You could put this into ``input.conf`` to hide the OSC with the ``a`` key and
|
||||
to set auto mode (the default) with ``b``::
|
||||
to unhide it with ``b``::
|
||||
|
||||
a script-message osc-visibility never
|
||||
b script-message osc-visibility auto
|
||||
|
||||
``osc-playlist``, ``osc-chapterlist``, ``osc-tracklist``
|
||||
Shows a limited view of the respective type of list using the OSC. First
|
||||
argument is duration in seconds.
|
||||
a script_message disable-osc
|
||||
b script_message enable-osc
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
STATS
|
||||
=====
|
||||
|
||||
This builtin script displays information and statistics for the currently
|
||||
played file. It is enabled by default if mpv was compiled with Lua support.
|
||||
It can be disabled entirely using the ``--load-stats-overlay=no`` option.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The following key bindings are active by default unless something else is
|
||||
already bound to them:
|
||||
|
||||
==== ==============================================
|
||||
i Show stats for a fixed duration
|
||||
I Toggle stats (shown until toggled again)
|
||||
==== ==============================================
|
||||
|
||||
While the stats are visible on screen the following key bindings are active,
|
||||
regardless of existing bindings. They allow you to switch between *pages* of
|
||||
stats:
|
||||
|
||||
==== ==================
|
||||
1 Show usual stats
|
||||
2 Show frame timings
|
||||
==== ==================
|
||||
|
||||
Font
|
||||
~~~~
|
||||
|
||||
For optimal visual experience, a font with support for many font weights and
|
||||
monospaced digits is recommended. By default, the open source font
|
||||
`Source Sans Pro <https://github.com/adobe-fonts/source-sans-pro>`_ is used.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
This script can be customized through a config file ``script-opts/stats.conf``
|
||||
placed in mpv's user directory and through the ``--script-opts`` command-line
|
||||
option. The configuration syntax is described in `ON SCREEN CONTROLLER`_.
|
||||
|
||||
Configurable Options
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``key_oneshot``
|
||||
Default: i
|
||||
``key_toggle``
|
||||
Default: I
|
||||
|
||||
Key bindings to display stats.
|
||||
|
||||
``key_page_1``
|
||||
Default: 1
|
||||
``key_page_2``
|
||||
Default: 2
|
||||
|
||||
Key bindings for page switching while stats are displayed.
|
||||
|
||||
``duration``
|
||||
Default: 4
|
||||
|
||||
How long the stats are shown in seconds (oneshot).
|
||||
|
||||
``redraw_delay``
|
||||
Default: 1
|
||||
|
||||
How long it takes to refresh the displayed stats in seconds (toggling).
|
||||
|
||||
``persistent_overlay``
|
||||
Default: no
|
||||
|
||||
When `no`, other scripts printing text to the screen can overwrite the
|
||||
displayed stats. When `yes`, displayed stats are persistently shown for the
|
||||
respective duration. This can result in overlapping text when multiple
|
||||
scripts decide to print text at the same time.
|
||||
|
||||
``plot_perfdata``
|
||||
Default: yes
|
||||
|
||||
Show graphs for performance data (page 2).
|
||||
|
||||
``plot_vsync_ratio``
|
||||
Default: yes
|
||||
``plot_vsync_jitter``
|
||||
Default: yes
|
||||
|
||||
Show graphs for vsync and jitter values (page 1). Only when toggled.
|
||||
|
||||
``flush_graph_data``
|
||||
Default: yes
|
||||
|
||||
Clear data buffers used for drawing graphs when toggling.
|
||||
|
||||
``font``
|
||||
Default: Source Sans Pro
|
||||
|
||||
Font name. Should support as many font weights as possible for optimal
|
||||
visual experience.
|
||||
|
||||
``font_mono``
|
||||
Default: Source Sans Pro
|
||||
|
||||
Font name for parts where monospaced characters are necessary to align
|
||||
text. Currently, monospaced digits are sufficient.
|
||||
|
||||
``font_size``
|
||||
Default: 8
|
||||
|
||||
Font size used to render text.
|
||||
|
||||
``font_color``
|
||||
Default: FFFFFF
|
||||
|
||||
Font color.
|
||||
|
||||
``border_size``
|
||||
Default: 0.8
|
||||
|
||||
Size of border drawn around the font.
|
||||
|
||||
``border_color``
|
||||
Default: 262626
|
||||
|
||||
Color of drawn border.
|
||||
|
||||
``alpha``
|
||||
Default: 11
|
||||
|
||||
Transparency for drawn text.
|
||||
|
||||
``plot_bg_border_color``
|
||||
Default: 0000FF
|
||||
|
||||
Border color used for drawing graphs.
|
||||
|
||||
``plot_bg_color``
|
||||
Default: 262626
|
||||
|
||||
Background color used for drawing graphs.
|
||||
|
||||
``plot_color``
|
||||
Default: FFFFFF
|
||||
|
||||
Color used for drawing graphs.
|
||||
|
||||
Note: colors are given as hexadecimal values and use ASS tag order: BBGGRR
|
||||
(blue green red).
|
||||
|
||||
Different key bindings
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A different key binding can be defined with the aforementioned options
|
||||
``key_oneshot`` and ``key_toggle`` but also with commands in ``input.conf``,
|
||||
for example::
|
||||
|
||||
e script-binding stats/display-stats
|
||||
E script-binding stats/display-stats-toggle
|
||||
|
||||
Using ``input.conf``, it is also possible to directly display a certain page::
|
||||
|
||||
i script-binding stats/display-page-1
|
||||
e script-binding stats/display-page-2
|
||||
+527
-485
File diff suppressed because it is too large.
Load diff
+493
-277
@@ -4,20 +4,29 @@ VIDEO OUTPUT DRIVERS
|
||||
Video output drivers are interfaces to different video output facilities. The
|
||||
syntax is:
|
||||
|
||||
``--vo=<driver1,driver2,...[,]>``
|
||||
``--vo=<driver1[:suboption1[=value]:...],driver2,...[,]>``
|
||||
Specify a priority list of video output drivers to be used.
|
||||
|
||||
If the list has a trailing ``,``, mpv will fall back on drivers not contained
|
||||
in the list.
|
||||
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.
|
||||
|
||||
``--vo-defaults=<driver1[:parameter1:parameter2:...],driver2,...>``
|
||||
Set defaults for each driver.
|
||||
|
||||
.. note::
|
||||
|
||||
See ``--vo=help`` for a list of compiled-in video output drivers.
|
||||
|
||||
The recommended output driver is ``--vo=gpu``, which is the default. All
|
||||
other drivers are for compatibility or special purposes. If the default
|
||||
does not work, it will fallback to other drivers (in the same order as
|
||||
listed by ``--vo=help``).
|
||||
The recommended output drivers are ``--vo=vdpau`` and ``--vo=opengl-hq``.
|
||||
All other drivers are just for compatibility or special purposes.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``--vo=opengl,xv,``
|
||||
Try the ``opengl`` driver, then the ``xv`` driver, then others.
|
||||
|
||||
Available video output drivers are:
|
||||
|
||||
@@ -28,13 +37,11 @@ Available video output drivers are:
|
||||
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--xv-adaptor=<number>``
|
||||
``adaptor=<number>``
|
||||
Select a specific XVideo adapter (check xvinfo results).
|
||||
``--xv-port=<number>``
|
||||
``port=<number>``
|
||||
Select a specific XVideo port.
|
||||
``--xv-ck=<cur|use|set>``
|
||||
``ck=<cur|use|set>``
|
||||
Select the source from which the color key is taken (default: cur).
|
||||
|
||||
cur
|
||||
@@ -45,11 +52,9 @@ Available video output drivers are:
|
||||
set
|
||||
Same as use but also sets the supplied color key.
|
||||
|
||||
``--xv-ck-method=<none|man|bg|auto>``
|
||||
``ck-method=<man|bg|auto>``
|
||||
Sets the color key drawing method (default: man).
|
||||
|
||||
none
|
||||
Disables color-keying.
|
||||
man
|
||||
Draw the color key manually (reduces flicker in some cases).
|
||||
bg
|
||||
@@ -57,15 +62,12 @@ Available video output drivers are:
|
||||
auto
|
||||
Let Xv draw the color key.
|
||||
|
||||
``--xv-colorkey=<number>``
|
||||
``colorkey=<number>``
|
||||
Changes the color key to an RGB value of your choice. ``0x000000`` is
|
||||
black and ``0xffffff`` is white.
|
||||
|
||||
``--xv-buffers=<number>``
|
||||
Number of image buffers to use for the internal ringbuffer (default: 2).
|
||||
Increasing this will use more memory, but might help with the X server
|
||||
not responding quickly enough if video FPS is close to or higher than
|
||||
the display refresh rate.
|
||||
``no-colorkey``
|
||||
Disables color-keying.
|
||||
|
||||
``x11`` (X11 only)
|
||||
Shared memory video output driver without hardware acceleration that works
|
||||
@@ -84,25 +86,23 @@ Available video output drivers are:
|
||||
``chroma-deint``, ``pullup``, ``hqscaling``. These sub-options are
|
||||
deprecated, and you should use the ``vdpaupp`` video filter instead.
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--vo-vdpau-sharpen=<-1-1>``
|
||||
``sharpen=<-1-1>``
|
||||
(Deprecated. See note about ``vdpaupp``.)
|
||||
|
||||
For positive values, apply a sharpening algorithm to the video, for
|
||||
negative values a blurring algorithm (default: 0).
|
||||
``--vo-vdpau-denoise=<0-1>``
|
||||
``denoise=<0-1>``
|
||||
(Deprecated. See note about ``vdpaupp``.)
|
||||
|
||||
Apply a noise reduction algorithm to the video (default: 0; no noise
|
||||
reduction).
|
||||
``--vo-vdpau-deint=<-4-4>``
|
||||
``deint=<-4-4>``
|
||||
(Deprecated. See note about ``vdpaupp``.)
|
||||
|
||||
Select deinterlacing mode (default: 0). In older versions (as well as
|
||||
MPlayer/mplayer2) you could use this option to enable deinterlacing.
|
||||
This doesn't work anymore, and deinterlacing is enabled with either
|
||||
the ``d`` key (by default mapped to the command ``cycle deinterlace``),
|
||||
the ``D`` key (by default mapped to the command ``cycle deinterlace``),
|
||||
or the ``--deinterlace`` option. Also, to select the default deint mode,
|
||||
you should use something like ``--vf-defaults=vdpaupp:deint-mode=temporal``
|
||||
instead of this sub-option.
|
||||
@@ -119,32 +119,32 @@ Available video output drivers are:
|
||||
4
|
||||
Motion-adaptive temporal deinterlacing with edge-guided spatial
|
||||
interpolation. Needs fast video hardware.
|
||||
``--vo-vdpau-chroma-deint``
|
||||
``chroma-deint``
|
||||
(Deprecated. See note about ``vdpaupp``.)
|
||||
|
||||
Makes temporal deinterlacers operate both on luma and chroma (default).
|
||||
Use no-chroma-deint to solely use luma and speed up advanced
|
||||
deinterlacing. Useful with slow video memory.
|
||||
``--vo-vdpau-pullup``
|
||||
``pullup``
|
||||
(Deprecated. See note about ``vdpaupp``.)
|
||||
|
||||
Try to apply inverse telecine, needs motion adaptive temporal
|
||||
deinterlacing.
|
||||
``--vo-vdpau-hqscaling=<0-9>``
|
||||
``hqscaling=<0-9>``
|
||||
(Deprecated. See note about ``vdpaupp``.)
|
||||
|
||||
0
|
||||
Use default VDPAU scaling (default).
|
||||
1-9
|
||||
Apply high quality VDPAU scaling (needs capable hardware).
|
||||
``--vo-vdpau-fps=<number>``
|
||||
``fps=<number>``
|
||||
Override autodetected display refresh rate value (the value is needed
|
||||
for framedrop to allow video playback rates higher than display
|
||||
refresh rate, and for vsync-aware frame timing adjustments). Default 0
|
||||
means use autodetected value. A positive value is interpreted as a
|
||||
refresh rate in Hz and overrides the autodetected value. A negative
|
||||
value disables all timing adjustment and framedrop logic.
|
||||
``--vo-vdpau-composite-detect``
|
||||
``composite-detect``
|
||||
NVIDIA's current VDPAU implementation behaves somewhat differently
|
||||
under a compositing window manager and does not give accurate frame
|
||||
timing information. With this option enabled, the player tries to
|
||||
@@ -154,21 +154,21 @@ Available video output drivers are:
|
||||
means timing is somewhat less accurate than without compositing, but
|
||||
with the composited mode behavior of the NVIDIA driver, there is no
|
||||
hard playback speed limit even without the disabled logic. Enabled by
|
||||
default, use ``--vo-vdpau-composite-detect=no`` to disable.
|
||||
``--vo-vdpau-queuetime-windowed=<number>`` and ``queuetime-fs=<number>``
|
||||
default, use ``no-composite-detect`` to disable.
|
||||
``queuetime_windowed=<number>`` and ``queuetime_fs=<number>``
|
||||
Use VDPAU's presentation queue functionality to queue future video
|
||||
frame changes at most this many milliseconds in advance (default: 50).
|
||||
See below for additional information.
|
||||
``--vo-vdpau-output-surfaces=<2-15>``
|
||||
``output_surfaces=<2-15>``
|
||||
Allocate this many output surfaces to display video frames (default:
|
||||
3). See below for additional information.
|
||||
``--vo-vdpau-colorkey=<#RRGGBB|#AARRGGBB>``
|
||||
``colorkey=<#RRGGBB|#AARRGGBB>``
|
||||
Set the VDPAU presentation queue background color, which in practice
|
||||
is the colorkey used if VDPAU operates in overlay mode (default:
|
||||
``#020507``, some shade of black). If the alpha component of this value
|
||||
is 0, the default VDPAU colorkey will be used instead (which is usually
|
||||
green).
|
||||
``--vo-vdpau-force-yuv``
|
||||
``force-yuv``
|
||||
Never accept RGBA input. This means mpv will insert a filter to convert
|
||||
to a YUV format before the VO. Sometimes useful to force availability
|
||||
of certain YUV-only features, like video equalizer or deinterlacing.
|
||||
@@ -195,40 +195,31 @@ Available video output drivers are:
|
||||
driver implementation may also have limits on the length of maximum
|
||||
queuing time or number of queued surfaces that work well or at all.
|
||||
|
||||
``direct3d`` (Windows only)
|
||||
``direct3d_shaders`` (Windows only)
|
||||
Video output driver that uses the Direct3D interface.
|
||||
|
||||
.. note:: This driver is for compatibility with systems that don't provide
|
||||
proper OpenGL drivers, and where ANGLE does not perform well.
|
||||
proper OpenGL drivers.
|
||||
|
||||
.. note:: Before to 0.21.0, ``direct3d_shaders`` and ``direct3d`` were
|
||||
different, with ``direct3d`` not using shader by default. Now
|
||||
both use shaders by default, and ``direct3d_shaders`` is a
|
||||
deprecated alias. Use the ``--vo-direct3d-prefer-stretchrect``
|
||||
or the ``--vo-direct3d-disable-shaders`` options to get the old
|
||||
behavior of ``direct3d``.
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--vo-direct3d-prefer-stretchrect``
|
||||
``prefer-stretchrect``
|
||||
Use ``IDirect3DDevice9::StretchRect`` over other methods if possible.
|
||||
|
||||
``--vo-direct3d-disable-stretchrect``
|
||||
``disable-stretchrect``
|
||||
Never render the video using ``IDirect3DDevice9::StretchRect``.
|
||||
|
||||
``--vo-direct3d-disable-textures``
|
||||
``disable-textures``
|
||||
Never render the video using D3D texture rendering. Rendering with
|
||||
textures + shader will still be allowed. Add ``disable-shaders`` to
|
||||
completely disable video rendering with textures.
|
||||
|
||||
``--vo-direct3d-disable-shaders``
|
||||
``disable-shaders``
|
||||
Never use shaders when rendering video.
|
||||
|
||||
``--vo-direct3d-only-8bit``
|
||||
``only-8bit``
|
||||
Never render YUV video with more than 8 bits per component.
|
||||
Using this flag will force software conversion to 8-bit.
|
||||
|
||||
``--vo-direct3d-disable-texture-align``
|
||||
``disable-texture-align``
|
||||
Normally texture sizes are always aligned to 16. With this option
|
||||
enabled, the video texture will always have exactly the same size as
|
||||
the video itself.
|
||||
@@ -238,11 +229,11 @@ Available video output drivers are:
|
||||
might crash, might cause slow downs, etc. Contact the developers if you
|
||||
actually need any of these for performance or proper operation.
|
||||
|
||||
``--vo-direct3d-force-power-of-2``
|
||||
``force-power-of-2``
|
||||
Always force textures to power of 2, even if the device reports
|
||||
non-power-of-2 texture sizes as supported.
|
||||
|
||||
``--vo-direct3d-texture-memory=<mode>``
|
||||
``texture-memory=<mode>``
|
||||
Only affects operation with shaders/texturing enabled, and (E)OSD.
|
||||
Possible values:
|
||||
|
||||
@@ -266,41 +257,397 @@ Available video output drivers are:
|
||||
Use ``D3DPOOL_SCRATCH``, with a ``D3DPOOL_SYSTEMMEM`` texture for
|
||||
locking.
|
||||
|
||||
``--vo-direct3d-swap-discard``
|
||||
``swap-discard``
|
||||
Use ``D3DSWAPEFFECT_DISCARD``, which might be faster.
|
||||
Might be slower too, as it must(?) clear every frame.
|
||||
|
||||
``--vo-direct3d-exact-backbuffer``
|
||||
``exact-backbuffer``
|
||||
Always resize the backbuffer to window size.
|
||||
|
||||
``gpu``
|
||||
General purpose, customizable, GPU-accelerated video output driver. It
|
||||
supports extended scaling methods, dithering, color management, custom
|
||||
shaders, HDR, and more.
|
||||
``direct3d`` (Windows only)
|
||||
Same as ``direct3d_shaders``, but with the options ``disable-textures``
|
||||
and ``disable-shaders`` forced.
|
||||
|
||||
See `GPU renderer options`_ for options specific to this VO.
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
By default, it tries to use fast and fail-safe settings. Use the
|
||||
``gpu-hq`` profile to use this driver with defaults set to high quality
|
||||
rendering. The profile can be applied with ``--profile=gpu-hq`` and its
|
||||
contents can be viewed with ``--show-profile=gpu-hq``.
|
||||
``opengl``
|
||||
OpenGL video output driver. It supports extended scaling methods, dithering
|
||||
and color management.
|
||||
|
||||
This VO abstracts over several possible graphics APIs and windowing
|
||||
contexts, which can be influenced using the ``--gpu-api`` and
|
||||
``--gpu-context`` options.
|
||||
By default, it tries to use fast and fail-safe settings. Use the alias
|
||||
``opengl-hq`` to use this driver with defaults set to high quality
|
||||
rendering.
|
||||
|
||||
Requires at least OpenGL 2.1.
|
||||
|
||||
Some features are available with OpenGL 3 capable graphics drivers only
|
||||
(or if the necessary extensions are available).
|
||||
|
||||
OpenGL ES 2.0 and 3.0 are supported as well.
|
||||
|
||||
Hardware decoding over OpenGL-interop is supported to some degree. Note
|
||||
that in this mode, some corner case might not be gracefully handled, and
|
||||
color space conversion and chroma upsampling is generally in the hand of
|
||||
the hardware decoder APIs.
|
||||
|
||||
``gpu`` makes use of FBOs by default. Sometimes you can achieve better
|
||||
quality or performance by changing the ``--gpu-fbo-format`` option to
|
||||
``rgb16f``, ``rgb32f`` or ``rgb``. Known problems include Mesa/Intel not
|
||||
accepting ``rgb16``, Mesa sometimes not being compiled with float texture
|
||||
support, and some OS X setups being very slow with ``rgb16`` but fast
|
||||
with ``rgb32f``. If you have problems, you can also try enabling the
|
||||
``--gpu-dumb-mode=yes`` option.
|
||||
``scale=<filter>``
|
||||
|
||||
``bilinear``
|
||||
Bilinear hardware texture filtering (fastest, very low quality).
|
||||
This is the default for compatibility reasons.
|
||||
|
||||
``spline36``
|
||||
Mid quality and speed. This is the default when using ``opengl-hq``.
|
||||
|
||||
``lanczos``
|
||||
Lanczos scaling. Provides mid quality and speed. Generally worse
|
||||
than ``spline36``, but it results in a slightly sharper image
|
||||
which is good for some content types. The number of taps can be
|
||||
controlled with ``scale-radius``, but is best left unchanged.
|
||||
|
||||
This filter corresponds to the old ``lanczos3`` alias if the default
|
||||
radius is used, while ``lanczos2`` corresponds to a radius of 2.
|
||||
|
||||
``ewa_lanczos``
|
||||
Elliptic weighted average Lanczos scaling. Also known as Jinc.
|
||||
Relatively slow, but very good quality. The number of taps can
|
||||
be controlled with ``scale-radius``. Adding extra taps makes the
|
||||
filter sharper but adds more ringing.
|
||||
|
||||
This filter supports antiringing (see ``scale-antiring``).
|
||||
|
||||
``mitchell``
|
||||
Mitchell-Netravali. The ``b`` and ``c`` parameters can be set with
|
||||
``scale-param1`` and ``scale-param2``. Both are set to 1/3 by default.
|
||||
This filter is very good at downscaling (see ``scale-down``).
|
||||
|
||||
There are some more filters, but most are not as useful. For a complete
|
||||
list, pass ``help`` as value, e.g.::
|
||||
|
||||
mpv --vo=opengl:scale=help
|
||||
|
||||
``scale-param1=<value>``
|
||||
Set filter parameters. Ignored if the filter is not tunable. These are
|
||||
unset by default, and use the filter specific default if applicable.
|
||||
|
||||
``scale-param2=<value>``
|
||||
See ``scale-param1``.
|
||||
|
||||
``scale-radius=<r>``
|
||||
Set radius for filters listed below, must be a float number between 1.0
|
||||
and 16.0. Defaults to be 3.0 if not specified.
|
||||
|
||||
``sinc``, ``lanczos``, ``ewa_lanczos``, ``blackman``, ``gaussian``
|
||||
|
||||
Note that depending on filter implementation details and video scaling
|
||||
ratio, the radius that actually being used might be different
|
||||
(most likely being increased a bit).
|
||||
|
||||
``scale-antiring=<value>``
|
||||
Set the antiringing strength. This tries to eliminate ringing, but can
|
||||
introduce other artifacts in the process. Must be a float number
|
||||
between 0.0 and 1.0. The default value of 0.0 disables antiringing
|
||||
entirely.
|
||||
|
||||
Note that this currently only affects ``ewa_lanczos``.
|
||||
|
||||
``scaler-resizes-only``
|
||||
Disable the scaler if the video image is not resized. In that case,
|
||||
``bilinear`` is used instead whatever is set with ``scale``. Bilinear
|
||||
will reproduce the source image perfectly if no scaling is performed.
|
||||
Note that this option never affects ``cscale``.
|
||||
|
||||
``srgb``
|
||||
Convert and color correct the output to sRGB before displaying it on
|
||||
the screen. This option enables ``linear-scaling``.
|
||||
|
||||
This option is equivalent to using ``icc-profile`` with an sRGB ICC
|
||||
profile, but it is implemented without a 3DLUT and does not require
|
||||
LittleCMS 2. If both ``srgb`` and ``icc-profile`` are present, the
|
||||
latter takes precedence, as they are somewhat redundant.
|
||||
|
||||
Note: When playing back BT.2020 content with this option enabled, out
|
||||
of gamut colors will be numerically clipped, which can potentially
|
||||
change the hue and/or luminance. If this is not desired, it is
|
||||
recommended to use ``icc-profile`` with an sRGB ICC profile instead,
|
||||
when playing back wide-gamut BT.2020 content.
|
||||
|
||||
``pbo``
|
||||
Enable use of PBOs. This is slightly faster, but can sometimes lead to
|
||||
sporadic and temporary image corruption (in theory, because reupload
|
||||
is not retried when it fails), and perhaps actually triggers slower
|
||||
paths with drivers that don't support PBOs properly.
|
||||
|
||||
``dither-depth=<N|no|auto>``
|
||||
Set dither target depth to N. Default: no.
|
||||
|
||||
no
|
||||
Disable any dithering done by mpv.
|
||||
auto
|
||||
Automatic selection. If output bit depth cannot be detected,
|
||||
8 bits per component are assumed.
|
||||
8
|
||||
Dither to 8 bit output.
|
||||
|
||||
Note that the depth of the connected video display device can not be
|
||||
detected. Often, LCD panels will do dithering on their own, which
|
||||
conflicts with ``opengl``'s dithering and leads to ugly output.
|
||||
|
||||
``dither-size-fruit=<2-8>``
|
||||
Set the size of the dither matrix (default: 6). The actual size of
|
||||
the matrix is ``(2^N) x (2^N)`` for an option value of ``N``, so a
|
||||
value of 6 gives a size of 64x64. The matrix is generated at startup
|
||||
time, and a large matrix can take rather long to compute (seconds).
|
||||
|
||||
Used in ``dither=fruit`` mode only.
|
||||
|
||||
``dither=<fruit|ordered|no>``
|
||||
Select dithering algorithm (default: fruit). (Normally, the
|
||||
``dither-depth`` option controls whether dithering is enabled.)
|
||||
|
||||
``temporal-dither``
|
||||
Enable temporal dithering. (Only active if dithering is enabled in
|
||||
general.) This changes between 8 different dithering pattern on each
|
||||
frame by changing the orientation of the tiled dithering matrix.
|
||||
Unfortunately, this can lead to flicker on LCD displays, since these
|
||||
have a high reaction time.
|
||||
|
||||
``debug``
|
||||
Check for OpenGL errors, i.e. call ``glGetError()``. Also request a
|
||||
debug OpenGL context (which does nothing with current graphics drivers
|
||||
as of this writing).
|
||||
|
||||
``swapinterval=<n>``
|
||||
Interval in displayed frames between two buffer swaps.
|
||||
1 is equivalent to enable VSYNC, 0 to disable VSYNC. Defaults to 1 if
|
||||
not specified.
|
||||
|
||||
``cscale=<filter>``
|
||||
As ``scale``, but for interpolating chroma information. If the image
|
||||
is not subsampled, this option is ignored entirely. Note that the
|
||||
implementation is currently always done as a single pass, so using
|
||||
it with separable filters will result in slow performance for very
|
||||
little visible benefit.
|
||||
|
||||
``scale-down=<filter>``
|
||||
Like ``scale``, but apply these filters on downscaling instead. If this
|
||||
option is unset, the filter implied by ``scale`` will be applied.
|
||||
|
||||
``cscale-param1``, ``cscale-param2``, ``cscale-radius``, ``cscale-antiring``
|
||||
Set filter parameters and radius for ``cscale``.
|
||||
|
||||
See ``scale-param1``, ``scale-param2``, ``scale-radius`` and
|
||||
``scale-antiring``.
|
||||
|
||||
``linear-scaling``
|
||||
Scale in linear light. This is automatically enabled if ``srgb``,
|
||||
``icc-profile`` or ``sigmoid-upscaling`` is set. It should only
|
||||
be used with a ``fbo-format`` that has at least 16 bit precision.
|
||||
|
||||
``fancy-downscaling``
|
||||
When using convolution based filters, extend the filter size
|
||||
when downscaling. Trades quality for reduced downscaling performance.
|
||||
|
||||
This is automatically disabled for anamorphic video, because this
|
||||
feature doesn't work correctly with different scale factors in
|
||||
different directions.
|
||||
|
||||
``sigmoid-upscaling``
|
||||
When upscaling, use a sigmoidal color transform to avoid emphasizing
|
||||
ringing artifacts. This also enables ``linear-scaling``.
|
||||
|
||||
``sigmoid-center``
|
||||
The center of the sigmoid curve used for ``sigmoid-upscaling``, must
|
||||
be a float between 0.0 and 1.0. Defaults to 0.75 if not specified.
|
||||
|
||||
``sigmoid-slope``
|
||||
The slope of the sigmoid curve used for ``sigmoid-upscaling``, must
|
||||
be a float between 1.0 and 20.0. Defaults to 6.5 if not specified.
|
||||
|
||||
``no-npot``
|
||||
Force use of power-of-2 texture sizes. For debugging only.
|
||||
Borders will be distorted due to filtering.
|
||||
|
||||
``glfinish``
|
||||
Call ``glFinish()`` before and after swapping buffers (default: disabled).
|
||||
Slower, but might help getting better results when doing framedropping.
|
||||
Can completely ruin performance. The details depend entirely on the
|
||||
OpenGL driver.
|
||||
|
||||
``waitvsync``
|
||||
Call ``glXWaitVideoSyncSGI`` after each buffer swap (default: disabled).
|
||||
This may or may not help with video timing accuracy and frame drop. It's
|
||||
possible that this makes video output slower, or has no effect at all.
|
||||
|
||||
X11/GLX only.
|
||||
|
||||
``sw``
|
||||
Continue even if a software renderer is detected.
|
||||
|
||||
``backend=<sys>``
|
||||
The value ``auto`` (the default) selects the windowing backend. You
|
||||
can also pass ``help`` to get a complete list of compiled in backends
|
||||
(sorted by autoprobe order).
|
||||
|
||||
auto
|
||||
auto-select (default)
|
||||
cocoa
|
||||
Cocoa/OS X
|
||||
win
|
||||
Win32/WGL
|
||||
x11, x11es
|
||||
X11/GLX (the ``es`` variant forces GLES)
|
||||
wayland
|
||||
Wayland/EGL
|
||||
x11egl, x11egles
|
||||
X11/EGL (the ``es`` variant forces GLES)
|
||||
|
||||
``fbo-format=<fmt>``
|
||||
Selects the internal format of textures used for FBOs. The format can
|
||||
influence performance and quality of the video output. (FBOs are not
|
||||
always used, and typically only when using extended scalers.)
|
||||
``fmt`` can be one of: rgb, rgba, rgb8, rgb10, rgb10_a2, rgb16, rgb16f,
|
||||
rgb32f, rgba12, rgba16, rgba16f, rgba32f.
|
||||
Default: rgba.
|
||||
|
||||
``gamma=<0.1..2.0>``
|
||||
Set a gamma value (default: 1.0). If gamma is adjusted in other ways
|
||||
(like with the ``--gamma`` option or key bindings and the ``gamma``
|
||||
property), the value is multiplied with the other gamma value.
|
||||
|
||||
Recommended values based on the environmental brightness:
|
||||
|
||||
1.0
|
||||
Brightly illuminated (default)
|
||||
0.9
|
||||
Slightly dim
|
||||
0.8
|
||||
Pitch black room
|
||||
|
||||
``icc-profile=<file>``
|
||||
Load an ICC profile and use it to transform linear RGB to screen output.
|
||||
Needs LittleCMS 2 support compiled in. This option overrides the ``srgb``
|
||||
property, as using both is somewhat redundant. It also enables
|
||||
``linear-scaling``.
|
||||
|
||||
|
||||
``icc-profile-auto``
|
||||
Automatically select the ICC display profile currently specified by
|
||||
the display settings of the operating system.
|
||||
|
||||
NOTE: Only implemented on OS X and X11
|
||||
|
||||
``icc-cache=<file>``
|
||||
Store and load the 3D LUT created from the ICC profile in this file.
|
||||
This can be used to speed up loading, since LittleCMS 2 can take a while
|
||||
to create the 3D LUT. Note that this file contains an uncompressed LUT.
|
||||
Its size depends on the ``3dlut-size``, and can be very big.
|
||||
|
||||
``icc-intent=<value>``
|
||||
Specifies the ICC Intent used for transformations between color spaces.
|
||||
This affects the rendering when using ``icc-profile`` or ``srgb`` and
|
||||
also affects the way DCP XYZ content gets converted to RGB.
|
||||
|
||||
0
|
||||
perceptual
|
||||
1
|
||||
relative colorimetric (default)
|
||||
2
|
||||
saturation
|
||||
3
|
||||
absolute colorimetric
|
||||
|
||||
``3dlut-size=<r>x<g>x<b>``
|
||||
Size of the 3D LUT generated from the ICC profile in each dimension.
|
||||
Default is 128x256x64.
|
||||
Sizes must be a power of two, and 512 at most.
|
||||
|
||||
``alpha=<blend|yes|no>``
|
||||
Decides what to do if the input has an alpha component (default: blend).
|
||||
|
||||
blend
|
||||
Blend the frame against a black background.
|
||||
yes
|
||||
Try to create a framebuffer with alpha component. This only makes sense
|
||||
if the video contains alpha information (which is extremely rare). May
|
||||
not be supported on all platforms. If alpha framebuffers are
|
||||
unavailable, it silently falls back on a normal framebuffer. Note
|
||||
that if you set the ``fbo-format`` option to a non-default value,
|
||||
a format with alpha must be specified, or this won't work.
|
||||
no
|
||||
Ignore alpha component.
|
||||
|
||||
``chroma-location=<auto|center|left>``
|
||||
Set the YUV chroma sample location. auto means use the bitstream
|
||||
flags (default: auto).
|
||||
|
||||
``rectangle-textures``
|
||||
Force use of rectangle textures (default: no). Normally this shouldn't
|
||||
have any advantages over normal textures. Note that hardware decoding
|
||||
overrides this flag.
|
||||
|
||||
``background=<color>``
|
||||
Color used to draw parts of the mpv window not covered by video.
|
||||
See ``--osd-color`` option how colors are defined.
|
||||
|
||||
``smoothmotion``
|
||||
Reduce stuttering caused by mismatches in video fps and display
|
||||
refresh rate (also known as judder).
|
||||
|
||||
Instead of drawing source frames for variable durations, smoothmotion
|
||||
will blend frames that overlap the transition between two frames in
|
||||
the source material.
|
||||
|
||||
For example, a 24 Hz clip played back on a 60 Hz display would normally
|
||||
result in a pattern like this::
|
||||
|
||||
A A A B B C C C D D E E E F F
|
||||
|
||||
which has different lengths, alternating between 3 and 2. This
|
||||
difference in frame duration is what causes judder.
|
||||
|
||||
With smoothmotion enabled, the pattern changes to::
|
||||
|
||||
A A A+B B B C C C+D D D E E E+F F F
|
||||
|
||||
where A+B is a blend of A and B. In this pattern, each frame gets a
|
||||
(consistent) duration of roughly 2.5 - resulting in smooth motion.
|
||||
|
||||
GPU drivers or compositing window managers overriding vsync behavior
|
||||
can lead to bad results. If the framerate is close to or over the
|
||||
display refresh rate, results can be bad as well.
|
||||
|
||||
.. note:: On systems other than Linux or OS X, you currently must set
|
||||
the ``--display-fps`` option, or the results will be bad.
|
||||
|
||||
``smoothmotion-threshold=<0.0-0.5>``
|
||||
Mix threshold at which interpolation is skipped (default: 0.0 – never
|
||||
skip).
|
||||
|
||||
For example, with a ``smoothmotion-threshold`` of 0.1, if the
|
||||
smoothmotion algorithm would try to blend two frames by a ratio of
|
||||
95% A + 5% B, it would simply display A instead. (Since the
|
||||
distance, 0.05, is lower than the threshold)
|
||||
|
||||
Setting this to 0.5 would be similar to disabling smoothmotion
|
||||
completely, since it would always just display the nearest frame.
|
||||
|
||||
``opengl-hq``
|
||||
Same as ``opengl``, but with default settings for high quality rendering.
|
||||
|
||||
This is equivalent to::
|
||||
|
||||
--vo=opengl:scale=spline36:scale-down=mitchell:dither-depth=auto:fbo-format=rgba16:fancy-downscaling:sigmoid-upscaling
|
||||
|
||||
Note that some cheaper LCDs do dithering that gravely interferes with
|
||||
``opengl``'s dithering. Disabling dithering with ``dither-depth=no`` helps.
|
||||
|
||||
Unlike ``opengl``, ``opengl-hq`` makes use of FBOs by default. Sometimes you
|
||||
can achieve better quality or performance by changing the ``fbo-format``
|
||||
suboption to ``rgb16f``, ``rgb32f`` or ``rgb``. Known problems include
|
||||
Mesa/Intel not accepting ``rgb16``, Mesa sometimes not being compiled with
|
||||
float texture support, and some OS X setups being very slow with ``rgb16``
|
||||
but fast with ``rgb32f``.
|
||||
|
||||
``sdl``
|
||||
SDL 2.0+ Render video output driver, depending on system with or without
|
||||
@@ -308,27 +655,24 @@ Available video output drivers are:
|
||||
For tuning, refer to your copy of the file ``SDL_hints.h``.
|
||||
|
||||
.. note:: This driver is for compatibility with systems that don't provide
|
||||
proper graphics drivers.
|
||||
proper graphics drivers, or which support GLES only.
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--sdl-sw``
|
||||
``sw``
|
||||
Continue even if a software renderer is detected.
|
||||
|
||||
``--sdl-switch-mode``
|
||||
``switch-mode``
|
||||
Instruct SDL to switch the monitor video mode when going fullscreen.
|
||||
|
||||
``vaapi``
|
||||
Intel VA API video output driver with support for hardware decoding. Note
|
||||
that there is absolutely no reason to use this, other than compatibility.
|
||||
This is low quality, and has issues with OSD.
|
||||
that there is absolutely no reason to use this, other than wanting to use
|
||||
hardware decoding to save power on laptops, or possibly preventing video
|
||||
tearing with some setups.
|
||||
|
||||
.. note:: This driver is for compatibility with crappy systems. You can
|
||||
use vaapi hardware decoding with ``--vo=gpu`` too.
|
||||
use vaapi hardware decoding with ``--vo=opengl`` too.
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--vo-vaapi-scaling=<algorithm>``
|
||||
``scaling=<algorithm>``
|
||||
default
|
||||
Driver default (mpv default as well).
|
||||
fast
|
||||
@@ -338,9 +682,9 @@ Available video output drivers are:
|
||||
nla
|
||||
``non-linear anamorphic scaling``
|
||||
|
||||
``--vo-vaapi-deint-mode=<mode>``
|
||||
``deint-mode=<mode>``
|
||||
Select deinterlacing algorithm. Note that by default deinterlacing is
|
||||
initially always off, and needs to be enabled with the ``d`` key
|
||||
initially always off, and needs to be enabled with the ``D`` key
|
||||
(default key binding for ``cycle deinterlace``).
|
||||
|
||||
This option doesn't apply if libva supports video post processing (vpp).
|
||||
@@ -353,11 +697,11 @@ Available video output drivers are:
|
||||
no
|
||||
Don't allow deinterlacing (default for newer libva).
|
||||
first-field
|
||||
Show only first field.
|
||||
Show only first field (going by ``--field-dominance``).
|
||||
bob
|
||||
bob deinterlacing (default for older libva).
|
||||
|
||||
``--vo-vaapi-scaled-osd=<yes|no>``
|
||||
``scaled-osd=<yes|no>``
|
||||
If enabled, then the OSD is rendered at video resolution and scaled to
|
||||
display resolution. By default, this is disabled, and the OSD is
|
||||
rendered at display resolution if the driver supports it.
|
||||
@@ -365,48 +709,16 @@ Available video output drivers are:
|
||||
``null``
|
||||
Produces no video output. Useful for benchmarking.
|
||||
|
||||
Usually, it's better to disable video with ``--no-video`` instead.
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--vo-null-fps=<value>``
|
||||
Simulate display FPS. This artificially limits how many frames the
|
||||
VO accepts per second.
|
||||
|
||||
``caca``
|
||||
Color ASCII art video output driver that works on a text console.
|
||||
|
||||
.. note:: This driver is a joke.
|
||||
|
||||
``tct``
|
||||
Color Unicode art video output driver that works on a text console.
|
||||
Depends on support of true color by modern terminals to display the images
|
||||
at full color range. On Windows it requires an ansi terminal such as mintty.
|
||||
|
||||
``--vo-tct-algo=<algo>``
|
||||
Select how to write the pixels to the terminal.
|
||||
|
||||
half-blocks
|
||||
Uses unicode LOWER HALF BLOCK character to achieve higher vertical
|
||||
resolution. (Default.)
|
||||
plain
|
||||
Uses spaces. Causes vertical resolution to drop twofolds, but in
|
||||
theory works in more places.
|
||||
|
||||
``--vo-tct-width=<width>`` ``--vo-tct-height=<height>``
|
||||
Assume the terminal has the specified character width and/or height.
|
||||
These default to 80x25 if the terminal size cannot be determined.
|
||||
|
||||
``--vo-tct-256=<yes|no>`` (default: no)
|
||||
Use 256 colors - for terminals which don't support true color.
|
||||
|
||||
``image``
|
||||
Output each frame into an image file in the current directory. Each file
|
||||
takes the frame number padded with leading zeros as name.
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--vo-image-format=<format>``
|
||||
``format=<format>``
|
||||
Select the image file format.
|
||||
|
||||
jpg
|
||||
@@ -415,172 +727,76 @@ Available video output drivers are:
|
||||
JPEG files, extension .jpeg.
|
||||
png
|
||||
PNG files.
|
||||
webp
|
||||
WebP files.
|
||||
ppm
|
||||
Portable bitmap format.
|
||||
pgm
|
||||
Portable graymap format.
|
||||
pgmyuv
|
||||
Portable graymap format, using the YV12 pixel format.
|
||||
tga
|
||||
Truevision TGA.
|
||||
|
||||
``--vo-image-png-compression=<0-9>``
|
||||
``png-compression=<0-9>``
|
||||
PNG compression factor (speed vs. file size tradeoff) (default: 7)
|
||||
``--vo-image-png-filter=<0-5>``
|
||||
``png-filter=<0-5>``
|
||||
Filter applied prior to PNG compression (0 = none; 1 = sub; 2 = up;
|
||||
3 = average; 4 = Paeth; 5 = mixed) (default: 5)
|
||||
``--vo-image-jpeg-quality=<0-100>``
|
||||
``jpeg-quality=<0-100>``
|
||||
JPEG quality factor (default: 90)
|
||||
``--vo-image-jpeg-optimize=<0-100>``
|
||||
``(no-)jpeg-progressive``
|
||||
Specify standard or progressive JPEG (default: no).
|
||||
``(no-)jpeg-baseline``
|
||||
Specify use of JPEG baseline or not (default: yes).
|
||||
``jpeg-optimize=<0-100>``
|
||||
JPEG optimization factor (default: 100)
|
||||
``--vo-image-webp-lossless=<yes|no>``
|
||||
Enable writing lossless WebP files (default: no)
|
||||
``--vo-image-webp-quality=<0-100>``
|
||||
WebP quality (default: 75)
|
||||
``--vo-image-webp-compression=<0-6>``
|
||||
WebP compression factor (default: 4)
|
||||
``--vo-image-outdir=<dirname>``
|
||||
``jpeg-smooth=<0-100>``
|
||||
smooth factor (default: 0)
|
||||
``jpeg-dpi=<1->``
|
||||
JPEG DPI (default: 72)
|
||||
``outdir=<dirname>``
|
||||
Specify the directory to save the image files to (default: ``./``).
|
||||
|
||||
``libmpv``
|
||||
For use with libmpv direct embedding. As a special case, on OS X it
|
||||
is used like a normal VO within mpv (cocoa-cb). Otherwise useless in any
|
||||
other contexts.
|
||||
(See ``<mpv/render.h>``.)
|
||||
``wayland`` (Wayland only)
|
||||
Wayland shared memory video output as fallback for ``opengl``.
|
||||
|
||||
This also supports many of the options the ``gpu`` VO has, depending on the
|
||||
backend.
|
||||
.. note:: This driver is for compatibility with systems that don't provide
|
||||
working OpenGL drivers.
|
||||
|
||||
``rpi`` (Raspberry Pi)
|
||||
Native video output on the Raspberry Pi using the MMAL API.
|
||||
``alpha``
|
||||
Use a buffer format that supports videos and images with alpha
|
||||
information
|
||||
``rgb565``
|
||||
Use RGB565 as buffer format. This format is implemented on most
|
||||
platforms, especially on embedded where it is far more efficient then
|
||||
RGB8888.
|
||||
``triple-buffering``
|
||||
Use 3 buffers instead of 2. This can lead to more fluid playback, but
|
||||
uses more memory.
|
||||
|
||||
This is deprecated. Use ``--vo=gpu`` instead, which is the default and
|
||||
provides the same functionality. The ``rpi`` VO will be removed in
|
||||
mpv 0.23.0. Its functionality was folded into --vo=gpu, which now uses
|
||||
RPI hardware decoding by treating it as a hardware overlay (without applying
|
||||
GL filtering). Also to be changed in 0.23.0: the --fs flag will be reset to
|
||||
"no" by default (like on the other platforms).
|
||||
``opengl-cb``
|
||||
For use with libmpv direct OpenGL embedding; useless in any other contexts.
|
||||
(See ``<mpv/opengl_cb.h>``.)
|
||||
Usually, ``opengl-cb`` renders frames asynchronously by client and this
|
||||
can cause some frame drops. In order to provide a way to handle this
|
||||
situation, ``opengl-cb`` has its own frame queue and calls update callback
|
||||
more frequently if the queue is not empty regardless of existence of new frame.
|
||||
Once the queue is filled, ``opengl-cb`` drops frames automatically.
|
||||
|
||||
The following deprecated global options are supported by this video output:
|
||||
With default options, ``opengl-cb`` renders only the latest frame and drops
|
||||
all frames handed over while waiting render function after update callback.
|
||||
|
||||
``--rpi-display=<number>``
|
||||
Select the display number on which the video overlay should be shown
|
||||
(default: 0).
|
||||
``frame-queue-size=<1..100>``
|
||||
The maximum count of frames which the frame queue can hold (default: 1)
|
||||
|
||||
``--rpi-layer=<number>``
|
||||
Select the dispmanx layer on which the video overlay should be shown
|
||||
(default: -10). Note that mpv will also use the 2 layers above the
|
||||
selected layer, to handle the window background and OSD. Actual video
|
||||
rendering will happen on the layer above the selected layer.
|
||||
``frame-drop-mode=<pop|clear>``
|
||||
Select the behavior when the frame queue is full.
|
||||
|
||||
``--rpi-background=<yes|no>``
|
||||
Whether to render a black background behind the video (default: no).
|
||||
Normally it's better to kill the console framebuffer instead, which
|
||||
gives better performance.
|
||||
pop
|
||||
Drop the oldest frame in the frame queue. (default)
|
||||
clear
|
||||
Drop all frames in the frame queue.
|
||||
|
||||
``--rpi-osd=<yes|no>``
|
||||
Enabled by default. If disabled with ``no``, no OSD layer is created.
|
||||
This also means there will be no subtitles rendered.
|
||||
This also supports many of the suboptions the ``opengl`` VO has. Runs
|
||||
``mpv --vo=opengl-cb:help`` for a list.
|
||||
|
||||
``drm`` (Direct Rendering Manager)
|
||||
Video output driver using Kernel Mode Setting / Direct Rendering Manager.
|
||||
Should be used when one doesn't want to install full-blown graphical
|
||||
environment (e.g. no X). Does not support hardware acceleration (if you
|
||||
need this, check the ``drm`` backend for ``gpu`` VO).
|
||||
|
||||
The following global options are supported by this video output:
|
||||
|
||||
``--drm-connector=[<gpu_number>.]<name>``
|
||||
Select the connector to use (usually this is a monitor.) If ``<name>``
|
||||
is empty or ``auto``, mpv renders the output on the first available
|
||||
connector. Use ``--drm-connector=help`` to get a list of available
|
||||
connectors. When using multiple graphic cards, use the ``<gpu_number>``
|
||||
argument to disambiguate.
|
||||
(default: empty)
|
||||
|
||||
``--drm-mode=<preferred|highest|N|WxH[@R]>``
|
||||
Mode to use (resolution and frame rate).
|
||||
Possible values:
|
||||
|
||||
:preferred: Use the preferred mode for the screen on the selected
|
||||
connector. (default)
|
||||
:highest: Use the mode with the highest resolution available on the
|
||||
selected connector.
|
||||
:N: Select mode by index.
|
||||
:WxH[@R]: Specify mode by width, height, and optionally refresh rate.
|
||||
In case several modes match, selects the mode that comes
|
||||
first in the EDID list of modes.
|
||||
|
||||
Use ``--drm-mode=help`` to get a list of available modes for all active
|
||||
connectors.
|
||||
|
||||
``--drm-atomic=<no|auto>``
|
||||
Toggle use of atomic modesetting. Mostly useful for debugging.
|
||||
|
||||
:no: Use legacy modesetting.
|
||||
:auto: Use atomic modesetting, falling back to legacy modesetting if
|
||||
not available. (default)
|
||||
|
||||
Note: Only affects ``gpu-context=drm``. ``vo=drm`` supports legacy
|
||||
modesetting only.
|
||||
|
||||
``--drm-draw-plane=<primary|overlay|N>``
|
||||
Select the DRM plane to which video and OSD is drawn to, under normal
|
||||
circumstances. The plane can be specified as ``primary``, which will
|
||||
pick the first applicable primary plane; ``overlay``, which will pick
|
||||
the first applicable overlay plane; or by index. The index is zero
|
||||
based, and related to the CRTC.
|
||||
(default: primary)
|
||||
|
||||
When using this option with the drmprime-drm hwdec interop, only the OSD
|
||||
is rendered to this plane.
|
||||
|
||||
``--drm-drmprime-video-plane=<primary|overlay|N>``
|
||||
Select the DRM plane to use for video with the drmprime-drm hwdec
|
||||
interop (used by e.g. the rkmpp hwdec on RockChip SoCs, and v4l2 hwdec:s
|
||||
on various other SoC:s). The plane is unused otherwise. This option
|
||||
accepts the same values as ``--drm-draw-plane``. (default: overlay)
|
||||
|
||||
To be able to successfully play 4K video on various SoCs you might need
|
||||
to set ``--drm-draw-plane=overlay --drm-drmprime-video-plane=primary``
|
||||
and setting ``--drm-draw-surface-size=1920x1080``, to render the OSD at a
|
||||
lower resolution (the video when handled by the hwdec will be on the
|
||||
drmprime-video plane and at full 4K resolution)
|
||||
|
||||
``--drm-format=<xrgb8888|xrgb2101010>``
|
||||
Select the DRM format to use (default: xrgb8888). This allows you to
|
||||
choose the bit depth of the DRM mode. xrgb8888 is your usual 24 bit per
|
||||
pixel/8 bits per channel packed RGB format with 8 bits of padding.
|
||||
xrgb2101010 is a packed 30 bits per pixel/10 bits per channel packed RGB
|
||||
format with 2 bits of padding.
|
||||
|
||||
There are cases when xrgb2101010 will work with the ``drm`` VO, but not
|
||||
with the ``drm`` backend for the ``gpu`` VO. This is because with the
|
||||
``gpu`` VO, in addition to requiring support in your DRM driver,
|
||||
requires support for xrgb2101010 in your EGL driver
|
||||
|
||||
``--drm-draw-surface-size=<[WxH]>``
|
||||
Sets the size of the surface used on the draw plane. The surface will
|
||||
then be upscaled to the current screen resolution. This option can be
|
||||
useful when used together with the drmprime-drm hwdec interop at high
|
||||
resolutions, as it allows scaling the draw plane (which in this case
|
||||
only handles the OSD) down to a size the GPU can handle.
|
||||
|
||||
When used without the drmprime-drm hwdec interop this option will just
|
||||
cause the video to get rendered at a different resolution and then
|
||||
scaled to screen size.
|
||||
|
||||
Note: this option is only available with DRM atomic support.
|
||||
(default: display resolution)
|
||||
|
||||
``mediacodec_embed`` (Android)
|
||||
Renders ``IMGFMT_MEDIACODEC`` frames directly to an ``android.view.Surface``.
|
||||
Requires ``--hwdec=mediacodec`` for hardware decoding, along with
|
||||
``--vo=mediacodec_embed`` and ``--wid=(intptr_t)(*android.view.Surface)``.
|
||||
|
||||
Since this video output driver uses native decoding and rendering routines,
|
||||
many of mpv's features (subtitle rendering, OSD/OSC, video filters, etc)
|
||||
are not available with this driver.
|
||||
|
||||
To use hardware decoding with ``--vo=gpu`` instead, use
|
||||
``--hwdec=mediacodec-copy`` along with ``--gpu-context=android``.
|
||||
|
||||
``wlshm`` (Wayland only)
|
||||
Shared memory video output driver without hardware acceleration that works
|
||||
whenever Wayland is present.
|
||||
|
||||
.. note:: This is a fallback only, and should not be normally used.
|
||||
This also supports the ``vo_cmdline`` command.
|
||||
+19
-32
@@ -7,11 +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.
|
||||
|
||||
.. admonition:: Warning
|
||||
|
||||
This document is **not updated** anymore, and is **incomplete** and
|
||||
**outdated**. If you look for old option replacements, always check with
|
||||
the current mpv manpage, as the options could have changed meanwhile.
|
||||
.. note::
|
||||
These lists are incomplete.
|
||||
|
||||
General Changes from MPlayer to mpv
|
||||
-----------------------------------
|
||||
@@ -33,7 +30,7 @@ Player
|
||||
* Slave mode compatibility broken (see below).
|
||||
* Re-enable screensaver while the player is paused.
|
||||
* Allow resuming playback at a later point with ``Shift+q``, also see the
|
||||
``quit-watch-later`` input command.
|
||||
``quit_watch_later`` input command.
|
||||
* ``--keep-open`` option to stop the player from closing the window and
|
||||
exiting after playback ends.
|
||||
* A client API, that allows embedding **mpv** into applications
|
||||
@@ -49,13 +46,6 @@ Input
|
||||
* Allow customizing whether a key binding for seeking shows the video time, the
|
||||
OSD bar, or nothing (see the `Input Command Prefixes`_ section).
|
||||
* Support mapping multiple commands to one key.
|
||||
* Classic LIRC support was removed. Install remotes as input devices instead.
|
||||
This way they will send X11 key events to the mpv window, which can be bound
|
||||
using the normal ``input.conf``.
|
||||
Also see: http://github.com/mpv-player/mpv/wiki/IR-remotes
|
||||
* Joystick support was removed. It was considered useless and was the cause
|
||||
of some problems (e.g. a laptop's accelerator being recognized as joystick).
|
||||
* Support for relative seeking by percentage.
|
||||
|
||||
Audio
|
||||
~~~~~
|
||||
@@ -76,16 +66,15 @@ Video
|
||||
|
||||
* Wayland support.
|
||||
* Native support for VAAPI and VDA. Improved VDPAU video output.
|
||||
* Improved GPU-accelerated video output (see the ``gpu-hq`` preset).
|
||||
* Make hardware decoding work with the ``gpu`` video output.
|
||||
* Improved OpenGL output (see the ``opengl-hq`` video output).
|
||||
* Make hardware decoding work with the ``opengl`` video output.
|
||||
* Support for libavfilter (for video->video and audio->audio). This allows
|
||||
using most of FFmpeg's filters, which improve greatly on the old MPlayer
|
||||
filters in features, performance, and correctness.
|
||||
* More correct color reproduction (color matrix generation), including support
|
||||
for BT.2020 (Ultra HD). linear XYZ (Digital Cinema) and SMPTE ST2084 (HDR)
|
||||
inputs.
|
||||
for BT.2020 (Ultra HD) and linear XYZ (Digital Cinema) inputs.
|
||||
* Support for color managed displays, via ICC profiles.
|
||||
* High-quality image resamplers (see the ``--scale`` suboption).
|
||||
* High-quality image resamplers (see the ``opengl`` ``scale`` suboption).
|
||||
* Support for scaling in (sigmoidized) linear light.
|
||||
* Better subtitle rendering using libass by default.
|
||||
* Improvements when playing multiple files (``-fixed-vo`` is default, do not
|
||||
@@ -98,8 +87,6 @@ Video
|
||||
|
||||
* Image subtitles (DVDs etc.) are rendered in color and use more correct
|
||||
positioning (color for image subs can be disabled with ``--sub-gray``).
|
||||
* Support for the X11 video output is removed, since it was considered
|
||||
deprecated. SDL video output can still be used as a fallback.
|
||||
|
||||
OSD and terminal
|
||||
~~~~~~~~~~~~~~~~
|
||||
@@ -212,7 +199,7 @@ Command Line Switches
|
||||
``-no<opt>`` ``--no-<opt>`` (add a dash)
|
||||
``-a52drc level`` ``--ad-lavc-ac3drc=level``
|
||||
``-ac spdifac3`` ``--ad=spdif:ac3`` (see ``--ad=help``)
|
||||
``-af volnorm`` (removed; use acompressor ffmpeg filter instead)
|
||||
``-af volnorm`` ``--af=drc`` (renamed)
|
||||
``-afm hwac3`` ``--ad=spdif:ac3,spdif:dts``
|
||||
``-ao alsa:device=hw=0.3`` ``--ao=alsa:device=[hw:0,3]``
|
||||
``-aspect`` ``--video-aspect``
|
||||
@@ -240,6 +227,7 @@ Command Line Switches
|
||||
``-idx`` ``--index``
|
||||
``-lavdopts ...`` ``--vd-lavc-...``
|
||||
``-lavfdopts`` ``--demuxer-lavf-...``
|
||||
``-lircconf`` ``--input-lirc-conf``
|
||||
``-loop 0`` ``--loop=inf``
|
||||
``-mixer-channel`` AO suboptions (``alsa``, ``oss``)
|
||||
``-mixer`` AO suboptions (``alsa``, ``oss``)
|
||||
@@ -251,6 +239,7 @@ Command Line Switches
|
||||
``-noar`` ``--no-input-appleremote``
|
||||
``-noautosub`` ``--no-sub-auto``
|
||||
``-noconsolecontrols`` ``--no-input-terminal``
|
||||
``-nojoystick`` ``--no-input-joystick``
|
||||
``-nosound`` ``--no-audio``
|
||||
``-osdlevel`` ``--osd-level``
|
||||
``-panscanrange`` ``--video-zoom``, ``--video-pan-x/y``
|
||||
@@ -265,14 +254,13 @@ 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-*``, ``--osd-*``
|
||||
``-subfont-*`` ``--sub-text-*``, ``--osd-*``
|
||||
``-subfont-text-scale`` ``--sub-scale``
|
||||
``-subfont`` ``--sub-font``
|
||||
``-subfont`` ``--sub-text-font``
|
||||
``-subfps`` ``--sub-fps``
|
||||
``-subpos`` ``--sub-pos``
|
||||
``-sws`` ``--sws-scaler``
|
||||
@@ -284,7 +272,7 @@ Command Line Switches
|
||||
``-xineramascreen`` ``--screen`` (different values)
|
||||
``-xy W`` ``--autofit=W``
|
||||
``-zoom`` Inverse available as ``--video-unscaled``
|
||||
``dvdnav://`` Removed.
|
||||
``dvdnav://`` ``dvdnav://menu``
|
||||
``dvd://1`` ``dvd://0`` (0-based offset)
|
||||
=========================== ========================================
|
||||
|
||||
@@ -316,11 +304,11 @@ input.conf and Slave Commands
|
||||
+--------------------------------+----------------------------------------+
|
||||
| Old | New |
|
||||
+================================+========================================+
|
||||
| ``pt_step 1 [0|1]`` | ``playlist-next [weak|force]`` |
|
||||
| ``pt_step 1 [0|1]`` | ``playlist_next [weak|force]`` |
|
||||
| | (translation layer cannot deal with |
|
||||
| | whitespace) |
|
||||
+--------------------------------+----------------------------------------+
|
||||
| ``pt_step -1 [0|1]`` | ``playlist-prev [weak|force] (same)`` |
|
||||
| ``pt_step -1 [0|1]`` | ``playlist_prev [weak|force] (same)`` |
|
||||
+--------------------------------+----------------------------------------+
|
||||
| ``switch_ratio [<ratio>]`` | ``set video-aspect <ratio>`` |
|
||||
| | |
|
||||
@@ -335,7 +323,7 @@ input.conf and Slave Commands
|
||||
| ``<step> <dir>`` | ``no-osd``: ``no-osd cycle <prop>`` |
|
||||
| | ``<step>`` |
|
||||
+--------------------------------+----------------------------------------+
|
||||
| ``osd_show_property_text`` | ``show-text <text>`` |
|
||||
| ``osd_show_property_text`` | ``show_text <text>`` |
|
||||
| ``<text>`` | The property expansion format string |
|
||||
| | syntax slightly changed. |
|
||||
+--------------------------------+----------------------------------------+
|
||||
@@ -344,9 +332,9 @@ input.conf and Slave Commands
|
||||
| | ``raw`` prefix to disable property |
|
||||
| | expansion. |
|
||||
+--------------------------------+----------------------------------------+
|
||||
| ``show_tracks`` | ``show-text ${track-list}`` |
|
||||
| ``show_tracks`` | ``show_text ${track-list}`` |
|
||||
+--------------------------------+----------------------------------------+
|
||||
| ``show_chapters`` | ``show-text ${chapter-list}`` |
|
||||
| ``show_chapters`` | ``show_text ${chapter-list}`` |
|
||||
+--------------------------------+----------------------------------------+
|
||||
| ``af_switch``, ``af_add``, ... | ``af set|add|...`` |
|
||||
+--------------------------------+----------------------------------------+
|
||||
@@ -404,8 +392,7 @@ Slave mode
|
||||
|
||||
Assuming the system supports ``/dev/stdin``.
|
||||
|
||||
(The option was added back in 0.5.1 and sets exactly these options. It was
|
||||
removed in 0.10.x again.)
|
||||
(The option was readded in 0.5.1 and sets exactly these options.)
|
||||
|
||||
* A JSON RPC protocol giving access to the client API is also supported. See
|
||||
`JSON IPC`_ for more information.
|
||||
|
||||
+29
-75
@@ -1,110 +1,64 @@
|
||||
Release Policy
|
||||
==============
|
||||
|
||||
Once or twice a month, a new release is cut off of the master branch and is
|
||||
assigned a 0.X.Y version number, where X is incremented each time a release
|
||||
contains breaking changes, such as changed options or added/removed features,
|
||||
and Y is incremented if a release contains only bugfixes and other minor
|
||||
changes.
|
||||
Every few months, a new release is cut off of the master branch and is assigned
|
||||
a 0.X.0 version number.
|
||||
|
||||
Releases are tagged on the master branch and will not be maintained separately.
|
||||
As part of the maintenance process, minor releases are made, which are assigned
|
||||
0.X.Y version numbers. Minor releases contain bug fixes only. They never merge
|
||||
the master branch, and no features are added to it. Only the latest release is
|
||||
maintained.
|
||||
|
||||
The goal of releases is to provide Linux distributions with something to
|
||||
package. If you want the newest features, just use the master branch.
|
||||
We try our best to keep it deployable at all times.
|
||||
The goal of releases is to provide stability and an unchanged base for the sake
|
||||
of Linux distributions. If you want the newest features, just use the master
|
||||
branch, which is stable most of the time, except sometimes, when it's not.
|
||||
|
||||
Releases other than the latest release are unsupported and unmaintained.
|
||||
|
||||
Release procedure
|
||||
-----------------
|
||||
|
||||
While on master:
|
||||
- Create branch release/0.X or cherry-pick commits to the relevant branch.
|
||||
|
||||
- Update the `RELEASE_NOTES` file.
|
||||
- Create and/or update the ``RELEASE_NOTES`` file.
|
||||
|
||||
- Update the `VERSION` file.
|
||||
- Create and/or update the ``VERSION`` file.
|
||||
|
||||
- Update `DOCS/client-api-changes.rst` and `DOCS/interface-changes.rst`
|
||||
(in particular, update the last version numbers if necessary)
|
||||
- Update ``DOCS/client-api-changes.rst`` (on major releases).
|
||||
|
||||
- Commit changes.
|
||||
- Create tag v0.X.Y.
|
||||
|
||||
- Create signed tag v0.X.Y.
|
||||
- Push branch and tag to GitHub.
|
||||
|
||||
- Add -UNKNOWN suffix to version in `VERSION` file.
|
||||
|
||||
- Commit changes, push branch and tag to GitHub.
|
||||
|
||||
- Create a new GitHub release using the content of `RELEASE_NOTES` related to
|
||||
- Create a new GitHub release using the content of ``RELEASE_NOTES`` related to
|
||||
the new version.
|
||||
|
||||
Release notes template
|
||||
----------------------
|
||||
|
||||
Here is a template that can be used for writing the `RELEASE_NOTES` file.
|
||||
Here is a template that can be used for writing the ``RELEASE_NOTES`` file.
|
||||
|
||||
```markdown
|
||||
Release 0.X.Y
|
||||
=============
|
||||
|
||||
Features
|
||||
--------
|
||||
Changes
|
||||
-------
|
||||
|
||||
New
|
||||
~~~
|
||||
- List of changes.
|
||||
|
||||
- List of new features
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
Removed
|
||||
~~~~~~~
|
||||
- List of bug fixes.
|
||||
|
||||
- List of removed features
|
||||
New features
|
||||
------------
|
||||
|
||||
Deprecated
|
||||
~~~~~~~~~~
|
||||
|
||||
- List of deprecated features
|
||||
|
||||
Behavior
|
||||
--------
|
||||
|
||||
- List of user-visible changes in behavior
|
||||
|
||||
Options and Commands
|
||||
--------------------
|
||||
|
||||
Added
|
||||
~~~~~
|
||||
|
||||
- List of added options and commands
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
|
||||
- List of changed options and commands
|
||||
|
||||
Renamed
|
||||
~~~~~~~
|
||||
|
||||
- List of renamed options and commands
|
||||
|
||||
Deprecated
|
||||
~~~~~~~~~~
|
||||
|
||||
- List of deprecated options and commands
|
||||
|
||||
Removed
|
||||
~~~~~~~
|
||||
|
||||
- List of removed options and commands
|
||||
|
||||
Fixes and Minor Enhancements
|
||||
----------------------------
|
||||
|
||||
- List of fixes and minor enhancements
|
||||
- List of new features.
|
||||
|
||||
This listing is not complete. There are many more bug fixes and changes. The
|
||||
complete change log can be viewed by running `git log <start>..<end>` in
|
||||
complete change log can be viewed by running ``git log <start>..<end>`` in
|
||||
the git repository.
|
||||
```
|
||||
|
||||
@@ -112,6 +66,6 @@ Note that the "Release 0.X.Y" title should be removed when creating a new GitHub
|
||||
release.
|
||||
|
||||
When creating a new point release its changes should be added on top of the
|
||||
`RELEASE_NOTES` file (with the appropriate title) so that all the changes in
|
||||
the current 0.X branch will be included. This way the `RELEASE_NOTES` file
|
||||
``RELEASE_NOTES`` file (with the appropriate title) so that all the changes in
|
||||
the current 0.X branch will be included. This way the ``RELEASE_NOTES`` file
|
||||
can be used by distributors as changelog for point releases too.
|
||||
+57
-33
@@ -46,7 +46,9 @@ player/*.c:
|
||||
- most state is in MPContext (core.h), which is not available to the
|
||||
subsystems
|
||||
- the currently played tracks are in mpctx->current_tracks, and decoder
|
||||
state in track.d_video/d_audio/d_sub
|
||||
state in d_video/d_audio/d_sub
|
||||
- the timeline stuff is used only with MKV ordered chapters (and some other
|
||||
minor features: cue, edl)
|
||||
- the other subsystems rarely call back into the frontend, and the frontend
|
||||
polls them instead (probably a good thing)
|
||||
- one exceptions are wakeup callbacks, which notify a "higher" component
|
||||
@@ -54,18 +56,27 @@ player/*.c:
|
||||
|
||||
I like to call the player/*.c files the "frontend".
|
||||
|
||||
ta.h & ta.c:
|
||||
Hierarchical memory manager inspired by talloc from Samba. It's like a
|
||||
malloc() with more features. Most importantly, each talloc allocation can
|
||||
have a parent, and if the parent is free'd, all children will be free'd as
|
||||
well. The parent is an arbitrary talloc allocation. It's either set by the
|
||||
allocation call by passing a talloc parent, usually as first argument to the
|
||||
allocation function. It can also be set or reset later by other calls (at
|
||||
least talloc_steal()). A talloc allocation that is used as parent is often
|
||||
called a talloc context.
|
||||
talloc.h & talloc.c:
|
||||
Hierarchical memory manager copied from Samba. It's like a malloc() with
|
||||
more features. Most importantly, each talloc allocation can have a parent,
|
||||
and if the parent is free'd, all children will be free'd as well. The
|
||||
parent is an arbitrary talloc allocation. It's either set by the allocation
|
||||
call by passing a talloc parent, usually as first argument to the allocation
|
||||
function. It can also be set or reset later by other calls (at least
|
||||
talloc_steal()). A talloc allocation that is used as parent is often called
|
||||
a talloc context.
|
||||
|
||||
Lots of code still uses malloc() proper, and you should be careful what
|
||||
type of allocation you're dealing with when returning or free'ing an
|
||||
allocation. (Needless to say, talloc_free() and free() are completely
|
||||
different things.)
|
||||
|
||||
The copy in mpv has been modified to abort on OOM conditions. An
|
||||
allocation call will never return NULL.
|
||||
|
||||
One very useful feature of talloc is fast tracking of memory leaks. ("Fast"
|
||||
as in it doesn't require valgrind.) You can enable it by setting the
|
||||
as in it doesn't require valgrind.) You can enable it by passing the option
|
||||
--leak-report as first parameter, or better, setting the
|
||||
MPV_LEAK_REPORT environment variable to "1":
|
||||
export MPV_LEAK_REPORT=1
|
||||
This will list all unfree'd allocations on exit.
|
||||
@@ -73,14 +84,16 @@ ta.h & ta.c:
|
||||
Documentation can be found here:
|
||||
http://git.samba.org/?p=samba.git;a=blob;f=lib/talloc/talloc.h;hb=HEAD
|
||||
|
||||
For some reason, we're still using API-compatible wrappers instead of TA
|
||||
directly. The talloc wrapper has only a subset of the functionality, and
|
||||
in particular the wrappers abort() on memory allocation failure.
|
||||
|
||||
Note: unlike tcmalloc, jemalloc, etc., talloc() is not actually a malloc
|
||||
replacement. It works on top of system malloc and provides additional
|
||||
features that are supposed to make memory management easier.
|
||||
|
||||
Warning: actually, we're not using talloc anymore. talloc in mpv has been
|
||||
replaced by a custom re-implementation (TA in ta/). It provides
|
||||
some talloc emulation (just the parts needed by mpv). We will get
|
||||
rid of the talloc emulation later and use TA natively.
|
||||
(See ta/README for details.)
|
||||
|
||||
player/command.c:
|
||||
This contains the implementation for client API commands and properties.
|
||||
Properties are essentially dynamic variables changed by certain commands.
|
||||
@@ -108,10 +121,10 @@ options/options.h, options/options.c
|
||||
their own sub-option tables separate from MPOpts.
|
||||
|
||||
The actual option parser is spread over m_option.c, m_config.c, and
|
||||
parse_commandline.c, and uses the option table in options.c.
|
||||
parser-mpcmd.c, and uses the option table in options.c.
|
||||
|
||||
input/input.c:
|
||||
This translates keyboard input coming from VOs and other sources (such
|
||||
This translates keyboard input comming from VOs and other sources (such
|
||||
as remote control devices like Apple IR or client API commands) to the
|
||||
key bindings listed in the user's (or the builtin) input.conf and turns
|
||||
them into items of type struct mp_cmd. These commands are queued, and read
|
||||
@@ -139,6 +152,9 @@ stream/*:
|
||||
Some stream inputs are just there to invoke special demuxers, like
|
||||
stream_mf.c. (Basically to make the prefix "mf://" do something special.)
|
||||
|
||||
cache.c is a caching wrapper around streams implementations, needed for
|
||||
smooth network playback.
|
||||
|
||||
demux/:
|
||||
Demuxers split data streams into audio/video/sub streams, which in turn
|
||||
are split in packets. Packets (see demux_packet.h) are mostly byte chunks
|
||||
@@ -146,16 +162,13 @@ demux/:
|
||||
|
||||
Most demuxers have been removed from this fork, and the only important and
|
||||
"actual" demuxers left are demux_mkv.c and demux_lavf.c (uses libavformat).
|
||||
There are some pseudo demuxers like demux_cue.c.
|
||||
There are some pseudo demuxers like demux_cue.c, which exist only to invoke
|
||||
other frontend code (tl_cue.c in this case).
|
||||
|
||||
The main interface is in demux.h. The stream headers are in stheader.h.
|
||||
There is a stream header for each audio/video/sub stream, and each of them
|
||||
holds codec information about the stream and other information.
|
||||
|
||||
demux.c is a bit big, the main reason being that it contains the demuxer
|
||||
cache, which is implemented as a list of packets. The cache is complex
|
||||
because it support seeking, multiple ranges, prefetching, and so on.
|
||||
|
||||
video/:
|
||||
This contains several things related to audio/video decoding, as well as
|
||||
video filters.
|
||||
@@ -164,8 +177,8 @@ video/:
|
||||
internally.
|
||||
|
||||
video/decode/:
|
||||
vd_*.c are video decoders. (There's only vd_lavc.c left.) dec_video.c
|
||||
handles most of connecting the frontend with the actual decoder.
|
||||
vd_*.c are video decoders. (There's only vd_lavc.c left.) dec_video.c/vd.c
|
||||
handle most of connecting the frontend with the actual decoder.
|
||||
|
||||
video/filter/:
|
||||
vf_*.c and vf.c form the video filter chain. They are fed by the video
|
||||
@@ -178,26 +191,27 @@ video/out/:
|
||||
Video output. They also create GUI windows and handle user input. In most
|
||||
cases, the windowing code is shared among VOs, like x11_common.c for X11 and
|
||||
w32_common.c for Windows. The VOs stand between frontend and windowing code.
|
||||
vo_gpu can pick a windowing system at runtime, e.g. the same binary can
|
||||
vo_opengl can pick a windowing system at runtime, e.g. the same binary can
|
||||
provide both X11 and Cocoa support on OSX.
|
||||
|
||||
VOs can be reconfigured at runtime. A vo_reconfig() call can change the video
|
||||
VOs can be reconfigured at runtime. A vo_config() call can change the video
|
||||
resolution and format, without destroying the window.
|
||||
|
||||
vo_gpu should be taken as reference.
|
||||
vo_vdpau and vo_opengl should be taken as reference.
|
||||
|
||||
audio/:
|
||||
format.h/format.c define the uncompressed audio formats. (As well as some
|
||||
compressed formats used for spdif.)
|
||||
|
||||
audio/decode/:
|
||||
ad_*.c and dec_audio.c handle audio decoding. ad_lavc.c is the
|
||||
ad_*.c and dec_audio.c/ad.c handle audio decoding. ad_lavc.c is the
|
||||
decoder using ffmpeg. ad_spdif.c is not really a decoder, but is used for
|
||||
compressed audio passthrough.
|
||||
|
||||
audio/filter/:
|
||||
Audio filter chain. af_lavrresample is inserted if any form of conversion
|
||||
between audio formats is needed.
|
||||
between audio formats is needed. (af_convert24.c and af_convertsignendian.c
|
||||
are also used for some formats not directly supported by FFmpeg.)
|
||||
|
||||
audio/out/:
|
||||
Audio outputs.
|
||||
@@ -231,12 +245,22 @@ sub/:
|
||||
|
||||
The subtitles are passed to dec_sub.c and the subtitle decoders in sd_*.c
|
||||
as they are demuxed. All text subtitles are rendered by sd_ass.c. If text
|
||||
subtitles are not in the ASS format, the libavcodec subtitle converters are
|
||||
used (lavc_conv.c).
|
||||
subtitles are not in the ASS format, subtitle converters are inserted, for
|
||||
example sd_srt.c, which is used to convert SRT->ASS. sd_srt.c is also used
|
||||
as general converter for text->ASS (to prevent interpretation of text as
|
||||
ASS tags).
|
||||
|
||||
Text subtitles can be preloaded, in which case they are read fully as soon
|
||||
as the subtitle is selected. In this case, they are effectively stored in
|
||||
sd_ass.c's internal state.
|
||||
as the subtitle is selected, and then effectively stored in an ASS_Track.
|
||||
It's used for external text subtitles, and required to make codepage
|
||||
detection as well as timing postprocessing work. (Timing postprocessing
|
||||
removes tiny gaps or overlaps between subtitle events.)
|
||||
|
||||
player/timeline/:
|
||||
A timeline is the abstraction used by loadfile.c to combine several files
|
||||
into one seemingly linear video. It's mainly used for ordered chapters
|
||||
playback. The high level code to find and load other files containing the
|
||||
segments for playing an ordered chapters file is in tl_matroska.c.
|
||||
|
||||
etc/:
|
||||
The file input.conf is actually integrated into the mpv binary by the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
waf build system overview
|
||||
=========================
|
||||
|
||||
mpv's new build system is based on waf and it should completely replace the
|
||||
mpv's new build system is based on waf and it should completly replace the
|
||||
custom ./configure + Makefile based system inherited from MPlayer.
|
||||
|
||||
Goals and the choice of waf
|
||||
@@ -20,9 +20,8 @@ shortcomings:
|
||||
part is this pieces are spread apart in the configure and copy pasted for
|
||||
any single case. That brings us to..
|
||||
|
||||
2) --enable-feature has to be overridden by the user and helps them understand that
|
||||
they have libraries missing and should install them for the feature to be
|
||||
enabled.
|
||||
2) --enable-feature has to override the user and help him understand that he
|
||||
has libraries missing and should install them for the feature to be enabled.
|
||||
|
||||
3) Must be customizable, hackable, pleasant to the developer eyes and to work
|
||||
with in general.
|
||||
@@ -65,7 +64,7 @@ This defines a feature called ``vdpau`` which can be enabled or disabled by
|
||||
the users with configure flags (that's the meaning of ``--``). This feature
|
||||
depends on another feature whose name is ``x11``, and the autodetection check
|
||||
consists of running ``pkg-config`` and looking for ``vdpau`` with version
|
||||
``>= 0.2``. If the check succeeds a ``#define HAVE_VDPAU 1`` will be added to
|
||||
``>= 0.2``. If the check succeds a ``#define HAVE_VDPAU 1`` will be added to
|
||||
``config.h``, if not ``#define HAVE_VDPAU 0`` will be added.
|
||||
|
||||
The defines names are automatically prepended with ``HAVE_``, capitalized and
|
||||
@@ -146,7 +145,7 @@ mpv's custom build step on top of waf
|
||||
|
||||
Build step is pretty much vanilla waf. The only difference being that the list
|
||||
of source files can contain both strings or tuples. If a tuple is found,
|
||||
the second element in the tuple will be used to match the features detected
|
||||
the second element in the tuple will the used to match the features detected
|
||||
in the configure step (the ``name`` field described above). If this feature
|
||||
was not enabled during configure, the source file will not be compiled in.
|
||||
|
||||
|
||||
File renamed without changes.
-502
@@ -1,502 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
@@ -1,79 +1,29 @@
|
||||

|
||||
|
||||
# mpv
|
||||
|
||||
|
||||
* [External links](#external-links)
|
||||
* [Overview](#overview)
|
||||
* [System requirements](#system-requirements)
|
||||
* [Downloads](#downloads)
|
||||
* [Changelog](#changelog)
|
||||
* [Compilation](#compilation)
|
||||
* [Release cycle](#release-cycle)
|
||||
* [Bug reports](#bug-reports)
|
||||
* [Contributing](#contributing)
|
||||
* [License](#license)
|
||||
* [Contact](#contact)
|
||||
|
||||
|
||||
## External links
|
||||
|
||||
|
||||
* [Wiki](https://github.com/mpv-player/mpv/wiki)
|
||||
* [FAQ](https://github.com/mpv-player/mpv/wiki/FAQ)
|
||||
* [Manual](http://mpv.io/manual/master/)
|
||||
|
||||
|
||||
## Overview
|
||||
mpv
|
||||
===
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
**mpv** is a media player based on MPlayer and mplayer2. It supports a wide
|
||||
variety of video file formats, audio and video codecs, and subtitle types.
|
||||
|
||||
Releases can be found on the [release list][releases].
|
||||
|
||||
## System requirements
|
||||
|
||||
- A not too ancient Linux, Windows 7 or later, or OSX 10.8 or later.
|
||||
- A somewhat capable CPU. Hardware decoding might help if the CPU is too slow to
|
||||
decode video in realtime, but must be explicitly enabled with the `--hwdec`
|
||||
option.
|
||||
- A not too crappy GPU. mpv is not intended to be used with bad GPUs. There are
|
||||
many caveats with drivers or system compositors causing tearing, stutter,
|
||||
etc. On Windows, you might want to make sure the graphics drivers are
|
||||
current. In some cases, ancient fallback video output methods can help
|
||||
(such as `--vo=xv` on Linux), but this use is not recommended or supported.
|
||||
|
||||
|
||||
## Downloads
|
||||
|
||||
Downloads
|
||||
---------
|
||||
|
||||
For semi-official builds and third-party packages please see
|
||||
[mpv.io/installation](http://mpv.io/installation/).
|
||||
|
||||
## Changelog
|
||||
|
||||
|
||||
There is no complete changelog; however, changes to the player core interface
|
||||
are listed in the [interface changelog][interface-changes].
|
||||
|
||||
Changes to the C API are documented in the [client API changelog][api-changes].
|
||||
|
||||
The [release list][releases] has a summary of most of the important changes
|
||||
on every release.
|
||||
|
||||
Changes to the default key bindings are indicated in
|
||||
[restore-old-bindings.conf][restore-old-bindings].
|
||||
|
||||
## Compilation
|
||||
[mpv.io](http://mpv.io/installation/).
|
||||
|
||||
Compilation
|
||||
-----------
|
||||
|
||||
Compiling with full features requires development files for several
|
||||
external libraries. Below is a list of some important requirements.
|
||||
|
||||
The mpv build system uses [waf](https://waf.io/), but we don't store it in the
|
||||
repository. The `./bootstrap.py` script will download the latest version
|
||||
of waf that was tested with the build system.
|
||||
The mpv build system uses *waf* but we don't store it in your source tree. The
|
||||
script './bootstrap.py' will download the latest version of waf that was tested
|
||||
with the build system.
|
||||
|
||||
For a list of the available build options use `./waf configure --help`. If
|
||||
you think you have support for some feature installed but configure fails to
|
||||
@@ -90,28 +40,24 @@ To build the software you can use `./waf build`: the result of the compilation
|
||||
will be located in `build/mpv`. You can use `./waf install` to install mpv
|
||||
to the *prefix* after it is compiled.
|
||||
|
||||
Example:
|
||||
|
||||
./bootstrap.py
|
||||
./waf configure
|
||||
./waf
|
||||
./waf install
|
||||
NOTE: Using the old build system (with `./old-configure`) should still work,
|
||||
but will be removed in a future version of mpv.
|
||||
|
||||
Essential dependencies (incomplete list):
|
||||
|
||||
- gcc or clang
|
||||
- X development headers (xlib, xrandr, xext, xscrnsaver, xinerama, libvdpau,
|
||||
libGL, GLX, EGL, xv, ...)
|
||||
- X development headers (xlib, X extensions, libvdpau, libGL, libXv, ...)
|
||||
- Audio output development headers (libasound/ALSA, pulseaudio)
|
||||
- FFmpeg libraries (libavutil libavcodec libavformat libswscale libavfilter
|
||||
and either libswresample or libavresample)
|
||||
At least FFmpeg 2.1.4 or Libav 10 is required.
|
||||
- zlib
|
||||
- iconv (normally provided by the system libc)
|
||||
- libass (OSD, OSC, text subtitles)
|
||||
- libass
|
||||
- Lua (optional, required for the OSC pseudo-GUI and youtube-dl integration)
|
||||
- libjpeg (optional, used for screenshots only)
|
||||
- uchardet (optional, for subtitle charset detection)
|
||||
- nvdec and vaapi libraries for hardware decoding on Linux (optional)
|
||||
- Enca (optional, for subtitle charset detection)
|
||||
- vdpau and vaapi libraries for hardware decoding on Linux (optional)
|
||||
|
||||
Libass dependencies:
|
||||
|
||||
@@ -124,83 +70,109 @@ Libass dependencies:
|
||||
FFmpeg dependencies:
|
||||
|
||||
- gcc or clang, yasm on x86 and x86_64
|
||||
- OpenSSL or GnuTLS (have to be explicitly enabled when compiling FFmpeg)
|
||||
- libx264/libmp3lame/libfdk-aac if you want to use encoding (have to be
|
||||
explicitly enabled when compiling FFmpeg)
|
||||
- For native DASH playback, FFmpeg needs to be built with --enable-libxml2
|
||||
(although there are security implications, and DAHS support has lots of bugs).
|
||||
- AV1 decoding support requires dav1d.
|
||||
- For good nvidia support on Linux, make sure nv-codec-headers is installed
|
||||
and can be found by configure.
|
||||
- OpenSSL (has to be explicitly enabled when compiling ffmpeg)
|
||||
- libx264/libmp3lame/libfdk-aac if you want to use encoding (has to be
|
||||
explicitly enabled when compiling ffmpeg)
|
||||
- Libav also works, but some features will not work. (See section below.)
|
||||
|
||||
Most of the above libraries are available in suitable versions on normal
|
||||
Linux distributions. For ease of compiling the latest git master of everything,
|
||||
you may wish to use the separately available build wrapper ([mpv-build][mpv-build])
|
||||
which first compiles FFmpeg libraries and libass, and then compiles the player
|
||||
statically linked against those.
|
||||
Linux distributions. However FFmpeg is an exception (distro versions may be
|
||||
too old to work at all or work well). For that reason you may want to use
|
||||
the separately available build wrapper ([mpv-build][mpv-build]) that first compiles FFmpeg
|
||||
libraries and libass, and then compiles the player statically linked against
|
||||
those.
|
||||
|
||||
If you are running Mac OSX and using homebrew we provide [homebrew-mpv][homebrew-mpv], an up
|
||||
to date formula that compiles mpv with sensible dependencies and defaults for
|
||||
OSX.
|
||||
|
||||
If you want to build a Windows binary, you either have to use MSYS2 and MinGW,
|
||||
or cross-compile from Linux with MinGW. See
|
||||
[Windows compilation][windows_compilation].
|
||||
or cross-compile from Linux with MinGW. See [Windows compilation][windows_compilation].
|
||||
|
||||
FFmpeg vs. Libav
|
||||
----------------
|
||||
|
||||
Generally, mpv should work with the latest release as well as the git version
|
||||
of both FFmpeg and Libav. But FFmpeg is preferred, and some mpv features work
|
||||
with FFmpeg only. See the [wiki article][ffmpeg_vs_libav] about the issue.
|
||||
|
||||
|
||||
## Release cycle
|
||||
Release cycle
|
||||
-------------
|
||||
|
||||
Every other month, an arbitrary git snapshot is made, and is assigned
|
||||
a 0.X.0 version number. No further maintenance is done.
|
||||
Every few months, a new release is cut off of the master branch and is assigned
|
||||
a 0.X.0 version number.
|
||||
|
||||
The goal of releases is to make Linux distributions happy. Linux distributions
|
||||
are also expected to apply their own patches in case of bugs and security
|
||||
issues.
|
||||
As part of the maintenance process, minor releases are made, which are assigned
|
||||
0.X.Y version numbers. Minor releases contain bug fixes only. They never merge
|
||||
the master branch, and no features are added to it. Only the latest release is
|
||||
maintained.
|
||||
|
||||
The goal of releases is to provide stability and an unchanged base for the sake
|
||||
of Linux distributions. If you want the newest features, just use the master
|
||||
branch, which is stable most of the time, except sometimes, when it's not.
|
||||
|
||||
Releases other than the latest release are unsupported and unmaintained.
|
||||
|
||||
See the [release policy document][release-policy] for more information.
|
||||
|
||||
## Bug reports
|
||||
|
||||
Bug reports
|
||||
-----------
|
||||
|
||||
Please use the [issue tracker][issue-tracker] provided by GitHub to send us bug
|
||||
reports or feature requests. Follow the template's instructions or the issue
|
||||
will likely be ignored or closed as invalid.
|
||||
reports or feature requests.
|
||||
|
||||
Using the bug tracker as place for simple questions is fine but IRC is
|
||||
recommended (see [Contact](#Contact) below).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
Please read [contribute.md][contribute.md].
|
||||
Contributing
|
||||
------------
|
||||
|
||||
For small changes you can just send us pull requests through GitHub. For bigger
|
||||
changes come and talk to us on IRC before you start working on them. It will
|
||||
make code review easier for both parties later on.
|
||||
|
||||
You can check [the wiki](https://github.com/mpv-player/mpv/wiki/Stuff-to-do)
|
||||
or the [issue tracker](https://github.com/mpv-player/mpv/issues?q=is%3Aopen+is%3Aissue+label%3A%22feature+request%22)
|
||||
for ideas on what you could contribute with.
|
||||
Relation to MPlayer and mplayer2
|
||||
--------------------------------
|
||||
|
||||
## License
|
||||
mpv is based on mplayer2, which in turn is based on the original MPlayer
|
||||
(also called mplayer, mplayer-svn, mplayer1). Many changes have been made, a
|
||||
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.
|
||||
|
||||
GPLv2 "or later" by default, LGPLv2.1 "or later" with `--enable-lgpl`.
|
||||
See [details.](https://github.com/mpv-player/mpv/blob/master/Copyright)
|
||||
mpv was forked because we wanted to modernize MPlayer. This includes
|
||||
removing cruft (including features which stopped making sense 10 years ago),
|
||||
and of course adding modern features. Such huge and intrusive changes made it
|
||||
infeasible to work directly with MPlayer, which is mostly focused on
|
||||
preservation, so a fork had to be made. (Actually, mpv is based on mplayer2,
|
||||
which already started this process of removing cruft.)
|
||||
|
||||
In general, mpv should be considered a completely new program, rather than a
|
||||
MPlayer drop-in replacement.
|
||||
|
||||
## Contact
|
||||
If you are wondering what's different from mplayer2 and MPlayer, an incomplete
|
||||
list of changes is located [here][mplayer-changes].
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
Most activity happens on the IRC channel and the github issue tracker.
|
||||
Most activity happens on the IRC channel and the github issue tracker. The
|
||||
mailing lists are mostly unused.
|
||||
|
||||
- **GitHub issue tracker**: [issue tracker][issue-tracker] (report bugs here)
|
||||
- **User IRC Channel**: `#mpv` on `irc.freenode.net`
|
||||
- **Developer IRC Channel**: `#mpv-devel` on `irc.freenode.net`
|
||||
- **Github issue tracker**: [issue tracker][issue-tracker] (report bugs here)
|
||||
- **User IRC Channel**: `#mpv-player` on `irc.freenode.net`
|
||||
- **Developer IRC Channel**: `#mpv-player-dev` on `irc.freenode.net`
|
||||
- **Users Mailing List**: `mpv-users@googlegroups.com` ([Archive / Subscribe][mpv-users]).
|
||||
- **Devel Mailing List**: `mpv-devel@googlegroups.com` ([Archive / Subscribe][mpv-devel])
|
||||
|
||||
To contact the `mpv` team in private write to `mpv-team@googlegroups.com`. Use
|
||||
only if discretion is required.
|
||||
|
||||
[releases]: https://github.com/mpv-player/mpv/releases
|
||||
[mpv-build]: https://github.com/mpv-player/mpv-build
|
||||
[homebrew-mpv]: https://github.com/mpv-player/homebrew-mpv
|
||||
[issue-tracker]: https://github.com/mpv-player/mpv/issues
|
||||
[mpv-users]: https://groups.google.com/forum/?hl=en#!forum/mpv-users
|
||||
[mpv-devel]: https://groups.google.com/forum/?hl=en#!forum/mpv-devel
|
||||
[ffmpeg_vs_libav]: https://github.com/mpv-player/mpv/wiki/FFmpeg-versus-Libav
|
||||
[release-policy]: https://github.com/mpv-player/mpv/blob/master/DOCS/release-policy.md
|
||||
[windows_compilation]: https://github.com/mpv-player/mpv/blob/master/DOCS/compile-windows.md
|
||||
[interface-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/interface-changes.rst
|
||||
[api-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/client-api-changes.rst
|
||||
[restore-old-bindings]: https://github.com/mpv-player/mpv/blob/master/etc/restore-old-bindings.conf
|
||||
[contribute.md]: https://github.com/mpv-player/mpv/blob/master/DOCS/contribute.md
|
||||
[mplayer-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/mplayer-changes.rst
|
||||
+209
-109
@@ -1,134 +1,234 @@
|
||||
Release 0.30.0
|
||||
==============
|
||||
Release 0.8.3
|
||||
=============
|
||||
|
||||
This release requires FFmpeg 4.0 or newer.
|
||||
This release has replaced the internal Vulkan rendering abstraction
|
||||
with libplacebo's more up-to-date implementation.
|
||||
Changes
|
||||
-------
|
||||
|
||||
- Documentation fixes and updates.
|
||||
- (Client API) Clarify `mpv_opengl_cb_render`'s viewport parameter behavior.
|
||||
|
||||
Features
|
||||
--------
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
Added
|
||||
~~~~~
|
||||
- (X11) Fix crash on `vo_xv:no-colorkey` with the Overlay adapter. (bug #1629)
|
||||
- Make the video equalizer work correctly on some VAAPI drivers. (bug #1647)
|
||||
- Prevent OSD from disappearing when clicking on mozplugger. (bug #1672)
|
||||
- The new DVB-S2 support code, using S2API, now builds on FreeBSD.
|
||||
- Fix decoding of seekable matroska from unseekable network stream. (bug #1656)
|
||||
- (OSX) Fix crashing when closing a VO's window (usually at exit). (bug #1657)
|
||||
- (OSX) Unhide the mouse cursor when over the Dock or Launchpad. (bug #513)
|
||||
- (OSX) Fix mouse cursor autohiding when the player is fullscreen.
|
||||
- `vf_vavpp` (VAAPI postprocessing) now deinterlaces video correctly.
|
||||
- `smb://` streams now use the stream cache (used to be inefficient).
|
||||
- (Windows) Do not hide the mouse cursor when it is hovering the window menu.
|
||||
- Fix 8-channel output on `ao_jack`. (bug #1688)
|
||||
- Fix `--mf-fps` parameter on JPEG files. (bug #1689)
|
||||
- Fix anamorphic scaling being ignored if it was very minor.
|
||||
|
||||
- vo_gpu: vulkan: hwdec_cuda: Add support for Vulkan interop
|
||||
- command: support for async commands
|
||||
- input: support for named arguments
|
||||
- cocoa-cb: add support for mac 10.14 Dark mode and run time switching
|
||||
- vo_gpu: switch to Vulkan API implementation based on libplacebo
|
||||
- context_drm_egl: Add support for presentation feedback
|
||||
- vo_gpu: implement error diffusion for dithering
|
||||
- vo/gpu: hwdec_vdpau: Support direct mode for 4:4:4 content
|
||||
- vo_gpu: hwdec_vaapi: Add Vulkan interop
|
||||
- video, TOOLS: add vf_fingerprint and a skip-logo script
|
||||
- vo_gpu: d3d11: add support for presentation feedback
|
||||
- vo_drm: 30bpp support
|
||||
- cocoa-cb: add support for 10bit opengl rendering
|
||||
- video: add pure gamma TRC curves for 2.0, 2.4 and 2.6
|
||||
- vo_drm: Implement N-buffering and presentation feedback
|
||||
- Reintroduce vo_wayland as vo_wlshm
|
||||
- video: add zimg wrapper
|
||||
- wayland: add presentation time
|
||||
- input: add gamepad support through SDL2
|
||||
This listing is not complete. A complete changelog can be seen by running
|
||||
`git log v0.8.2..v0.8.3` in the git repository.
|
||||
|
||||
Release 0.8.2
|
||||
=============
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
- cocoa-cb: use libmpv's advanced rendering control and timing
|
||||
- vo_gpu: improve tone mapping desaturation
|
||||
- vo_gpu: redesign peak detection algorithm
|
||||
- vo_gpu: allow boosting dark scenes when tone mapping
|
||||
- osc: improve look of seekranges
|
||||
- vo_gpu: x11: remove special vdpau probing, use EGL by default
|
||||
- demux: sort filenames naturally when playing a directory / archive
|
||||
- stream_dvb: rewrite channel switching, remove old stream control
|
||||
- filters: extend vf_format so that it can convert color parameters
|
||||
- Fix OSD placement accidentally messed up in 0.8.1.
|
||||
|
||||
Release 0.8.1
|
||||
=============
|
||||
|
||||
Removed
|
||||
~~~~~~~
|
||||
Changes
|
||||
-------
|
||||
|
||||
- demux, stream: rip out the classic stream cache
|
||||
- vo_gpu: removed internal Vulkan implementation
|
||||
- Remove libdvdread support in favor of libdvdnav
|
||||
- demux, stream: remove much of the optical disc support
|
||||
- Remove classic Linux analog TV support, and DVB runtime controls
|
||||
- demux, stream: remove old rar support in favor of libarchive
|
||||
- vo_gpu: remove mali-fbdev
|
||||
- vo_gpu: remove vdpau/GLX backend
|
||||
- vf_vapourynth: remove Lua backend
|
||||
- vo_gpu: remove hwdec_d3d11eglrgb
|
||||
- DOCS/client-api-changes has been correctly updated for the v0.8.0 release
|
||||
series.
|
||||
- Quality and major perfomance improvements to smoothmotion.
|
||||
- Silence the "[ytdl_hook] WARNING: video doesn't have subtitles" warning.
|
||||
- Other documentation updates.
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
Options and Commands
|
||||
--------------------
|
||||
- Attempt to fix OpenGL shader compilation on Intel windows drivers. (bug
|
||||
#1536)
|
||||
- Attempt to improve the OpenGL shader's compatibility with GLES2.
|
||||
- (Windows) Fix noise when seeking while using wasapi:exclusive. (bug #1529)
|
||||
- Fix the waf-based build system when used with newer versions of waf with
|
||||
python3.
|
||||
- Documentation fixes. (includes bug #1608)
|
||||
|
||||
Added
|
||||
~~~~~
|
||||
New features
|
||||
------------
|
||||
|
||||
- command: add a subprocess command
|
||||
- vo_gpu: added --tone-mapping-max-boost, --hdr-peak-decay-rate, --hdr-scene-threshold-low/high
|
||||
- player: add --demuxer-cache-wait option
|
||||
- Implement backwards playback
|
||||
- demux: add a on-disk cache
|
||||
- demux, command: add another stream recording mechanism, `dump-cache` command
|
||||
- ao_pulse: add --pulse-allow-suspended
|
||||
- command: add video-add/video-remove/video-reload commands
|
||||
- demux_cue: added --demuxer-cue-codepage to select CUE sheet charset
|
||||
- input: add keybind command
|
||||
- command: add sub-start & sub-end properties
|
||||
- video/d3d11: added --d3d11-adapter to select a rendering adapter by name
|
||||
- vo_gpu/d3d11: added --d3d11-output-format for configuring swap chain format
|
||||
- mpv now tries to load '.vtt' subtitles.
|
||||
|
||||
This listing is not complete. A complete changelog can be seen by running
|
||||
`git log v0.8.0..v0.8.1` in the git repository.
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
Release 0.8.0
|
||||
=============
|
||||
|
||||
- vo_gpu: split --linear-scaling into --linear-upscaling and --linear-downscaling
|
||||
- vo_gpu: split --tone-mapping-desaturate into strength and exponent
|
||||
- drm: rename --drm-osd-plane-id to --drm-draw-plane, --drm-video-plane-id to --drm-drmprime-video-plane, --drm-osd-size to --drm-draw-surface-size
|
||||
Changes
|
||||
-------
|
||||
|
||||
Changes that may break users' config files have been annotated with a `(!)`.
|
||||
|
||||
Deprecated
|
||||
~~~~~~~~~~
|
||||
- `(!)` vo_opengl_old has been removed. OpenGL rendering now requires hardware
|
||||
that can do at least OpenGL 2.1, the oldest version supported by vo_opengl.
|
||||
- `(!)` vf_pp has been removed. A version of it can still be accessed through
|
||||
lavfilter (e.g. --vf=lavfi=[pp...]), but it receives no QP information.
|
||||
Also, vf_dlopen no longer passes QP information to its loaded plugin either
|
||||
(it's always 0).
|
||||
- `(!)` vf_softpulldown, vf_swapuv, vf_phase, vf_divtc and vf_ilpack have all
|
||||
been removed. Ports or alternative versions of these filters are available
|
||||
through libavfilter (vf_lavfi).
|
||||
- vf_pullup and vf_noise now are simply wrappers to their libavfilter
|
||||
equivalents. Both are only currently available on FFmpeg (not Libav).
|
||||
- `(!)` ao_portaudio has been removed. There is good support for the native
|
||||
audio drivers of all major desktop platforms, as well as ao_sdl and
|
||||
ao_openal as fallbacks.
|
||||
- `(!)` vo_opengl's `lscale` suboption has been renamed to `scale`; `lradius`
|
||||
is now `scale-radius`, `lparam1` and `lparam2` are now respectively
|
||||
`scale-param1` and `scale-param2`; `lscale-down` is now `scale-down`.
|
||||
The `cscale` suboption remains as is.
|
||||
- `(!)` Several of the `vo_opengl` radius-preset aliases supported by `scale`
|
||||
have been removed; use `scale-radius` to set if needed. For example, use
|
||||
`--vo=opengl:scale=lanczos:scale-radius=2` instead of `scale=lanczos2`.
|
||||
The default radius is recommended for most filters.
|
||||
- `(!)` vo_opengl no longer supports the `stereo` suboption. The anaglyph
|
||||
effect can be reproduced with the stereo3d filter. The quadbuffer support,
|
||||
which requires expensive specialized hardware to begin with, is removed.
|
||||
- `(!)` The `approx-gamma` suboption to vo_opengl has been removed. The
|
||||
BT.1886 specification says that it's actually how it's supposed to be done
|
||||
so it is now the default when `srgb` or `icc-profile` are enabled. This does
|
||||
not include BT.1886's gamma drop.
|
||||
- `(!)` The `no-scale-sep` and `indirect` suboptions to vo_opengl have been
|
||||
removed. These are now autodetected and enabled whenever they would have
|
||||
benefit.
|
||||
- `(!)` The `--lua` and `--lua-opts` parameters / options are now called
|
||||
`--script` and `--script-opts`, respectively. The `lua` subdir of the mpv
|
||||
config dir is also now expected to be called `scripts` instead.
|
||||
- `(!)` The `--fixed-vo` option has been removed. It has been the default for
|
||||
a long time anyway, and disabling fixed-vo is not useful.
|
||||
- vo_opengl_hq has been updated to take into account new features.
|
||||
`fancy-downscaling` and `sigmoid-upscaling` are enabled,
|
||||
"mitchell" is now the default for `scale-down`.
|
||||
- The `sub-visibility` OSD message is now clearer about whether subtitles
|
||||
are hidden or just not available / selected.
|
||||
- The device IDs given to `--audio-device` for use with ao_coreaudio now use
|
||||
UIDs, so they don't change when devices are added/removed or after reboots.
|
||||
- `--msg-level` now also accepts ',' as separator.
|
||||
- (Client API) The client API now refuses to initialize if the LC_NUMERIC
|
||||
locale is not "C".
|
||||
- (Client API) The native type of the `msg-level` parameter is now a key-value
|
||||
list. Setting or reading it as a string still works.
|
||||
- (Slave API) The `get_property` command is now deprecated.
|
||||
- Documentation updates.
|
||||
- PDF documentation is now disabled by default due to rst2pdf being fickle,
|
||||
causing weird build errors.
|
||||
- Print desync messages with negative A/V sync as well. While rare, it could
|
||||
happen with some uses of `--autosync`.
|
||||
|
||||
- options: deprecate --video-aspect, replaced by --video-aspect-override
|
||||
- options: deprecate --record-file, --spirv-compiler
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
- (Windows) Avoid resizing the video window when player is minimized, might
|
||||
address bug #1547.
|
||||
- (NetBSD) Fix build with v4l2.
|
||||
- (Linux) Attempt to address conflicts with the pulseaudio mixer. (bug #1578)
|
||||
- Multiple cdda:// fixes. (bugs #1555, #1560)
|
||||
- VP9 timestamps no longer cause "missing PTS" warnings with new enough FFmpeg
|
||||
builds.
|
||||
- Fix a crash when using H.264 hardware decoding on new enough libavcodecs.
|
||||
(bug #1587)
|
||||
|
||||
Removed
|
||||
~~~~~~~
|
||||
New features
|
||||
------------
|
||||
|
||||
- options: remove deprecated --chapter option
|
||||
- demux: remove "program" property
|
||||
- stream: remove "disc-titles", "disc-title", "disc-title-list", and "angle" properties
|
||||
- cocoa-cb: remove --macos-title-bar-style, replaced by --macos-title-bar-material and --macos-title-bar-appearance
|
||||
- spirv: remove support for --spirv-compiler=nvidia (shaderc is the only remaining option)
|
||||
- vo_opengl now supports frame blending to eliminate stuttering when the video
|
||||
framerate does not nicely match the display framerate through the
|
||||
`smoothmotion` suboption. This is not meant to artificially increase the
|
||||
video's FPS, so there is no "soap opera effect" or difficulties with some
|
||||
video types (e.g. anime).
|
||||
- vo_opengl now supports sigmoidal upscaling (e.g. for fullscreen), which
|
||||
reduces ringing induced by upscaling, enabled through the
|
||||
`sigmoid-upscaling` suboption.
|
||||
- vo_opengl now supports ewa_lanczos (Jinc) scaling, which provides higher
|
||||
quality with less aliasing. It supports an experimental `scale-antiringing`
|
||||
parameter, which tries to further reduce video ringing.
|
||||
- vo_opengl now has a `linear-scaling` suboption, that makes the scalers work
|
||||
in linear light. Implied by the `srgb`, `icc-profile` or the new
|
||||
`sigmoid-upscaling` suboption.
|
||||
- vo_opengl has improved downscaling for higher downscale ratios when
|
||||
`fancy-downscaling` is enabled.
|
||||
- Add `--keep-open=always` to make `--keep-open` apply to all files instead of
|
||||
only the last.
|
||||
- mpv now filters the tags that are printed on the console to try to hide
|
||||
useless metadata. The filter works as a whitelist, and can be configured
|
||||
with the `--display-tags` option.
|
||||
- Add a `--sub-scale-by-window` option that, when set to 'no', prevents
|
||||
subtitles from changing their pixel size when the window changes sizes.
|
||||
- vo_opengl now technically has GLES 2 and 3 support (but not GLES 1). GLES 3
|
||||
support is only tested on Mesa's software emulation. GLES 2 has been tested
|
||||
on nvidia drivers. Both GLES modes are feature deficient and inefficient due
|
||||
to GLES limitations, so they should not be preferred over the standard
|
||||
OpenGL mode.
|
||||
- (X11) vo_opengl now supports the `icc-profile-auto` option on X11 hosts.
|
||||
- The 'A' key now by default cycles through a list of preset aspect ratios.
|
||||
Meant to be used to work around broken files.
|
||||
- There is now a "force" mode for `--loop`. Works like "inf", but tries to
|
||||
open files/streams even if there was an error on the previous attempt.
|
||||
- There is now a `--log-file` option to write mpv's log messages to a specifed
|
||||
file.
|
||||
- There is now a `--audio-file-auto` option to automatically load an external
|
||||
audio file with certain constraints. Will only load external audio if the
|
||||
playing file has a video stream. Set to "exact" by default. (bug #967)
|
||||
- There is now a `--network-timeout` option to specify a timeout in seconds
|
||||
for network access. If 0 (default), uses the libavformat default. If a
|
||||
protocol that doesn't support timeouts is used, this option is ignored.
|
||||
- (X11) The XF86 special keys are now all mappable in `input.conf`. All keys
|
||||
documented in `XF86keysym.h` are available, but only as their numeric codes.
|
||||
- (Linux) The DVB implementation now supports DVB-S2 through S2API.
|
||||
- (Linux) The VDR format for `channels.conf` is now supported and preferred.
|
||||
See http://linuxtv.org/vdrwiki/index.php/Syntax_of_channels.conf for the
|
||||
syntax. Tuning to DVB-S2 channels requires the VDR-format `channels.conf`.
|
||||
- (Linux) There is now a `--dvbin-full-transponder` option for handling
|
||||
special broadcast cases where PIDs switch, or just to work around incomplete
|
||||
PID data.
|
||||
- (Client API) There is now an opengl_cb VO, which receives the OpenGL context
|
||||
from the libmpv client. This allows a client to render libmpv video directly
|
||||
to a provided OpenGL context without having to use --wid embedding.
|
||||
- (Client API) The aforementioned --wid parameter can now be set at any time,
|
||||
but has no effect if a file is already loaded.
|
||||
- (Client API) The list of DVD titles can now be queried.
|
||||
- (Client API) There is now a `filtered-metadata` property, containing only
|
||||
the tags allowed by `--display-tags`.
|
||||
- (Client API) There is now support for XEmbed `--wid` targets, such as a
|
||||
`GtkSocket`'s `gtk_socket_get_id()`.
|
||||
- (Client API) There is now a `file-format` property with a symbolic name
|
||||
for the file format. In some cases this might be a comma separated list
|
||||
of various different extensions due to libavformat idiosyncrasies.
|
||||
- (Client API) There is now a `mouse` command for generating mouse events
|
||||
over the video window.
|
||||
- (Client API) There is now a `partially-seekable` property that indicates
|
||||
whether a file is only considered `seekable` because of the stream cache,
|
||||
but would not be seekable otherwise (e.g. realtime stream, or HTTP with
|
||||
no resume support). Small relative seeks may be fine, but larger seeks
|
||||
will likely fail.
|
||||
- (Client API) There is now an MPV_EVENT_QUEUE_OVERFLOW event that is posted
|
||||
whenever events have to be dropped because the queue is full. No further
|
||||
events are posted until the MPV_EVENT_QUEUE_OVERFLOW is consumed to avoid
|
||||
duplicated posting.
|
||||
- (Client API) There is now a helper `mpv_wait_async_requests()` function
|
||||
that blocks until all known async requests have completed. (bug #1542)
|
||||
- (Client API) There is now a `detected-hwdec` property that returns the
|
||||
detected hardware decoder when one is successfully opened. This probably
|
||||
only returns a valid value after playback has started.
|
||||
- (Client API) There are now `audio_add`, `audio_remove` and `audio_reload`
|
||||
counterparts to the equivalent `sub_` commands for handling external audio
|
||||
files.
|
||||
|
||||
|
||||
Fixes and Minor Enhancements
|
||||
----------------------------
|
||||
|
||||
- context_drm_egl: implement n-buffering
|
||||
- cocoa-cb: add support for custom colored title bar
|
||||
- vo_gpu: x11egl: support Mesa OML sync extension
|
||||
- demux, demux_edl: add extension for tracks sourced from separate streams
|
||||
- context_drm_egl: Use eglGetPlatformDisplayEXT if available
|
||||
- vo_gpu: vulkan: add Android context
|
||||
- wayland: use xdg-decoration if available
|
||||
- vo_gpu: glx: use GLX_OML_sync_control for better vsync reporting
|
||||
- demux: runtime option changing for cache and stream recording
|
||||
- x11: fix ICC profiling for multiple monitors
|
||||
- zsh completion: move generation to runtime and improve
|
||||
|
||||
|
||||
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.29.1..v0.30.0`
|
||||
in the git repository or by visiting either
|
||||
https://github.com/mpv-player/mpv/compare/v0.29.1...v0.30.0 or
|
||||
https://git.srsfckn.biz/mpv/log/?qt=range&q=v0.29.1..v0.30.0
|
||||
This listing is not complete. A complete changelog can be seen by running
|
||||
`git log v0.7.0..v0.8.0` in the git repository.
|
||||
Whitespace-only changes.
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
set -e
|
||||
|
||||
export DEST_OS=win32
|
||||
export CC=gcc
|
||||
export PKG_CONFIG=/usr/bin/pkg-config
|
||||
export PERL=/usr/bin/perl
|
||||
export PYTHON=/usr/bin/python3
|
||||
|
||||
"$PYTHON" bootstrap.py
|
||||
"$PYTHON" waf configure \
|
||||
--check-c-compiler=gcc \
|
||||
--enable-spirv-cross \
|
||||
--enable-d3d-hwaccel \
|
||||
--enable-d3d11 \
|
||||
--enable-jpeg \
|
||||
--enable-lcms2 \
|
||||
--enable-libarchive \
|
||||
--enable-libass \
|
||||
--enable-lua \
|
||||
--enable-rubberband \
|
||||
--enable-shaderc \
|
||||
--enable-uchardet \
|
||||
--enable-vulkan
|
||||
"$PYTHON" waf build
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
set -e
|
||||
|
||||
export PYTHON=/usr/bin/python3
|
||||
|
||||
# Write an empty fonts.conf to speed up fc-cache
|
||||
export FONTCONFIG_FILE=/dummy-fonts.conf
|
||||
cat >"$FONTCONFIG_FILE" <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig></fontconfig>
|
||||
EOF
|
||||
|
||||
# Install build dependencies for mpv
|
||||
pacman -S --noconfirm --needed \
|
||||
$MINGW_PACKAGE_PREFIX-toolchain \
|
||||
$MINGW_PACKAGE_PREFIX-cmake \
|
||||
$MINGW_PACKAGE_PREFIX-lcms2 \
|
||||
$MINGW_PACKAGE_PREFIX-libarchive \
|
||||
$MINGW_PACKAGE_PREFIX-libass \
|
||||
$MINGW_PACKAGE_PREFIX-libjpeg-turbo \
|
||||
$MINGW_PACKAGE_PREFIX-libplacebo \
|
||||
$MINGW_PACKAGE_PREFIX-lua51 \
|
||||
$MINGW_PACKAGE_PREFIX-ninja \
|
||||
$MINGW_PACKAGE_PREFIX-rubberband \
|
||||
$MINGW_PACKAGE_PREFIX-uchardet \
|
||||
$MINGW_PACKAGE_PREFIX-vulkan
|
||||
|
||||
# Delete unused packages to reduce space used in the Appveyor cache
|
||||
pacman -Sc --noconfirm
|
||||
|
||||
# Compile ffmpeg
|
||||
(
|
||||
git clone --depth=1 https://github.com/FFmpeg/ffmpeg.git && cd ffmpeg
|
||||
|
||||
mkdir build && cd build
|
||||
../configure \
|
||||
--prefix=$MINGW_PREFIX \
|
||||
--target-os=mingw32 \
|
||||
--arch=$MSYSTEM_CARCH \
|
||||
--disable-static \
|
||||
--disable-doc \
|
||||
--disable-asm \
|
||||
--enable-gpl \
|
||||
--enable-version3 \
|
||||
--enable-shared \
|
||||
--enable-pic \
|
||||
--enable-d3d11va \
|
||||
--enable-dxva2 \
|
||||
--enable-schannel
|
||||
make -j4 install
|
||||
)
|
||||
|
||||
# Compile shaderc
|
||||
(
|
||||
git clone --depth=1 https://github.com/google/shaderc && cd shaderc
|
||||
"$PYTHON" utils/git-sync-deps
|
||||
|
||||
mkdir build && cd build
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DSHADERC_SKIP_TESTS=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX ..
|
||||
ninja install
|
||||
)
|
||||
|
||||
# Compile SPIRV-Cross
|
||||
(
|
||||
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Cross && cd SPIRV-Cross
|
||||
|
||||
mkdir build && cd build
|
||||
cmake -GNinja -DSPIRV_CROSS_SHARED=ON -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX ..
|
||||
ninja install
|
||||
)
|
||||
+8
-58
@@ -20,24 +20,12 @@ def is_user_lib(objfile, libname):
|
||||
not "libc." in libname and \
|
||||
not "libgcc." in libname and \
|
||||
not os.path.basename(libname) == 'Python' and \
|
||||
not os.path.basename(objfile) in libname and \
|
||||
not "libswift" in libname
|
||||
not os.path.basename(objfile) in libname
|
||||
|
||||
def otool(objfile):
|
||||
command = "otool -L '%s' | grep -e '\t' | awk '{ print $1 }'" % objfile
|
||||
output = subprocess.check_output(command, shell = True, universal_newlines=True)
|
||||
return set(filter(partial(is_user_lib, objfile), output.split()))
|
||||
|
||||
def get_rpaths_dev_tools(binary):
|
||||
command = "otool -l '%s' | grep -A2 LC_RPATH | grep path | grep \"Xcode\|CommandLineTools\"" % binary
|
||||
result = subprocess.check_output(command, shell = True, universal_newlines=True)
|
||||
pathRe = re.compile("^\s*path (.*) \(offset \d*\)$")
|
||||
output = []
|
||||
|
||||
for line in result.splitlines():
|
||||
output.append(pathRe.search(line).group(1).strip())
|
||||
|
||||
return output
|
||||
command = "otool -L %s | grep -e '\t' | awk '{ print $1 }'" % objfile
|
||||
output = subprocess.check_output(command, shell = True)
|
||||
return filter(partial(is_user_lib, objfile), output.split())
|
||||
|
||||
def install_name_tool_change(old, new, objfile):
|
||||
subprocess.call(["install_name_tool", "-change", old, new, objfile])
|
||||
@@ -45,15 +33,9 @@ def install_name_tool_change(old, new, objfile):
|
||||
def install_name_tool_id(name, objfile):
|
||||
subprocess.call(["install_name_tool", "-id", name, objfile])
|
||||
|
||||
def install_name_tool_add_rpath(rpath, binary):
|
||||
subprocess.call(["install_name_tool", "-add_rpath", rpath, binary])
|
||||
|
||||
def install_name_tool_delete_rpath(rpath, binary):
|
||||
subprocess.call(["install_name_tool", "-delete_rpath", rpath, binary])
|
||||
|
||||
def libraries(objfile, result = dict()):
|
||||
libs_list = otool(objfile)
|
||||
result[objfile] = libs_list
|
||||
result[objfile] = set(libs_list)
|
||||
|
||||
for lib in libs_list:
|
||||
if lib not in result:
|
||||
@@ -98,47 +80,15 @@ def process_libraries(libs_dict, binary, processed = []):
|
||||
if p in libs_dict[src]:
|
||||
install_name_tool_change(p, lib_name(p), dst)
|
||||
|
||||
return ls
|
||||
|
||||
def process_swift_libraries(binary):
|
||||
command = ['xcrun', '--find', 'swift-stdlib-tool']
|
||||
swiftStdlibTool = subprocess.check_output(command, universal_newlines=True).strip()
|
||||
# from xcode11 on the dynamic swift libs reside in a separate directory from
|
||||
# the std one, might need versioned paths for future swift versions
|
||||
swiftLibPath = os.path.join(swiftStdlibTool, '../../lib/swift-5.0/macosx')
|
||||
swiftLibPath = os.path.abspath(swiftLibPath)
|
||||
|
||||
command = [swiftStdlibTool, '--copy', '--platform', 'macosx', '--scan-executable', binary, '--destination', lib_path(binary)]
|
||||
|
||||
if os.path.exists(swiftLibPath):
|
||||
command.extend(['--source-libraries', swiftLibPath])
|
||||
|
||||
subprocess.check_output(command, universal_newlines=True)
|
||||
|
||||
print(">> setting additional rpath for swift libraries")
|
||||
install_name_tool_add_rpath("@executable_path/lib", binary)
|
||||
|
||||
def remove_dev_tools_rapths(binary):
|
||||
for path in get_rpaths_dev_tools(binary):
|
||||
install_name_tool_delete_rpath(path, binary)
|
||||
process_libraries(libs_dict, binary, ls)
|
||||
|
||||
def main():
|
||||
binary = os.path.abspath(sys.argv[1])
|
||||
if not os.path.exists(lib_path(binary)):
|
||||
os.makedirs(lib_path(binary))
|
||||
print(">> gathering all linked libraries")
|
||||
libs = libraries(binary)
|
||||
|
||||
print(">> copying and processing all linked libraries")
|
||||
libs_processed = process_libraries(libs, binary)
|
||||
while libs_processed is not None:
|
||||
libs_processed = process_libraries(libs, binary, libs_processed)
|
||||
|
||||
print(">> removing rpath definitions towards dev tools")
|
||||
remove_dev_tools_rapths(binary)
|
||||
|
||||
print(">> copying and processing swift libraries")
|
||||
process_swift_libraries(binary)
|
||||
print(libs)
|
||||
process_libraries(libs, binary)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#! /usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Convert the contents of a file into a C string constant.
|
||||
# Note that the compiler will implicitly add an extra 0 byte at the end
|
||||
# of every string, so code using the string may need to remove that to get
|
||||
# the exact contents of the original file.
|
||||
# FIXME: why not a char array?
|
||||
|
||||
# treat only alphanumeric and not-" punctuation as safe
|
||||
my $unsafe_chars = qr{[^][A-Za-z0-9!#%&'()*+,./:;<=>?^_{|}~ -]};
|
||||
|
||||
for my $file (@ARGV) {
|
||||
open my $fh, '<:raw', $file or next;
|
||||
print "/* Generated from $file */\n";
|
||||
while (<$fh>) {
|
||||
# replace unsafe chars with their equivalent octal escapes
|
||||
s/($unsafe_chars)/\\@{[sprintf '%03o', ord($1)]}/gos;
|
||||
print "\"$_\"\n"
|
||||
}
|
||||
close $fh;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Convert the contents of a file into a C string constant.
|
||||
# Note that the compiler will implicitly add an extra 0 byte at the end
|
||||
# of every string, so code using the string may need to remove that to get
|
||||
# the exact contents of the original file.
|
||||
|
||||
#
|
||||
# This file is part of mpv.
|
||||
#
|
||||
# mpv is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# mpv is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import sys
|
||||
|
||||
# Indexing a byte string yields int on Python 3.x, and a str on Python 2.x
|
||||
def pord(c):
|
||||
return ord(c) if type(c) == str else c
|
||||
|
||||
def file2string(infilename, infile, outfile):
|
||||
outfile.write("// Generated from %s\n\n" % infilename)
|
||||
|
||||
conv = ['\\' + ("%03o" % c) for c in range(256)]
|
||||
safe_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \
|
||||
"0123456789!#%&'()*+,-./:;<=>?[]^_{|}~ "
|
||||
|
||||
for c in safe_chars:
|
||||
conv[ord(c)] = c
|
||||
for c, esc in ("\nn", "\tt", r"\\", '""'):
|
||||
conv[ord(c)] = '\\' + esc
|
||||
for line in infile:
|
||||
outfile.write('"' + ''.join(conv[pord(c)] for c in line) + '"\n')
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open(sys.argv[1], 'rb') as infile:
|
||||
file2string(sys.argv[1], infile, sys.stdout)
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script is expected to be called as TOOLS/gen-osd-font.sh (it will access
|
||||
# TOOLS/mpv-osd-symbols.sfdir), and it will write sub/osd_font.otf.
|
||||
|
||||
# Needs fontforge with python scripting
|
||||
|
||||
fontforge -lang=py -c 'f=open(argv[1]); f.generate(argv[2])' \
|
||||
TOOLS/mpv-osd-symbols.sfdir sub/osd_font.otf
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script is expected to be called as TOOLS/gen-x11-icon.sh (it will access
|
||||
# etc/mpv-icon...), and it will write video/out/x11_icon.bin.
|
||||
|
||||
conv() {
|
||||
echo
|
||||
identify -format "icon: %w %h" "$1"
|
||||
convert "$1" -depth 8 rgba:-
|
||||
}
|
||||
|
||||
(echo "# File generated by gen-x11-icon.sh" ;
|
||||
conv etc/mpv-icon-8bit-16x16.png ;
|
||||
conv etc/mpv-icon-8bit-32x32.png ;
|
||||
conv etc/mpv-icon-8bit-64x64.png) | gzip -c > video/out/x11_icon.bin
|
||||
+7
-7
@@ -47,7 +47,7 @@ judge()
|
||||
progressive=$((progressive + progressive1))
|
||||
undetermined=$((undetermined + undetermined1))
|
||||
done <<EOF
|
||||
$(testfun "$@" | sed 's/:/: /g')
|
||||
$(testfun "$@")
|
||||
EOF
|
||||
|
||||
interlaced=$((bff + tff))
|
||||
@@ -95,18 +95,18 @@ case "$verdict" in
|
||||
exit 0
|
||||
;;
|
||||
interlaced-tff)
|
||||
judge "$@" --vf-clr --vf-pre=lavfi=\[setfield=tff\],pullup
|
||||
judge "$@" --vf-clr --vf-pre=pullup --field-dominance=top
|
||||
case "$verdict" in
|
||||
progressive)
|
||||
[ -n "$ILDETECT_DRY_RUN" ] || \
|
||||
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=tff\],pullup
|
||||
$ILDETECT_MPV "$@" --vf-pre=pullup --field-dominance=top
|
||||
r=$?
|
||||
[ $r -eq 0 ] || exit $((r | 16))
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
[ -n "$ILDETECT_DRY_RUN" ] || \
|
||||
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=tff\],yadif
|
||||
$ILDETECT_MPV "$@" --vf-pre=yadif --field-dominance=top
|
||||
r=$?
|
||||
[ $r -eq 0 ] || exit $((r | 16))
|
||||
exit 2
|
||||
@@ -114,18 +114,18 @@ case "$verdict" in
|
||||
esac
|
||||
;;
|
||||
interlaced-bff)
|
||||
judge "$@" --vf-clr --vf-pre=lavfi=\[setfield=bff\],pullup
|
||||
judge "$@" --vf-clr --vf-pre=pullup --field-dominance=bottom
|
||||
case "$verdict" in
|
||||
progressive)
|
||||
[ -n "$ILDETECT_DRY_RUN" ] || \
|
||||
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=bff\],pullup
|
||||
$ILDETECT_MPV "$@" --vf-pre=pullup --field-dominance=bottom
|
||||
r=$?
|
||||
[ $r -eq 0 ] || exit $((r | 16))
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
[ -n "$ILDETECT_DRY_RUN" ] || \
|
||||
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=bff\],yadif
|
||||
$ILDETECT_MPV "$@" --vf-pre=yadif --field-dominance=bottom
|
||||
r=$?
|
||||
[ $r -eq 0 ] || exit $((r | 16))
|
||||
exit 2
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# ABSTRACT: Module collection to parse Matroska files.
|
||||
package Parse::Matroska;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<use>s L<Parse::Matroska::Reader>. See the documentation
|
||||
of the modules mentioned in L</"SEE ALSO"> for more information
|
||||
in how to use this module.
|
||||
|
||||
It's intended for this module to contain high-level interfaces
|
||||
to the other modules in the distribution.
|
||||
|
||||
=head1 SOURCE CODE
|
||||
|
||||
L<https://github.com/Kovensky/Parse-Matroska>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Parse::Matroska::Reader>, L<Parse::Matroska::Element>,
|
||||
L<Parse::Matroska::Definitions>.
|
||||
|
||||
=cut
|
||||
|
||||
use Parse::Matroska::Reader;
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,357 @@
|
||||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# ABSTRACT: internal EBML grammar definitions
|
||||
package Parse::Matroska::Definitions;
|
||||
|
||||
use Parse::Matroska::Utils qw{uniq uncamelize};
|
||||
|
||||
use Exporter;
|
||||
our @ISA = qw{Exporter};
|
||||
our @EXPORT_OK = qw{elem_by_hexid %EBML_DEFINITION %MATROSKA_DEFINITION};
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Parse::Matroska::Definitions qw{elem_by_hexid};
|
||||
my $ebml_id = elem_by_hexid('1a45dfa3');
|
||||
print "EBML ID $ebml_id->{elid}'s name: $ebml_id->{name}";
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Contains the definition of the EBML grammar as expected in
|
||||
Matroska files. This module is meant mostly for internal use.
|
||||
|
||||
As this was extended from a script in mpv-player, some data
|
||||
generated is apparently useless for regular module users
|
||||
but is still relevant to the mpv-player script. Such data
|
||||
is annotated as being for mpv compatibility.
|
||||
|
||||
=head1 NOTE
|
||||
|
||||
The API of this module is not yet considered stable.
|
||||
|
||||
=head1 GLOBALS
|
||||
|
||||
These global variables are considered B<immutable>.
|
||||
|
||||
=head2 @Parse::Matroska::Definitions::global_elem_list
|
||||
|
||||
A global list of known matroska elements. Useful for
|
||||
mpv's matroska script, used for generating C headers
|
||||
that parse matroska.
|
||||
|
||||
=head2 %Parse::Matroska::Definitions::global_elem_dict
|
||||
|
||||
A global hash of known matroska elements. Used internally
|
||||
by L</elem_by_hexid($id)>.
|
||||
|
||||
=cut
|
||||
|
||||
@Parse::Matroska::Definitions::global_elem_list = ();
|
||||
%Parse::Matroska::Definitions::global_elem_dict = ();
|
||||
|
||||
=head2 %EBML_DEFINITION
|
||||
|
||||
Optionally-importable hash of known EBML IDs belonging
|
||||
to the EBML generic grammar.
|
||||
|
||||
=head2 %MATROSKA_DEFINITION
|
||||
|
||||
Optionally-importable hash of known EBML IDs belonging
|
||||
to the Matroska-specific grammar.
|
||||
|
||||
=cut
|
||||
|
||||
our %EBML_DEFINITION = define_ebml();
|
||||
our %MATROSKA_DEFINITION = define_matroska();
|
||||
|
||||
=method elem_by_hexid($id)
|
||||
|
||||
Returns an EBML Element Definition corresponding to the provided
|
||||
hexadecimal string. Returns C<undef> if the element is unknown.
|
||||
|
||||
=cut
|
||||
sub elem_by_hexid {
|
||||
my ($elid) = @_;
|
||||
return $Parse::Matroska::Definitions::global_elem_dict{$elid};
|
||||
}
|
||||
|
||||
################################################
|
||||
### Helper functions for document definition ###
|
||||
################################################
|
||||
|
||||
# used by elem when setting the 'valname' key
|
||||
use constant TYPE_MAP => {
|
||||
uint => 'uint64_t',
|
||||
str => 'struct bstr',
|
||||
binary => 'struct bstr',
|
||||
ebml_id => 'uint32_t',
|
||||
float => 'double',
|
||||
sint => 'int64_t',
|
||||
};
|
||||
|
||||
# this will be localized to "MATROSKA" or "EBML" on the elem declarations
|
||||
our $ELEM_DEFINE_TYPE = undef;
|
||||
|
||||
=method elem($name,$elid,$valtype)
|
||||
|
||||
NOTE: never call this function yourself; it changes data structures
|
||||
that are considered immutable outside of this package.
|
||||
|
||||
Internal API function that generates the EBML Element Definitions.
|
||||
|
||||
This API function returns an array which first element is C<$elid>
|
||||
and the second is a generated hash. The generated hash is stored
|
||||
in the @global_elem_list and %global_elem_dict.
|
||||
|
||||
The generated hash contains:
|
||||
|
||||
=for :list
|
||||
= name
|
||||
The EBML Element's name, given through C<$name>.
|
||||
= elid
|
||||
The EBML Element's hex id, given through C<$elid>. Used for lookups by L</elem_by_hexid($id)>.
|
||||
= valtype
|
||||
The EBML Element's type, given through C<$valtype>, except when C<$valtype> is an arrayref.
|
||||
= multiple
|
||||
If C<$name> ends with a C<*>, this is set as true and strips the C<*> from L</name>. Used to
|
||||
mark elements that may be repeated.
|
||||
= subelements
|
||||
An arrayref of elements that may be children of this element, given through C<$valtype> if it
|
||||
is an arrayref. Sets L</valtype> to C<sub> if there are subelements.
|
||||
= subids
|
||||
An arrayref listing all the L</elid>s of subelements, C<uniq>ified.
|
||||
|
||||
The following elements are for mpv compatibility:
|
||||
|
||||
=for :list
|
||||
= definename
|
||||
Name used for generating C #defines.
|
||||
= fieldname
|
||||
Name used for generating C struct fields.
|
||||
= structname
|
||||
Name used for generating C struct names.
|
||||
= ebmltype
|
||||
A pre-#defined constant to describe the element's type.
|
||||
= valname
|
||||
Typename used when declaring a struct field referring to this element.
|
||||
|
||||
=cut
|
||||
sub elem {
|
||||
my %e = (name => shift, elid => shift, valtype => shift);
|
||||
|
||||
# strip * from name, set 'multiple' if there was one
|
||||
$e{multiple} = scalar $e{name} =~ s/\*$//;
|
||||
|
||||
# ELEM_DEFINE_TYPE is either MATROSKA or EBML
|
||||
$e{definename} = "${ELEM_DEFINE_TYPE}_ID_".uc($e{name});
|
||||
$e{fieldname} = uncamelize $e{name};
|
||||
$e{structname} = "ebml_$e{fieldname}";
|
||||
|
||||
if (ref $e{valtype} eq 'HASH') {
|
||||
$e{subelements} = $e{valtype};
|
||||
$e{subids} = uniq map { $_->{elid} } values %{$e{subelements}};
|
||||
$e{valtype} = 'sub';
|
||||
$e{ebmltype} = 'EBML_TYPE_SUBELEMENTS';
|
||||
$e{valname} = "struct $e{structname}";
|
||||
} else {
|
||||
$e{ebmltype} = "EBML_TYPE_\U$e{valtype}";
|
||||
die "Unrecognized value type $e{valtype}" unless
|
||||
defined ($e{valname} = TYPE_MAP->{$e{valtype}});
|
||||
}
|
||||
my $e = \%e;
|
||||
push @Parse::Matroska::Definitions::global_elem_list, $e;
|
||||
$Parse::Matroska::Definitions::global_elem_dict{$e{elid}} = $e;
|
||||
return ($e{elid}, $e);
|
||||
}
|
||||
|
||||
#############################################
|
||||
### EBML and Matroska document definitons ###
|
||||
#############################################
|
||||
|
||||
=method define_ebml
|
||||
|
||||
Internal function that defines the EBML generic grammar.
|
||||
|
||||
Must not be called from outside the package.
|
||||
|
||||
=cut
|
||||
sub define_ebml {
|
||||
local $ELEM_DEFINE_TYPE = 'EBML';
|
||||
return (
|
||||
elem('EBML', '1a45dfa3', {
|
||||
elem('EBMLVersion', '4286', 'uint'),
|
||||
elem('EBMLReadVersion', '42f7', 'uint'),
|
||||
elem('EBMLMaxIDLength', '42f2', 'uint'),
|
||||
elem('EBMLMaxSizeLength', '42f3', 'uint'),
|
||||
elem('DocType', '4282', 'str'),
|
||||
elem('DocTypeVersion', '4287', 'uint'),
|
||||
elem('DocTypeReadVersion', '4285', 'uint'),
|
||||
}),
|
||||
|
||||
elem('CRC32', 'bf', 'binary'),
|
||||
elem('Void', 'ec', 'binary'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
=method define_matroska
|
||||
|
||||
Internal function that defines the Matroska-specific EBML grammar.
|
||||
|
||||
Must not be called from outside the package.
|
||||
|
||||
=cut
|
||||
sub define_matroska {
|
||||
local $ELEM_DEFINE_TYPE = 'MATROSKA';
|
||||
return (
|
||||
elem('Segment', '18538067', {
|
||||
elem('SeekHead*', '114d9b74', {
|
||||
elem('Seek*', '4dbb', {
|
||||
elem('SeekID', '53ab', 'ebml_id'),
|
||||
elem('SeekPosition', '53ac', 'uint'),
|
||||
}),
|
||||
}),
|
||||
|
||||
elem('Info*', '1549a966', {
|
||||
elem('SegmentUID', '73a4', 'binary'),
|
||||
elem('PrevUID', '3cb923', 'binary'),
|
||||
elem('NextUID', '3eb923', 'binary'),
|
||||
elem('TimecodeScale', '2ad7b1', 'uint'),
|
||||
elem('DateUTC', '4461', 'sint'),
|
||||
elem('Title', '7ba9', 'str'),
|
||||
elem('MuxingApp', '4d80', 'str'),
|
||||
elem('WritingApp', '5741', 'str'),
|
||||
elem('Duration', '4489', 'float'),
|
||||
}),
|
||||
|
||||
elem('Cluster*', '1f43b675', {
|
||||
elem('Timecode', 'e7', 'uint'),
|
||||
elem('BlockGroup*', 'a0', {
|
||||
elem('Block', 'a1', 'binary'),
|
||||
elem('BlockDuration', '9b', 'uint'),
|
||||
elem('ReferenceBlock*', 'fb', 'sint'),
|
||||
elem('DiscardPadding', '75A2', 'sint'),
|
||||
}),
|
||||
elem('SimpleBlock*', 'a3', 'binary'),
|
||||
}),
|
||||
|
||||
elem('Tracks*', '1654ae6b', {
|
||||
elem('TrackEntry*', 'ae', {
|
||||
elem('TrackNumber', 'd7', 'uint'),
|
||||
elem('TrackUID', '73c5', 'uint'),
|
||||
elem('TrackType', '83', 'uint'),
|
||||
elem('FlagEnabled', 'b9', 'uint'),
|
||||
elem('FlagDefault', '88', 'uint'),
|
||||
elem('FlagForced', '55aa', 'uint'),
|
||||
elem('FlagLacing', '9c', 'uint'),
|
||||
elem('MinCache', '6de7', 'uint'),
|
||||
elem('MaxCache', '6df8', 'uint'),
|
||||
elem('DefaultDuration', '23e383', 'uint'),
|
||||
elem('TrackTimecodeScale', '23314f', 'float'),
|
||||
elem('MaxBlockAdditionID', '55ee', 'uint'),
|
||||
elem('Name', '536e', 'str'),
|
||||
elem('Language', '22b59c', 'str'),
|
||||
elem('CodecID', '86', 'str'),
|
||||
elem('CodecPrivate', '63a2', 'binary'),
|
||||
elem('CodecName', '258688', 'str'),
|
||||
elem('CodecDecodeAll', 'aa', 'uint'),
|
||||
elem('CodecDelay', '56AA', 'uint'),
|
||||
elem('SeekPreRoll', '56BB', 'uint'),
|
||||
elem('Video', 'e0', {
|
||||
elem('FlagInterlaced', '9a', 'uint'),
|
||||
elem('PixelWidth', 'b0', 'uint'),
|
||||
elem('PixelHeight', 'ba', 'uint'),
|
||||
elem('DisplayWidth', '54b0', 'uint'),
|
||||
elem('DisplayHeight', '54ba', 'uint'),
|
||||
elem('DisplayUnit', '54b2', 'uint'),
|
||||
elem('FrameRate', '2383e3', 'float'),
|
||||
elem('ColourSpace', '2eb524', 'binary'),
|
||||
elem('StereoMode', '53b8', 'uint'),
|
||||
}),
|
||||
elem('Audio', 'e1', {
|
||||
elem('SamplingFrequency', 'b5', 'float'),
|
||||
elem('OutputSamplingFrequency', '78b5', 'float'),
|
||||
elem('Channels', '9f', 'uint'),
|
||||
elem('BitDepth', '6264', 'uint'),
|
||||
}),
|
||||
elem('ContentEncodings', '6d80', {
|
||||
elem('ContentEncoding*', '6240', {
|
||||
elem('ContentEncodingOrder', '5031', 'uint'),
|
||||
elem('ContentEncodingScope', '5032', 'uint'),
|
||||
elem('ContentEncodingType', '5033', 'uint'),
|
||||
elem('ContentCompression', '5034', {
|
||||
elem('ContentCompAlgo', '4254', 'uint'),
|
||||
elem('ContentCompSettings', '4255', 'binary'),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
||||
elem('Cues', '1c53bb6b', {
|
||||
elem('CuePoint*', 'bb', {
|
||||
elem('CueTime', 'b3', 'uint'),
|
||||
elem('CueTrackPositions*', 'b7', {
|
||||
elem('CueTrack', 'f7', 'uint'),
|
||||
elem('CueClusterPosition', 'f1', 'uint'),
|
||||
elem('CueRelativePosition','f0', 'uint'),
|
||||
elem('CueDuration', 'b2', 'uint'),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
||||
elem('Attachments', '1941a469', {
|
||||
elem('AttachedFile*', '61a7', {
|
||||
elem('FileDescription', '467e', 'str'),
|
||||
elem('FileName', '466e', 'str'),
|
||||
elem('FileMimeType', '4660', 'str'),
|
||||
elem('FileData', '465c', 'binary'),
|
||||
elem('FileUID', '46ae', 'uint'),
|
||||
}),
|
||||
}),
|
||||
|
||||
elem('Chapters', '1043a770', {
|
||||
elem('EditionEntry*', '45b9', {
|
||||
elem('EditionUID', '45bc', 'uint'),
|
||||
elem('EditionFlagHidden', '45bd', 'uint'),
|
||||
elem('EditionFlagDefault', '45db', 'uint'),
|
||||
elem('EditionFlagOrdered', '45dd', 'uint'),
|
||||
elem('ChapterAtom*', 'b6', {
|
||||
elem('ChapterUID', '73c4', 'uint'),
|
||||
elem('ChapterTimeStart', '91', 'uint'),
|
||||
elem('ChapterTimeEnd', '92', 'uint'),
|
||||
elem('ChapterFlagHidden', '98', 'uint'),
|
||||
elem('ChapterFlagEnabled', '4598', 'uint'),
|
||||
elem('ChapterSegmentUID', '6e67', 'binary'),
|
||||
elem('ChapterSegmentEditionUID', '6ebc', 'uint'),
|
||||
elem('ChapterDisplay*', '80', {
|
||||
elem('ChapString', '85', 'str'),
|
||||
elem('ChapLanguage*', '437c', 'str'),
|
||||
elem('ChapCountry*', '437e', 'str'),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
elem('Tags*', '1254c367', {
|
||||
elem('Tag*', '7373', {
|
||||
elem('Targets', '63c0', {
|
||||
elem('TargetTypeValue', '68ca', 'uint'),
|
||||
elem('TargetTrackUID', '63c5', 'uint'),
|
||||
elem('TargetEditionUID', '63c9', 'uint'),
|
||||
elem('TargetChapterUID', '63c4', 'uint'),
|
||||
elem('TargetAttachmentUID', '63c6', 'uint'),
|
||||
}),
|
||||
elem('SimpleTag*', '67c8', {
|
||||
elem('TagName', '45a3', 'str'),
|
||||
elem('TagLanguage', '447a', 'str'),
|
||||
elem('TagString', '4487', 'str'),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,331 @@
|
||||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# ABSTRACT: a mid-level representation of an EBML element
|
||||
package Parse::Matroska::Element;
|
||||
|
||||
use Carp;
|
||||
use List::Util qw{first};
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Parse::Matroska::Reader;
|
||||
my $reader = Parse::Matroska::Reader->new($path);
|
||||
my $elem = $reader->read_element;
|
||||
|
||||
print "ID: $elem->{elid}\n";
|
||||
print "Name: $elem->{name}\n";
|
||||
print "Length: $elem->{content_len}\n";
|
||||
print "Type: $elem->{type}\n";
|
||||
print "Child count: ", scalar(@{$elem->all_children}), "\n";
|
||||
if ($elem->{type} eq 'sub') {
|
||||
while (my $chld = $elem->next_child) {
|
||||
print "Child Name: $chld->{name}\n";
|
||||
}
|
||||
} else {
|
||||
print "Value: ", $elem->get_value, "\n";
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Represents a single Matroska element as decoded by
|
||||
L<Parse::Matroska::Reader>. This is essentially a hash
|
||||
augmented with functions for delay-loading of binary
|
||||
values and children elements.
|
||||
|
||||
=head1 NOTE
|
||||
|
||||
The API of this module is not yet considered stable.
|
||||
|
||||
=attr elid
|
||||
|
||||
The EBML Element ID, suitable for passing to
|
||||
L<Parse::Matroska::Definitions/elem_by_hexid>.
|
||||
|
||||
=attr name
|
||||
|
||||
The EBML Element's name.
|
||||
|
||||
=attr type
|
||||
|
||||
The EBML Element's type. Can be C<uint>, C<sint>,
|
||||
C<float>, C<ebml_id>, C<str> or C<binary>. See L</value>
|
||||
for details.
|
||||
|
||||
Equivalent to
|
||||
C<elem_by_hexid($elem-E<gt>{value})-E<gt>{valtype}>.
|
||||
|
||||
=attr value
|
||||
|
||||
The EBML Element's value. Should be obtained through
|
||||
L</get_value>.
|
||||
|
||||
Is an unicode string if the L</type> is C<str>, that is,
|
||||
the string has already been decoded by L<Encode/decode>.
|
||||
|
||||
Is C<undef> if the L</type> is C<binary> and the contents
|
||||
were delay-loaded and not yet read. L</get_value> will
|
||||
do the delayed load if needed.
|
||||
|
||||
Is an arrayref if the L</type> is C<sub>, containing
|
||||
the children nodes that were already loaded.
|
||||
|
||||
Is a hashref if the L</type> is C<ebml_id>, containing
|
||||
the referred element's information as defined in
|
||||
L<Parse::Matroska::Definitions>. Calling
|
||||
C<elem_by_hexid($elem-E<gt>{value}-E<gt>{elid})> will
|
||||
return the same object as $elem->{value}.
|
||||
|
||||
=attr full_len
|
||||
|
||||
The entire length of this EBML Element, including
|
||||
the header's.
|
||||
|
||||
=attr size_len
|
||||
|
||||
The length of the size marker. Used when calculating
|
||||
L</full_len> from L</content_len>
|
||||
|
||||
=attr content_len
|
||||
|
||||
The length of the contents of this EBML Element,
|
||||
which excludes the header.
|
||||
|
||||
=attr reader
|
||||
|
||||
A weakened reference to the associated
|
||||
L<Parse::Matroska::Reader>.
|
||||
|
||||
=method new(%hash)
|
||||
|
||||
Creates a new Element initialized with the hash
|
||||
given as argument.
|
||||
|
||||
=cut
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
$self->initialize(@_);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=method initialize(%hash)
|
||||
|
||||
Called by L</new> on initialization.
|
||||
|
||||
=cut
|
||||
sub initialize {
|
||||
my ($self, %args) = @_;
|
||||
for (keys %args) {
|
||||
$self->{$_} = $args{$_};
|
||||
}
|
||||
$self->{depth} = 0 unless $self->{depth};
|
||||
}
|
||||
|
||||
=method skip
|
||||
|
||||
Called by the user to ignore the contents of this EBML node.
|
||||
Needed when ignoring the children of a node.
|
||||
|
||||
=cut
|
||||
sub skip {
|
||||
my ($self) = @_;
|
||||
my $reader = $self->{reader};
|
||||
return unless $reader; # we don't have to skip if there's no reader
|
||||
my $pos = $reader->getpos;
|
||||
croak "Too late to skip, reads were already done"
|
||||
if $pos ne $self->{data_pos};
|
||||
$reader->skip($self->{content_len});
|
||||
}
|
||||
|
||||
=method get_value($keep_bin)
|
||||
|
||||
Returns the value contained by this EBML element.
|
||||
|
||||
If the element has children, returns an arrayref to
|
||||
the children elements that were already encountered.
|
||||
|
||||
If the element's type is C<binary> and the value was
|
||||
delay-loaded, does the reading now.
|
||||
|
||||
If $keep_bin is true, the delay-loaded data is kept
|
||||
as the L</value>, otherwise, further calls to
|
||||
C<get_value> will reread the data from the L</reader>.
|
||||
|
||||
=cut
|
||||
sub get_value {
|
||||
my ($self, $keep_bin) = @_;
|
||||
|
||||
return undef if $self->{type} eq 'skip';
|
||||
return $self->{value} if $self->{value};
|
||||
|
||||
my $reader = $self->{reader} or
|
||||
croak "The associated Reader has been deleted";
|
||||
|
||||
# delay-loaded 'binary'
|
||||
if ($self->{type} eq 'binary') {
|
||||
croak "Cannot seek in the current Reader" unless $self->{data_pos};
|
||||
# seek to the data position...
|
||||
$reader->setpos($self->{data_pos});
|
||||
# read the data, keeping it in value if requested
|
||||
if ($keep_bin) {
|
||||
$self->{value} = $reader->readlen($self->{content_len});
|
||||
return $self->{value};
|
||||
} else {
|
||||
return $reader->readlen($self->{content_len});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
=method next_child($read_bin)
|
||||
|
||||
Builtin iterator; reads and returns the next child element.
|
||||
Always returns undef if the type isn't C<sub>.
|
||||
|
||||
Returns undef at the end of the iterator and resets itself to
|
||||
point to the first element; so calling L</next_child($read_bin)>
|
||||
after the iterator returned C<undef> will return the first child.
|
||||
|
||||
The optional C<$read_bin> parameter has the children elements
|
||||
not delay-load their value if their type is C<binary>.
|
||||
|
||||
If all children elements have already been read, return
|
||||
each element in-order as would be given by
|
||||
L</all_children($recurse,$read_bin)>.
|
||||
|
||||
=cut
|
||||
sub next_child {
|
||||
my ($self, $read_bin) = @_;
|
||||
return unless $self->{type} eq 'sub';
|
||||
|
||||
if ($self->{_all_children_read}) {
|
||||
my $idx = $self->{_last_child} ||= 0;
|
||||
if ($idx == @{$self->{value}}) {
|
||||
# reset the iterator, returning undef once
|
||||
$self->{_last_child} = 0;
|
||||
return;
|
||||
}
|
||||
my $ret = $self->{value}->[$idx];
|
||||
|
||||
++$idx;
|
||||
$self->{_last_child} = $idx;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $len = defined $self->{remaining_len}
|
||||
? $self->{remaining_len}
|
||||
: $self->{content_len};
|
||||
|
||||
if ($len == 0) {
|
||||
# we've read all children; switch into $self->{value} iteration mode
|
||||
$self->{_all_children_read} = 1;
|
||||
# return undef since the iterator will reset
|
||||
return;
|
||||
}
|
||||
|
||||
$self->{pos_offset} ||= 0;
|
||||
my $pos = $self->{data_pos};
|
||||
my $reader = $self->{reader} or croak "The associated reader has been deleted";
|
||||
$reader->setpos($pos);
|
||||
$reader->{fh}->seek($self->{pos_offset}, 1) if $pos;
|
||||
|
||||
my $chld = $reader->read_element($read_bin);
|
||||
return undef unless defined $chld;
|
||||
$self->{pos_offset} += $chld->{full_len};
|
||||
|
||||
$self->{remaining_len} = $len - $chld->{full_len};
|
||||
|
||||
if ($self->{remaining_len} < 0) {
|
||||
croak "Child elements consumed $self->{remaining_len} more bytes than parent $self->{name} contained";
|
||||
}
|
||||
|
||||
$chld->{depth} = $self->{depth} + 1;
|
||||
$self->{value} ||= [];
|
||||
|
||||
push @{$self->{value}}, $chld;
|
||||
|
||||
return $chld;
|
||||
}
|
||||
|
||||
=method all_children($recurse,$read_bin)
|
||||
|
||||
Calls L</populate_children($recurse,$read_bin)> on self
|
||||
and returns an arrayref with the children nodes.
|
||||
|
||||
Both C<$recurse> and C<$read_bin> are optional and default
|
||||
to false.
|
||||
|
||||
=cut
|
||||
sub all_children {
|
||||
my ($self, $recurse, $read_bin) = @_;
|
||||
$self->populate_children($recurse, $read_bin);
|
||||
return $self->{value};
|
||||
}
|
||||
|
||||
=method children_by_name($name)
|
||||
|
||||
Searches in the already read children elements for all
|
||||
elements with the EBML name C<$name>. Returns an array
|
||||
containing all found elements. On scalar context,
|
||||
returns only the first element found.
|
||||
|
||||
Croaks if the element's C<type> isn't C<sub>.
|
||||
|
||||
=cut
|
||||
sub children_by_name {
|
||||
my ($self, $name) = @_;
|
||||
return unless defined wantarray; # don't do work if work isn't wanted
|
||||
croak "Element can't have children" unless $self->{type} eq 'sub';
|
||||
|
||||
my @found = grep { $_->{name} eq $name } @{$self->{value}};
|
||||
return @found if wantarray; # list
|
||||
return shift @found if defined wantarray; # scalar
|
||||
}
|
||||
|
||||
=method populate_children($recurse,$read_bin)
|
||||
|
||||
Populates the internal array of children elements, that is,
|
||||
requests that the associated L<Matroska::Parser::Reader> reads
|
||||
all children elements. Returns itself.
|
||||
|
||||
Returns false if the element's C<type> isn't C<sub>.
|
||||
|
||||
If C<$recurse> is provided and is true, the method will call
|
||||
itself in the children elements with the same parameters it
|
||||
received; this will build a full EBML tree.
|
||||
|
||||
If C<$read_bin> is provided and is true, disables delay-loading
|
||||
of the contents of C<binary>-type nodes, reading the contents
|
||||
to memory.
|
||||
|
||||
If both C<$recurse> and C<$read_bin> are true, entire EBML trees
|
||||
can be loaded without requiring seeks, thus behaving correctly
|
||||
on unseekable streams. If C<$read_bin> is false, the entire EBML
|
||||
tree is still loaded, but calling L</get_value> on C<binary>-type
|
||||
nodes will produce an error on unseekable streams.
|
||||
|
||||
=cut
|
||||
sub populate_children {
|
||||
my ($self, $recurse, $read_bin) = @_;
|
||||
|
||||
return unless $self->{type} eq 'sub';
|
||||
|
||||
if (@{$self->{value}} && $recurse) {
|
||||
# only recurse
|
||||
foreach (@{$self->{value}}) {
|
||||
$_->populate_children($recurse, $read_bin);
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
while (my $chld = $self->next_child($read_bin)) {
|
||||
$chld->populate_children($recurse, $read_bin) if $recurse;
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,426 @@
|
||||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# ABSTRACT: a low-level reader for EBML files
|
||||
package Parse::Matroska::Reader;
|
||||
|
||||
use Parse::Matroska::Definitions qw{elem_by_hexid};
|
||||
use Parse::Matroska::Element;
|
||||
|
||||
use Carp;
|
||||
use Scalar::Util qw{openhandle weaken};
|
||||
use IO::Handle;
|
||||
use IO::File;
|
||||
use List::Util qw{first};
|
||||
use Encode;
|
||||
|
||||
use constant BIGINT_TRY => 'Pari,GMP,FastCalc';
|
||||
use Math::BigInt try => BIGINT_TRY;
|
||||
use Math::BigRat try => BIGINT_TRY;
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Parse::Matroska::Reader;
|
||||
my $reader = Parse::Matroska::Reader->new($path);
|
||||
$reader->close;
|
||||
$reader->open(\$string_with_matroska_data);
|
||||
|
||||
my $elem = $reader->read_element;
|
||||
print "Element ID: $elem->{elid}\n";
|
||||
print "Element name: $elem->{name}\n";
|
||||
if ($elem->{type} ne 'sub') {
|
||||
print "Element value: $elem->get_value\n";
|
||||
} else {
|
||||
while (my $child = $elem->next_child) {
|
||||
print "Child element: $child->{name}\n";
|
||||
}
|
||||
}
|
||||
$reader->close;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Reads EBML data, which is used in Matroska files.
|
||||
This is a low-level reader which is meant to be used as a backend
|
||||
for higher level readers. TODO: write the high level readers :)
|
||||
|
||||
=head1 NOTE
|
||||
|
||||
The API of this module is not yet considered stable.
|
||||
|
||||
=method new
|
||||
|
||||
Creates a new reader.
|
||||
Calls L</open($arg)> with its arguments if provided.
|
||||
|
||||
=cut
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
$self->open(@_) if @_;
|
||||
return $self;
|
||||
}
|
||||
|
||||
=method open($arg)
|
||||
|
||||
Creates the internal filehandle. The argument can be:
|
||||
|
||||
=for :list
|
||||
* An open filehandle or L<IO::Handle> object.
|
||||
The filehandle is not C<dup()>ed, so calling L</close> in this
|
||||
object will close the given filehandle as well.
|
||||
* A scalar containing a path to a file.
|
||||
* On perl v5.14 or newer, a scalarref pointing to EBML data.
|
||||
For similar functionality in older perls, give an L<IO::String> object
|
||||
or the handle to an already C<open>ed scalarref.
|
||||
|
||||
=cut
|
||||
sub open {
|
||||
my ($self, $arg) = @_;
|
||||
$self->{fh} = openhandle($arg) || IO::File->new($arg, "<:raw")
|
||||
or croak "Can't open $arg: $!";
|
||||
}
|
||||
|
||||
=method close
|
||||
|
||||
Closes the internal filehandle.
|
||||
|
||||
=cut
|
||||
sub close {
|
||||
my ($self) = @_;
|
||||
$self->{fh}->close;
|
||||
delete $self->{fh};
|
||||
}
|
||||
|
||||
# equivalent to $self->readlen(1), possibly faster
|
||||
sub _getc {
|
||||
my ($self) = @_;
|
||||
my $c = $self->{fh}->getc;
|
||||
croak "Can't do read of length 1: $!" if !defined $c && $!;
|
||||
return $c;
|
||||
}
|
||||
|
||||
=method readlen($length)
|
||||
|
||||
Reads C<$length> bytes from the internal filehandle.
|
||||
|
||||
=cut
|
||||
sub readlen {
|
||||
my ($self, $len) = @_;
|
||||
my $data;
|
||||
my $readlen = $self->{fh}->read($data, $len);
|
||||
croak "Can't do read of length $len: $!"
|
||||
unless defined $readlen;
|
||||
return $data;
|
||||
}
|
||||
|
||||
# converts a byte string into an integer
|
||||
# we do so by converting the integer into a hex string (big-endian)
|
||||
# and then reading the hex-string into an integer
|
||||
sub _bin2int($) {
|
||||
my ($bin) = @_;
|
||||
# if the length is larger than 3
|
||||
# the resulting integer might be larger than INT_MAX
|
||||
if (length($bin) > 3) {
|
||||
return Math::BigInt->from_hex(unpack("H*", $bin));
|
||||
}
|
||||
return hex(unpack("H*", $bin));
|
||||
}
|
||||
|
||||
# creates a floating-point number with the given mantissa and exponent
|
||||
sub _ldexp {
|
||||
my ($mantissa, $exponent) = @_;
|
||||
my $r = new Math::BigRat($mantissa);
|
||||
return $r * Math::BigRat->new(2)**$exponent;
|
||||
}
|
||||
|
||||
# NOTE: the read_* functions are hard to read because they're ports
|
||||
# of even harder to read python functions.
|
||||
# TODO: make them readable
|
||||
|
||||
=method read_id
|
||||
|
||||
Reads an EBML ID atom in hexadecimal string format, suitable
|
||||
for passing to L<Parse::Matroska::Definitions/elem_by_hexid($id)>.
|
||||
|
||||
=cut
|
||||
sub read_id {
|
||||
my ($self) = @_;
|
||||
my $t = $self->_getc;
|
||||
return undef unless defined $t;
|
||||
my $i = 0;
|
||||
my $mask = 1<<7;
|
||||
|
||||
if (ord($t) == 0) {
|
||||
croak "Matroska Syntax error: first byte of ID was \\0"
|
||||
}
|
||||
until (ord($t) & $mask) {
|
||||
++$i;
|
||||
$mask >>= 1;
|
||||
}
|
||||
# return hex string of the bytes we just read
|
||||
return unpack "H*", ($t . $self->readlen($i));
|
||||
}
|
||||
|
||||
=method read_size
|
||||
|
||||
Reads an EBML Data Size atom, which immediately follows
|
||||
an EBML ID atom.
|
||||
|
||||
This returns an array consisting of:
|
||||
|
||||
=for :list
|
||||
0. The length of the Data Size atom.
|
||||
1. The value encoded in the Data Size atom, which is the length of all the data following it.
|
||||
|
||||
=cut
|
||||
sub read_size {
|
||||
my ($self) = @_;
|
||||
my $t = $self->_getc;
|
||||
my $i = 0;
|
||||
my $mask = 1<<7;
|
||||
|
||||
if (ord($t) == 0) {
|
||||
croak "Matroska Syntax error: first byte of data size was \\0"
|
||||
}
|
||||
until (ord($t) & $mask) {
|
||||
++$i;
|
||||
$mask >>= 1;
|
||||
}
|
||||
$t = $t & chr($mask-1); # strip length bits (keep only significant bits)
|
||||
return ($i+1, _bin2int $t . $self->readlen($i));
|
||||
}
|
||||
|
||||
=method read_str($length)
|
||||
|
||||
Reads a string of length C<$length> bytes from the internal filehandle.
|
||||
The string is already L<Encode/decode>d from C<UTF-8>, which is the
|
||||
standard Matroska string encoding.
|
||||
|
||||
=cut
|
||||
{
|
||||
my $utf8 = find_encoding("UTF-8");
|
||||
sub read_str {
|
||||
my ($self, $length) = @_;
|
||||
return $utf8->decode($self->readlen($length));
|
||||
}
|
||||
}
|
||||
|
||||
=method read_uint($length)
|
||||
|
||||
Reads an unsigned integer of length C<$length> bytes
|
||||
from the internal filehandle.
|
||||
|
||||
Returns a L<Math::BigInt> object if C<$length> is greater
|
||||
than 4.
|
||||
|
||||
=cut
|
||||
sub read_uint {
|
||||
my ($self, $length) = @_;
|
||||
return _bin2int $self->readlen($length);
|
||||
}
|
||||
|
||||
=method read_sint($length)
|
||||
|
||||
Reads a signed integer of length C<$length> bytes
|
||||
from the internal filehandle.
|
||||
|
||||
Returns a L<Math::BigInt> object if C<$length> is greater
|
||||
than 4.
|
||||
|
||||
=cut
|
||||
sub read_sint {
|
||||
my ($self, $length) = @_;
|
||||
my $i = $self->read_uint($length);
|
||||
|
||||
# Apply 2's complement to the unsigned int
|
||||
my $mask = int(2 ** ($length * 8 - 1));
|
||||
# if the most significant bit is set...
|
||||
if ($i & $mask) {
|
||||
# subtract the MSB twice
|
||||
$i -= 2 * $mask;
|
||||
}
|
||||
return $i;
|
||||
}
|
||||
|
||||
=method read_float($length)
|
||||
|
||||
Reads an IEEE floating point number of length C<$length>
|
||||
bytes from the internal filehandle.
|
||||
|
||||
Only lengths C<4> and C<8> are supported (C C<float> and C<double>).
|
||||
|
||||
=cut
|
||||
{
|
||||
my $b1 = new Math::BigInt 1;
|
||||
|
||||
sub read_float {
|
||||
my ($self, $length) = @_;
|
||||
my $i = new Math::BigInt $self->read_uint($length)->bstr;
|
||||
my $f;
|
||||
|
||||
# These evil expressions reinterpret an unsigned int as IEEE binary floats
|
||||
if ($length == 4) {
|
||||
$f = _ldexp(($i & ((1<<23) - 1)) + (1<<23), ($i>>23 & ((1<<8) - 1)) - 150);
|
||||
$f = -$f if $i & ($b1<<31);
|
||||
} elsif ($length == 8) {
|
||||
$f = _ldexp(($i & (($b1<<52) - 1)) + ($b1<<52), ($i>>52 & ((1<<12) - 1)) - 1075);
|
||||
$f = -$f if $i & ($b1<<63);
|
||||
} else {
|
||||
croak "Matroska Syntax error: unsupported IEEE float byte size $length";
|
||||
}
|
||||
|
||||
return $f;
|
||||
}
|
||||
}
|
||||
|
||||
=method read_ebml_id($length)
|
||||
|
||||
Reads an EBML ID when it's encoded as the data inside another
|
||||
EBML element, that is, when the enclosing element's C<type> is
|
||||
C<ebml_id>.
|
||||
|
||||
This returns a hashref with the EBML element description as
|
||||
defined in L<Parse::Matroska::Definitions>.
|
||||
|
||||
=cut
|
||||
sub read_ebml_id {
|
||||
my ($self, $length) = @_;
|
||||
return elem_by_hexid(unpack("H*", $self->readlen($length)));
|
||||
}
|
||||
|
||||
=method skip($length)
|
||||
|
||||
Skips C<$length> bytes in the internal filehandle.
|
||||
|
||||
=cut
|
||||
sub skip {
|
||||
my ($self, $len) = @_;
|
||||
return if $self->{fh}->can('seek') && $self->{fh}->seek($len, 1);
|
||||
$self->readlen($len);
|
||||
return;
|
||||
}
|
||||
|
||||
=method getpos
|
||||
|
||||
Wrapper for L<IO::Seekable/$io-E<gt>getpos> in the internal filehandle.
|
||||
|
||||
Returns undef if the internal filehandle can't C<getpos>.
|
||||
|
||||
=cut
|
||||
sub getpos {
|
||||
my ($self) = @_;
|
||||
return undef unless $self->{fh}->can('getpos');
|
||||
return $self->{fh}->getpos;
|
||||
}
|
||||
|
||||
=method setpos($pos)
|
||||
|
||||
Wrapper for L<IO::Seekable/$io-E<gt>setpos> in the internal filehandle.
|
||||
|
||||
Returns C<undef> if the internal filehandle can't C<setpos>.
|
||||
|
||||
Croaks if C<setpos> does not seek to the requested position,
|
||||
that is, if calling C<getpos> does not yield the same object
|
||||
as the C<$pos> argument.
|
||||
|
||||
=cut
|
||||
sub setpos {
|
||||
my ($self, $pos) = @_;
|
||||
return undef unless $pos && $self->{fh}->can('setpos');
|
||||
|
||||
my $ret = $self->{fh}->setpos($pos);
|
||||
croak "Cannot seek to correct position"
|
||||
unless $self->getpos eq $pos;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
=method read_element($read_bin)
|
||||
|
||||
Reads a full EBML element from the internal filehandle.
|
||||
|
||||
Returns a L<Parse::Matroska::Element> object initialized with
|
||||
the read data. If C<read_bin> is not present or is false, will
|
||||
delay-load the contents of C<binary> type elements, that is,
|
||||
they will only be loaded when calling C<get_value> on the
|
||||
returned L<Parse::Matroska::Element> object.
|
||||
|
||||
Does not read the children of the element if its type is
|
||||
C<sub>. Look into the L<Parse::Matroska::Element> interface
|
||||
for details in how to read children elements.
|
||||
|
||||
Pass a true C<$read_bin> if the stream being read is not
|
||||
seekable (C<getpos> is undef) and the contents of C<binary>
|
||||
elements is desired, otherwise seeking errors or internal
|
||||
filehandle corruption might occur.
|
||||
|
||||
=cut
|
||||
sub read_element {
|
||||
my ($self, $read_bin) = @_;
|
||||
return undef if $self->{fh}->eof;
|
||||
|
||||
my $elem_pos = $self->getpos;
|
||||
|
||||
my $elid = $self->read_id;
|
||||
my $elem_def = elem_by_hexid($elid);
|
||||
my ($size_len, $content_len) = $self->read_size;
|
||||
my $full_len = length($elid)/2 + $size_len + $content_len;
|
||||
|
||||
my $elem = Parse::Matroska::Element->new(
|
||||
elid => $elid,
|
||||
name => $elem_def && $elem_def->{name},
|
||||
type => $elem_def && $elem_def->{valtype},
|
||||
size_len => $size_len,
|
||||
content_len => $content_len,
|
||||
full_len => $full_len,
|
||||
reader => $self,
|
||||
elem_pos => $elem_pos,
|
||||
data_pos => $self->getpos,
|
||||
);
|
||||
weaken($elem->{reader});
|
||||
|
||||
if (defined $elem_def) {
|
||||
if ($elem->{type} eq 'sub') {
|
||||
$elem->{value} = [];
|
||||
} elsif ($elem->{type} eq 'str') {
|
||||
$elem->{value} = $self->read_str($content_len);
|
||||
} elsif ($elem->{type} eq 'ebml_id') {
|
||||
$elem->{value} = $self->read_ebml_id($content_len);
|
||||
} elsif ($elem->{type} eq 'uint') {
|
||||
$elem->{value} = $self->read_uint($content_len);
|
||||
} elsif ($elem->{type} eq 'sint') {
|
||||
$elem->{value} = $self->read_sint($content_len);
|
||||
} elsif ($elem->{type} eq 'float') {
|
||||
$elem->{value} = $self->read_float($content_len);
|
||||
} elsif ($elem->{type} eq 'skip') {
|
||||
$self->skip($content_len);
|
||||
} elsif ($elem->{type} eq 'binary') {
|
||||
if ($read_bin) {
|
||||
$elem->{value} = $self->readlen($content_len);
|
||||
} else {
|
||||
$self->skip($content_len);
|
||||
}
|
||||
} else {
|
||||
die "Matroska Definition error: type $elem->{valtype} unknown"
|
||||
}
|
||||
} else {
|
||||
$self->skip($content_len);
|
||||
}
|
||||
return $elem;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 CAVEATS
|
||||
|
||||
Children elements have to be processed as soon as an element
|
||||
with children is found, or their children ignored with
|
||||
L<Parse::Matroska::Element/skip>. Not doing so doesn't cause
|
||||
errors but results in an invalid structure, with constant C<0>
|
||||
depth.
|
||||
|
||||
To work correctly in unseekable streams, either the contents
|
||||
of C<binary>-type elements has to be ignored or the C<read_bin>
|
||||
flag to C<read_element> has to be true.
|
||||
@@ -0,0 +1,37 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# ABSTRACT: internally-used helper functions
|
||||
package Parse::Matroska::Utils;
|
||||
|
||||
use Exporter;
|
||||
our @ISA = qw{Exporter};
|
||||
our @EXPORT_OK = qw{uniq uncamelize};
|
||||
|
||||
=method uniq(@array)
|
||||
|
||||
The same as L<List::MoreUtils/"uniq LIST">.
|
||||
Included to avoid depending on it since it's
|
||||
not a core module.
|
||||
|
||||
=cut
|
||||
sub uniq(@) {
|
||||
my %seen;
|
||||
return grep { !$seen{$_}++ } @_;
|
||||
}
|
||||
|
||||
=method uncamelize($string)
|
||||
|
||||
Converts a "StringLikeTHIS" into a
|
||||
"string_like_this".
|
||||
|
||||
=cut
|
||||
sub uncamelize($) {
|
||||
local $_ = shift;
|
||||
# lc followed by UC: lc_UC
|
||||
s/(?<=[a-z])([A-Z])/_\L$1/g;
|
||||
# UC followed by two lc: _UClclc
|
||||
s/([A-Z])(?=[a-z]{2})/_\L$1/g;
|
||||
# strip leading _ that the second regexp might add; lowercase all
|
||||
s/^_//; lc
|
||||
}
|
||||
@@ -10,11 +10,3 @@ to mpv's command line.
|
||||
|
||||
Where appropriate, they may also be placed in ~/.config/mpv/scripts/ from
|
||||
where they will be automatically loaded when mpv starts.
|
||||
|
||||
This is only a small selection of internally maintained scripts. Some of them
|
||||
are just for testing mpv internals, or serve as examples. An extensive
|
||||
user-edited list of 3rd party scripts is available here:
|
||||
|
||||
https://github.com/mpv-player/mpv/wiki/User-Scripts
|
||||
|
||||
(Anyone can add their own scripts to that list.)
|
||||
@@ -1,155 +0,0 @@
|
||||
-- This script adds control to the dynamic range compression ffmpeg
|
||||
-- filter including key bindings for adjusting parameters.
|
||||
--
|
||||
-- See https://ffmpeg.org/ffmpeg-filters.html#acompressor for explanation
|
||||
-- of the parameteres.
|
||||
|
||||
local mp = require 'mp'
|
||||
local options = require 'mp.options'
|
||||
|
||||
local o = {
|
||||
default_enable = false,
|
||||
show_osd = true,
|
||||
osd_timeout = 4000,
|
||||
filter_label = mp.get_script_name(),
|
||||
|
||||
key_toggle = 'n',
|
||||
key_increase_threshold = 'F1',
|
||||
key_decrease_threshold = 'Shift+F1',
|
||||
key_increase_ratio = 'F2',
|
||||
key_decrease_ratio = 'Shift+F2',
|
||||
key_increase_knee = 'F3',
|
||||
key_decrease_knee = 'Shift+F3',
|
||||
key_increase_makeup = 'F4',
|
||||
key_decrease_makeup = 'Shift+F4',
|
||||
key_increase_attack = 'F5',
|
||||
key_decrease_attack = 'Shift+F5',
|
||||
key_increase_release = 'F6',
|
||||
key_decrease_release = 'Shift+F6',
|
||||
|
||||
default_threshold = -25.0,
|
||||
default_ratio = 3.0,
|
||||
default_knee = 2.0,
|
||||
default_makeup = 8.0,
|
||||
default_attack = 20.0,
|
||||
default_release = 250.0,
|
||||
|
||||
step_threshold = -2.5,
|
||||
step_ratio = 1.0,
|
||||
step_knee = 1.0,
|
||||
step_makeup = 1.0,
|
||||
step_attack = 10.0,
|
||||
step_release = 10.0,
|
||||
}
|
||||
options.read_options(o)
|
||||
|
||||
local params = {
|
||||
{ name = 'attack', min=0.01, max=2000, hide_default=true, dB='' },
|
||||
{ name = 'release', min=0.01, max=9000, hide_default=true, dB='' },
|
||||
{ name = 'threshold', min= -30, max= 0, hide_default=false, dB='dB' },
|
||||
{ name = 'ratio', min= 1, max= 20, hide_default=false, dB='' },
|
||||
{ name = 'knee', min= 1, max= 10, hide_default=true, dB='dB' },
|
||||
{ name = 'makeup', min= 0, max= 24, hide_default=false, dB='dB' },
|
||||
}
|
||||
|
||||
local function parse_value(value)
|
||||
-- Using nil here because tonumber differs between lua 5.1 and 5.2 when parsing fractions in combination with explicit base argument set to 10.
|
||||
-- And we can't omit it because gsub returns 2 values which would get unpacked and cause more problems. Gotta love scripting languages.
|
||||
return tonumber(value:gsub('dB$', ''), nil)
|
||||
end
|
||||
|
||||
local function format_value(value, dB)
|
||||
return string.format('%g%s', value, dB)
|
||||
end
|
||||
|
||||
local function show_osd(filter)
|
||||
if not o.show_osd then
|
||||
return
|
||||
end
|
||||
|
||||
if not filter.enabled then
|
||||
mp.commandv('show-text', 'Dynamic range compressor: disabled', o.osd_timeout)
|
||||
return
|
||||
end
|
||||
|
||||
local pretty = {}
|
||||
for _,param in ipairs(params) do
|
||||
local value = parse_value(filter.params[param.name])
|
||||
if not (param.hide_default and value == o['default_' .. param.name]) then
|
||||
pretty[#pretty+1] = string.format('%s: %g%s', param.name:gsub("^%l", string.upper), value, param.dB)
|
||||
end
|
||||
end
|
||||
|
||||
if #pretty == 0 then
|
||||
pretty = ''
|
||||
else
|
||||
pretty = '\n(' .. table.concat(pretty, ', ') .. ')'
|
||||
end
|
||||
|
||||
mp.commandv('show-text', 'Dynamic range compressor: enabled' .. pretty, o.osd_timeout)
|
||||
end
|
||||
|
||||
local function get_filter()
|
||||
local af = mp.get_property_native('af', {})
|
||||
|
||||
for i = 1, #af do
|
||||
if af[i].label == o.filter_label then
|
||||
return af, i
|
||||
end
|
||||
end
|
||||
|
||||
af[#af+1] = {
|
||||
name = 'acompressor',
|
||||
label = o.filter_label,
|
||||
enabled = false,
|
||||
params = {},
|
||||
}
|
||||
|
||||
for _,param in pairs(params) do
|
||||
af[#af].params[param.name] = format_value(o['default_' .. param.name], param.dB)
|
||||
end
|
||||
|
||||
return af, #af
|
||||
end
|
||||
|
||||
local function toggle_acompressor()
|
||||
local af, i = get_filter()
|
||||
af[i].enabled = not af[i].enabled
|
||||
mp.set_property_native('af', af)
|
||||
show_osd(af[i])
|
||||
end
|
||||
|
||||
local function update_param(name, increment)
|
||||
for _,param in pairs(params) do
|
||||
if param.name == string.lower(name) then
|
||||
local af, i = get_filter()
|
||||
local value = parse_value(af[i].params[param.name])
|
||||
value = math.max(param.min, math.min(value + increment, param.max))
|
||||
af[i].params[param.name] = format_value(value, param.dB)
|
||||
af[i].enabled = true
|
||||
mp.set_property_native('af', af)
|
||||
show_osd(af[i])
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
mp.msg.error('Unknown parameter "' .. name .. '"')
|
||||
end
|
||||
|
||||
mp.add_key_binding(o.key_toggle, "toggle-acompressor", toggle_acompressor)
|
||||
mp.register_script_message('update-param', update_param)
|
||||
|
||||
for _,param in pairs(params) do
|
||||
for direction,step in pairs({increase=1, decrease=-1}) do
|
||||
mp.add_key_binding(o['key_' .. direction .. '_' .. param.name],
|
||||
'acompressor-' .. direction .. '-' .. param.name,
|
||||
function() update_param(param.name, step*o['step_' .. param.name]); end,
|
||||
{ repeatable = true })
|
||||
end
|
||||
end
|
||||
|
||||
if o.default_enable then
|
||||
local af, i = get_filter()
|
||||
af[i].enabled = true
|
||||
mp.set_property_native('af', af)
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
-- Handles the edge case where previous attempts to init audio have failed, but
|
||||
-- might start working due to a newly added device. This is required in
|
||||
-- particular for ao=wasapi, since the internal IMMNotificationClient code that
|
||||
-- normally triggers ao-reload will not be running in this case.
|
||||
|
||||
function do_reload()
|
||||
mp.command("ao-reload")
|
||||
reloading = nil
|
||||
end
|
||||
|
||||
function on_audio_device_list_change()
|
||||
if mp.get_property("current-ao") == "null" and not reloading then
|
||||
mp.msg.verbose("audio-device-list changed: reloading audio")
|
||||
-- avoid calling ao-reload too often
|
||||
reloading = mp.add_timeout(0.5, do_reload)
|
||||
end
|
||||
end
|
||||
|
||||
mp.set_property("options/audio-fallback-to-null", "yes")
|
||||
mp.observe_property("audio-device-list", "native", on_audio_device_list_change)
|
||||
@@ -1,8 +0,0 @@
|
||||
local utils = require("mp.utils")
|
||||
|
||||
mp.observe_property("audio-device-list", "native", function(name, val)
|
||||
print("Audio device list changed:")
|
||||
for index, e in ipairs(val) do
|
||||
print(" - '" .. e.name .. "' (" .. e.description .. ")")
|
||||
end
|
||||
end)
|
||||
@@ -66,8 +66,8 @@ function autocrop_start()
|
||||
-- insert the cropdetect filter
|
||||
ret=mp.command(
|
||||
string.format(
|
||||
'vf add @%s:cropdetect=limit=%f:round=2:reset=0',
|
||||
cropdetect_label, 24/255
|
||||
'vf add @%s:lavfi=graph="cropdetect=limit=24:round=2:reset=0"',
|
||||
cropdetect_label
|
||||
)
|
||||
)
|
||||
-- wait to gather data
|
||||
@@ -79,7 +79,6 @@ function do_crop()
|
||||
local cropdetect_metadata = mp.get_property_native(
|
||||
string.format("vf-metadata/%s", cropdetect_label)
|
||||
)
|
||||
|
||||
-- use it to crop if its valid
|
||||
if cropdetect_metadata then
|
||||
if cropdetect_metadata["lavfi.cropdetect.w"]
|
||||
@@ -87,7 +86,7 @@ function do_crop()
|
||||
and cropdetect_metadata["lavfi.cropdetect.x"]
|
||||
and cropdetect_metadata["lavfi.cropdetect.y"]
|
||||
then
|
||||
mp.command(string.format("vf add @%s:lavfi-crop=w=%s:h=%s:x=%s:y=%s",
|
||||
mp.command(string.format("vf add @%s:crop=%s:%s:%s:%s",
|
||||
crop_label,
|
||||
cropdetect_metadata["lavfi.cropdetect.w"],
|
||||
cropdetect_metadata["lavfi.cropdetect.h"],
|
||||
|
||||
+66
-58
@@ -2,16 +2,21 @@
|
||||
-- appropriate deinterlacing filter based on a short section of the
|
||||
-- currently playing video.
|
||||
--
|
||||
-- It registers the key-binding ctrl+d, which when pressed, inserts the filters
|
||||
-- ``vf=idet,lavfi-pullup,idet``. After 4 seconds, it removes these
|
||||
-- filters and decides whether the content is progressive, interlaced, or
|
||||
-- telecined and the interlacing field dominance.
|
||||
-- It registers the key-binding ctrl+d, which when pressed, inserts
|
||||
-- the filter vf=lavfi=idet. After 4 second, it examines the results
|
||||
-- to determine whether the content progressive or interlaced and the
|
||||
-- interlacing field dominance. It immediately sets the latter within
|
||||
-- mpv.
|
||||
--
|
||||
-- Based on this information, it may set mpv's ``deinterlace`` property (which
|
||||
-- usually inserts the yadif filter), or insert the ``pullup`` filter if the
|
||||
-- content is telecined. It also sets field dominance with lavfi setfield.
|
||||
-- If the content is judged not to be progressive, it may be either
|
||||
-- interlaced or telecined. To determine which one, the video is
|
||||
-- seeked back to the detection starting point with the "pullup"
|
||||
-- filter inserted. After another four seconds, if idet thinks that
|
||||
-- the pulled up viedo is "progressive", then pullup is the correct
|
||||
-- filter and this script leaves it in places while removing the idet
|
||||
-- filter. Otherwise, the content plain interlaced and mpv's deinterlace
|
||||
-- property is set. This will usually insert the yadif deinterlacing filter.
|
||||
--
|
||||
-- OPTIONS:
|
||||
-- The default detection time may be overridden by adding
|
||||
--
|
||||
-- --script-opts=autodeint.detect_seconds=<number of seconds>
|
||||
@@ -22,15 +27,16 @@
|
||||
-- To see counts of the various types of frames for each detection phase,
|
||||
-- the verbosity can be increased with
|
||||
--
|
||||
-- --msg-level=autodeint=v
|
||||
-- --msg-level autodeint=v
|
||||
--
|
||||
-- This script requires a recent version of ffmpeg for which the idet
|
||||
-- filter adds the required metadata.
|
||||
|
||||
require "mp.msg"
|
||||
|
||||
script_name = mp.get_script_name()
|
||||
detect_label = string.format("%s-detect", script_name)
|
||||
pullup_label = string.format("%s", script_name)
|
||||
dominance_label = string.format("%s-dominance", script_name)
|
||||
ivtc_detect_label = string.format("%s-ivtc-detect", script_name)
|
||||
|
||||
-- number of seconds to gather cropdetect data
|
||||
detect_seconds = tonumber(mp.get_opt(string.format("%s.detect_seconds", script_name)))
|
||||
@@ -53,10 +59,6 @@ function del_filter_if_present(label)
|
||||
return false
|
||||
end
|
||||
|
||||
local function add_vf(label, filter)
|
||||
return mp.command(('vf add @%s:%s'):format(label, filter))
|
||||
end
|
||||
|
||||
function start_detect()
|
||||
-- exit if detection is already in progress
|
||||
if timer then
|
||||
@@ -66,43 +68,42 @@ function start_detect()
|
||||
|
||||
mp.set_property("deinterlace","no")
|
||||
del_filter_if_present(pullup_label)
|
||||
del_filter_if_present(dominance_label)
|
||||
|
||||
-- insert the detection filters
|
||||
if not (add_vf(detect_label, 'idet') and
|
||||
add_vf(dominance_label, 'setfield=mode=auto') and
|
||||
add_vf(pullup_label, 'lavfi-pullup') and
|
||||
add_vf(ivtc_detect_label, 'idet')) then
|
||||
mp.msg.error("failed to insert detection filters")
|
||||
percent_pos = mp.get_property("percent-pos")
|
||||
|
||||
-- insert the detection filter
|
||||
local cmd = string.format('vf add @%s:lavfi=graph="idet"', detect_label)
|
||||
if not mp.command(cmd) then
|
||||
mp.msg.error("failed to insert detection filter")
|
||||
return
|
||||
end
|
||||
|
||||
-- wait to gather data
|
||||
timer = mp.add_timeout(detect_seconds, select_filter)
|
||||
timer = mp.add_timeout(detect_seconds, judge_field_dominance)
|
||||
end
|
||||
|
||||
function stop_detect()
|
||||
del_filter_if_present(detect_label)
|
||||
del_filter_if_present(ivtc_detect_label)
|
||||
timer = nil
|
||||
mp.set_property("playback-pos", percent_pos)
|
||||
end
|
||||
|
||||
progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3, 4
|
||||
|
||||
function judge(label)
|
||||
function judge()
|
||||
-- get the metadata
|
||||
local result = mp.get_property_native(string.format("vf-metadata/%s", label))
|
||||
local num_tff = tonumber(result["lavfi.idet.multiple.tff"])
|
||||
local num_bff = tonumber(result["lavfi.idet.multiple.bff"])
|
||||
local num_progressive = tonumber(result["lavfi.idet.multiple.progressive"])
|
||||
local num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"])
|
||||
local num_interlaced = num_tff + num_bff
|
||||
local num_determined = num_interlaced + num_progressive
|
||||
local result = mp.get_property_native(string.format("vf-metadata/%s", detect_label))
|
||||
num_tff = tonumber(result["lavfi.idet.multiple.tff"])
|
||||
num_bff = tonumber(result["lavfi.idet.multiple.bff"])
|
||||
num_progressive = tonumber(result["lavfi.idet.multiple.progressive"])
|
||||
num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"])
|
||||
num_interlaced = num_tff + num_bff
|
||||
num_determined = num_interlaced + num_progressive
|
||||
|
||||
mp.msg.verbose(label.." progressive = "..num_progressive)
|
||||
mp.msg.verbose(label.." interlaced-tff = "..num_tff)
|
||||
mp.msg.verbose(label.." interlaced-bff = "..num_bff)
|
||||
mp.msg.verbose(label.." undetermined = "..num_undetermined)
|
||||
mp.msg.verbose("progressive = "..num_progressive)
|
||||
mp.msg.verbose("interlaced-tff = "..num_tff)
|
||||
mp.msg.verbose("interlaced-bff = "..num_bff)
|
||||
mp.msg.verbose("undetermined = "..num_undetermined)
|
||||
|
||||
if num_determined < num_undetermined then
|
||||
mp.msg.warn("majority undetermined frames")
|
||||
@@ -118,39 +119,46 @@ function judge(label)
|
||||
end
|
||||
end
|
||||
|
||||
function select_filter()
|
||||
-- handle the first detection filter results
|
||||
local verdict = judge(detect_label)
|
||||
local ivtc_verdict = judge(ivtc_detect_label)
|
||||
local dominance = "auto"
|
||||
function judge_field_dominance()
|
||||
verdict = judge()
|
||||
if verdict == progressive then
|
||||
mp.msg.info("progressive: doing nothing")
|
||||
stop_detect()
|
||||
del_filter_if_present(dominance_label)
|
||||
del_filter_if_present(pullup_label)
|
||||
mp.msg.info("progressive: doing nothing")
|
||||
return
|
||||
else
|
||||
if verdict == interlaced_tff then
|
||||
dominance = "tff"
|
||||
add_vf(dominance_label, 'setfield=mode='..dominance)
|
||||
elseif verdict == interlaced_bff then
|
||||
dominance = "bff"
|
||||
add_vf(dominance_label, 'setfield=mode='..dominance)
|
||||
else
|
||||
del_filter_if_present(dominance_label)
|
||||
end
|
||||
elseif verdict == interlaced_tff then
|
||||
mp.set_property("field-dominance", "top")
|
||||
elseif verdict == interlaced_bff then
|
||||
mp.set_property("field-dominance", "bottom")
|
||||
elseif verdict == interlaced then
|
||||
mp.set_property("field-dominance", "auto")
|
||||
end
|
||||
|
||||
-- handle the ivtc detection filter results
|
||||
if ivtc_verdict == progressive then
|
||||
mp.msg.info(string.format("telecined with %s field dominance: using pullup", dominance))
|
||||
local cmd = string.format("vf pre @%s:pullup", pullup_label)
|
||||
if not mp.command(cmd) then
|
||||
mp.msg.error("failed to insert pullup filter")
|
||||
stop_detect()
|
||||
return
|
||||
end
|
||||
|
||||
-- redo the detection with the pullup filter to see if it's telecined
|
||||
mp.set_property("percent-pos", percent_pos)
|
||||
timer = mp.add_timeout(detect_seconds, judge_ivtc)
|
||||
end
|
||||
|
||||
function judge_ivtc()
|
||||
verdict = judge()
|
||||
|
||||
if verdict == progressive then
|
||||
mp.msg.info(string.format("telecinied with %s field dominance: using pullup", mp.get_property("field-dominance")))
|
||||
stop_detect()
|
||||
else
|
||||
mp.msg.info(string.format("interlaced with %s field dominance: setting deinterlace property", dominance))
|
||||
mp.msg.info(string.format("interlaced with %s field dominance: setting deinterlace property", mp.get_property("field-dominance")))
|
||||
del_filter_if_present(pullup_label)
|
||||
mp.set_property("deinterlace","yes")
|
||||
stop_detect()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
mp.add_key_binding("ctrl+d", script_name, start_detect)
|
||||
+12
-154
@@ -4,172 +4,36 @@
|
||||
-- alphabetically, and adds entries before and after the current file to
|
||||
-- the internal playlist. (It stops if the it would add an already existing
|
||||
-- playlist entry at the same position - this makes it "stable".)
|
||||
-- Add at most 5000 * 2 files when starting a file (before + after).
|
||||
-- Add at most 5 * 2 files when starting a file (before + after).
|
||||
MAXENTRIES = 5
|
||||
|
||||
--[[
|
||||
To configure this script use file autoload.conf in director script-opts (the "script-opts"
|
||||
directory must be in the mpv configuration directory, typically ~/.config/mpv/).
|
||||
|
||||
Example configuration would be:
|
||||
|
||||
disabled=false
|
||||
images=false
|
||||
videos=true
|
||||
audio=true
|
||||
|
||||
--]]
|
||||
|
||||
MAXENTRIES = 5000
|
||||
|
||||
local msg = require 'mp.msg'
|
||||
local options = require 'mp.options'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
o = {
|
||||
disabled = false,
|
||||
images = true,
|
||||
videos = true,
|
||||
audio = true
|
||||
}
|
||||
options.read_options(o)
|
||||
|
||||
function Set (t)
|
||||
local set = {}
|
||||
for _, v in pairs(t) do set[v] = true end
|
||||
return set
|
||||
end
|
||||
|
||||
function SetUnion (a,b)
|
||||
local res = {}
|
||||
for k in pairs(a) do res[k] = true end
|
||||
for k in pairs(b) do res[k] = true end
|
||||
return res
|
||||
end
|
||||
|
||||
EXTENSIONS_VIDEO = Set {
|
||||
'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp'
|
||||
}
|
||||
|
||||
EXTENSIONS_AUDIO = Set {
|
||||
'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus'
|
||||
}
|
||||
|
||||
EXTENSIONS_IMAGES = Set {
|
||||
'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'webp', 'svg', 'bmp'
|
||||
}
|
||||
|
||||
EXTENSIONS = Set {}
|
||||
if o.videos then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_VIDEO) end
|
||||
if o.audio then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_AUDIO) end
|
||||
if o.images then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_IMAGES) end
|
||||
mputils = require 'mp.utils'
|
||||
|
||||
function add_files_at(index, files)
|
||||
index = index - 1
|
||||
local oldcount = mp.get_property_number("playlist-count", 1)
|
||||
for i = 1, #files do
|
||||
mp.commandv("loadfile", files[i], "append")
|
||||
mp.commandv("playlist-move", oldcount + i - 1, index + i - 1)
|
||||
mp.commandv("playlist_move", oldcount + i - 1, index + i - 1)
|
||||
end
|
||||
end
|
||||
|
||||
function get_extension(path)
|
||||
match = string.match(path, "%.([^%.]+)$" )
|
||||
if match == nil then
|
||||
return "nomatch"
|
||||
else
|
||||
return match
|
||||
end
|
||||
end
|
||||
|
||||
table.filter = function(t, iter)
|
||||
for i = #t, 1, -1 do
|
||||
if not iter(t[i]) then
|
||||
table.remove(t, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus
|
||||
-- Released under the MIT License
|
||||
-- http://www.davekoelle.com/files/alphanum.lua
|
||||
|
||||
-- split a string into a table of number and string values
|
||||
function splitbynum(s)
|
||||
local result = {}
|
||||
for x, y in (s or ""):gmatch("(%d*)(%D*)") do
|
||||
if x ~= "" then table.insert(result, tonumber(x)) end
|
||||
if y ~= "" then table.insert(result, y) end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function clean_key(k)
|
||||
k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower()
|
||||
return splitbynum(k)
|
||||
end
|
||||
|
||||
-- compare two strings
|
||||
function alnumcomp(x, y)
|
||||
local xt, yt = clean_key(x), clean_key(y)
|
||||
for i = 1, math.min(#xt, #yt) do
|
||||
local xe, ye = xt[i], yt[i]
|
||||
if type(xe) == "string" then ye = tostring(ye)
|
||||
elseif type(ye) == "string" then xe = tostring(xe) end
|
||||
if xe ~= ye then return xe < ye end
|
||||
end
|
||||
return #xt < #yt
|
||||
end
|
||||
|
||||
local autoloaded = nil
|
||||
|
||||
function find_and_add_entries()
|
||||
local path = mp.get_property("path", "")
|
||||
local dir, filename = utils.split_path(path)
|
||||
msg.trace(("dir: %s, filename: %s"):format(dir, filename))
|
||||
if o.disabled then
|
||||
msg.verbose("stopping: autoload disabled")
|
||||
return
|
||||
elseif #dir == 0 then
|
||||
msg.verbose("stopping: not a local path")
|
||||
local dir, filename = mputils.split_path(path)
|
||||
if #dir == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local pl_count = mp.get_property_number("playlist-count", 1)
|
||||
-- check if this is a manually made playlist
|
||||
if (pl_count > 1 and autoloaded == nil) or
|
||||
(pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then
|
||||
msg.verbose("stopping: manually made playlist")
|
||||
return
|
||||
else
|
||||
autoloaded = true
|
||||
end
|
||||
|
||||
local pl = mp.get_property_native("playlist", {})
|
||||
local pl_current = mp.get_property_number("playlist-pos-1", 1)
|
||||
msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current,
|
||||
utils.to_string(pl)))
|
||||
|
||||
local files = utils.readdir(dir, "files")
|
||||
local files = mputils.readdir(dir, "files")
|
||||
if files == nil then
|
||||
msg.verbose("no other files in directory")
|
||||
return
|
||||
end
|
||||
table.filter(files, function (v, k)
|
||||
if string.match(v, "^%.") then
|
||||
return false
|
||||
end
|
||||
local ext = get_extension(v)
|
||||
if ext == nil then
|
||||
return false
|
||||
end
|
||||
return EXTENSIONS[string.lower(ext)]
|
||||
end)
|
||||
table.sort(files, alnumcomp)
|
||||
|
||||
table.sort(files)
|
||||
if dir == "." then
|
||||
dir = ""
|
||||
end
|
||||
|
||||
local pl = mp.get_property_native("playlist", {})
|
||||
local pl_current = mp.get_property_number("playlist-pos", 0) + 1
|
||||
-- Find the current pl entry (dir+"/"+filename) in the sorted dir list
|
||||
local current
|
||||
for i = 1, #files do
|
||||
@@ -181,8 +45,6 @@ function find_and_add_entries()
|
||||
if current == nil then
|
||||
return
|
||||
end
|
||||
msg.trace("current file position in files: "..current)
|
||||
|
||||
local append = {[-1] = {}, [1] = {}}
|
||||
for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1
|
||||
for i = 1, MAXENTRIES do
|
||||
@@ -191,28 +53,24 @@ function find_and_add_entries()
|
||||
if file == nil or file[1] == "." then
|
||||
break
|
||||
end
|
||||
|
||||
local filepath = dir .. file
|
||||
if pl_e then
|
||||
-- If there's a playlist entry, and it's the same file, stop.
|
||||
msg.trace(pl_e.filename.." == "..filepath.." ?")
|
||||
if pl_e.filename == filepath then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if direction == -1 then
|
||||
if pl_current == 1 then -- never add additional entries in the middle
|
||||
msg.info("Prepending " .. file)
|
||||
mp.msg.info("Prepending " .. file)
|
||||
table.insert(append[-1], 1, filepath)
|
||||
end
|
||||
else
|
||||
msg.info("Adding " .. file)
|
||||
mp.msg.info("Adding " .. file)
|
||||
table.insert(append[1], filepath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
add_files_at(pl_current + 1, append[1])
|
||||
add_files_at(pl_current, append[-1])
|
||||
end
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
-- Test script for some command API details.
|
||||
|
||||
local utils = require("mp.utils")
|
||||
|
||||
function join(sep, arr, count)
|
||||
local r = ""
|
||||
if count == nil then
|
||||
count = #arr
|
||||
end
|
||||
for i = 1, count do
|
||||
if i > 1 then
|
||||
r = r .. sep
|
||||
end
|
||||
r = r .. utils.to_string(arr[i])
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
mp.observe_property("vo-configured", "bool", function(_, v)
|
||||
if v ~= true then
|
||||
return
|
||||
end
|
||||
|
||||
print("async expand-text")
|
||||
mp.command_native_async({"expand-text", "hello ${path}!"},
|
||||
function(res, val, err)
|
||||
print("done async expand-text: " .. join(" ", {res, val, err}))
|
||||
end)
|
||||
|
||||
-- make screenshot writing very slow
|
||||
mp.set_property("screenshot-format", "png")
|
||||
mp.set_property("screenshot-png-compression", "9")
|
||||
|
||||
timer = mp.add_periodic_timer(0.1, function() print("I'm alive") end)
|
||||
timer:resume()
|
||||
|
||||
print("Slow screenshot command...")
|
||||
res, err = mp.command_native({"screenshot"})
|
||||
print("done, res: " .. utils.to_string(res))
|
||||
|
||||
print("Slow screenshot async command...")
|
||||
res, err = mp.command_native_async({"screenshot"}, function(res)
|
||||
print("done (async), res: " .. utils.to_string(res))
|
||||
timer:kill()
|
||||
end)
|
||||
print("done (sending), res: " .. utils.to_string(res))
|
||||
|
||||
print("Broken screenshot async command...")
|
||||
mp.command_native_async({"screenshot-to-file", "/nonexistent/bogus.png"},
|
||||
function(res, val, err)
|
||||
print("done err scr.: " .. join(" ", {res, val, err}))
|
||||
end)
|
||||
|
||||
mp.command_native_async({name = "subprocess", args = {"sh", "-c", "echo hi && sleep 10s"}, capture_stdout = true},
|
||||
function(res, val, err)
|
||||
print("done subprocess: " .. join(" ", {res, val, err}))
|
||||
end)
|
||||
|
||||
local x = mp.command_native_async({name = "subprocess", args = {"sleep", "inf"}},
|
||||
function(res, val, err)
|
||||
print("done sleep inf subprocess: " .. join(" ", {res, val, err}))
|
||||
end)
|
||||
mp.add_timeout(15, function()
|
||||
print("aborting sleep inf subprocess after timeout")
|
||||
mp.abort_async_command(x)
|
||||
end)
|
||||
|
||||
-- (assuming this "freezes")
|
||||
local y = mp.command_native_async({name = "sub-add", url = "-"},
|
||||
function(res, val, err)
|
||||
print("done sub-add stdin: " .. join(" ", {res, val, err}))
|
||||
end)
|
||||
mp.add_timeout(20, function()
|
||||
print("aborting sub-add stdin after timeout")
|
||||
mp.abort_async_command(y)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-- This should get killed on script exit.
|
||||
mp.command_native_async({name = "subprocess", playback_only = false,
|
||||
args = {"sleep", "inf"}}, function()end)
|
||||
|
||||
-- Runs detached; should be killed on player exit (forces timeout)
|
||||
mp.command_native({_flags={"async"}, name = "subprocess",
|
||||
playback_only = false, args = {"sleep", "inf"}})
|
||||
end)
|
||||
|
||||
function freeze_test(playback_only)
|
||||
-- This "freezes" the script, should be killed via timeout.
|
||||
counter = counter and counter + 1 or 0
|
||||
print("freeze! " .. counter)
|
||||
local x = mp.command_native({name = "subprocess",
|
||||
playback_only = playback_only,
|
||||
args = {"sleep", "inf"}})
|
||||
print("done, killed=" .. utils.to_string(x.killed_by_us))
|
||||
end
|
||||
|
||||
mp.register_event("shutdown", function()
|
||||
freeze_test(false)
|
||||
end)
|
||||
|
||||
mp.register_event("idle", function()
|
||||
freeze_test(true)
|
||||
end)
|
||||
@@ -0,0 +1,99 @@
|
||||
-- This script enables live control of the dynamic range compression
|
||||
-- (drc) audio filter while the video is playing back. This can be
|
||||
-- useful to avoid having to stop and restart mpv to adjust filter
|
||||
-- parameters. See the entry for "drc" under the "AUDIO FILTERS"
|
||||
-- section of the man page for a complete description of the filter.
|
||||
--
|
||||
-- This script registers the key-binding "\" to toggle the filter between
|
||||
--
|
||||
-- * off
|
||||
-- * method=1 (single-sample smoothing)
|
||||
-- * method=2 (multi-sample smoothing)
|
||||
--
|
||||
-- It registers the keybindings ctrl+9/ctrl+0 to decrease/increase the
|
||||
-- target ampltiude. These keys will insert the filter at the default
|
||||
-- target amplitude of 0.25 if it was not previously present.
|
||||
--
|
||||
-- OSD feedback of the current filter state is displayed on pressing
|
||||
-- each bound key.
|
||||
|
||||
script_name = mp.get_script_name()
|
||||
|
||||
function print_state(params)
|
||||
if params then
|
||||
mp.osd_message(script_name..":\n"
|
||||
.."method = "..params["method"].."\n"
|
||||
.."target = "..params["target"])
|
||||
else
|
||||
mp.osd_message(script_name..":\noff")
|
||||
end
|
||||
end
|
||||
|
||||
function get_index_of_drc(afs)
|
||||
for i,af in pairs(afs) do
|
||||
if af["label"] == script_name then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function append_drc(afs)
|
||||
afs[#afs+1] = {
|
||||
name = "drc",
|
||||
label = script_name,
|
||||
params = {
|
||||
method = "1",
|
||||
target = "0.25"
|
||||
}
|
||||
}
|
||||
print_state(afs[#afs]["params"])
|
||||
end
|
||||
|
||||
function modify_or_create_af(fun)
|
||||
afs = mp.get_property_native("af")
|
||||
i = get_index_of_drc(afs)
|
||||
if not i then
|
||||
append_drc(afs)
|
||||
else
|
||||
fun(afs, i)
|
||||
end
|
||||
mp.set_property_native("af", afs)
|
||||
end
|
||||
|
||||
function drc_toggle_method_handler()
|
||||
modify_or_create_af(
|
||||
function (afs, i)
|
||||
new_method=(afs[i]["params"]["method"]+1)%3
|
||||
if new_method == 0 then
|
||||
table.remove(afs, i)
|
||||
print_state(nil)
|
||||
else
|
||||
afs[i]["params"]["method"] = tostring((afs[i]["params"]["method"])%2+1)
|
||||
print_state(afs[i]["params"])
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function drc_scale_target(factor)
|
||||
modify_or_create_af(
|
||||
function (afs)
|
||||
afs[i]["params"]["target"] = tostring(afs[i]["params"]["target"]*factor)
|
||||
print_state(afs[i]["params"])
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function drc_louder_handler()
|
||||
drc_scale_target(2.0)
|
||||
end
|
||||
|
||||
function drc_quieter_handler()
|
||||
drc_scale_target(0.5)
|
||||
end
|
||||
|
||||
-- toggle between off, method 1 and method 2
|
||||
mp.add_key_binding("\\", "drc_toggle_method", drc_toggle_method_handler)
|
||||
-- increase or decrease target volume
|
||||
mp.add_key_binding("ctrl+9", "drc_quieter", drc_quieter_handler)
|
||||
mp.add_key_binding("ctrl+0", "drc_louder", drc_louder_handler)
|
||||
@@ -1,37 +0,0 @@
|
||||
-- Test a float property which internally uses NaN.
|
||||
-- Run with --no-config (or just scale-param1 not set).
|
||||
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
prop_name = "scale-param1"
|
||||
|
||||
-- internal NaN, return string "default" instead of NaN
|
||||
v = mp.get_property_native(prop_name, "fail")
|
||||
print("Exp:", "string", "\"default\"")
|
||||
print("Got:", type(v), utils.to_string(v))
|
||||
|
||||
v = mp.get_property(prop_name)
|
||||
print("Exp:", "default")
|
||||
print("Got:", v)
|
||||
|
||||
-- not representable -> return provided fallback value
|
||||
v = mp.get_property_number(prop_name, -100)
|
||||
print("Exp:", -100)
|
||||
print("Got:", v)
|
||||
|
||||
mp.set_property_native(prop_name, 123)
|
||||
v = mp.get_property_number(prop_name, -100)
|
||||
print("Exp:", "number", 123)
|
||||
print("Got:", type(v), utils.to_string(v))
|
||||
|
||||
-- try to set an actual NaN
|
||||
st, msg = mp.set_property_number(prop_name, 0.0/0)
|
||||
print("Exp:", nil, "<message>")
|
||||
print("Got:", st, msg)
|
||||
|
||||
-- set default
|
||||
mp.set_property(prop_name, "default")
|
||||
|
||||
v = mp.get_property(prop_name)
|
||||
print("Exp:", "default")
|
||||
print("Got:", v)
|
||||
@@ -6,17 +6,9 @@
|
||||
|
||||
local utils = require("mp.utils")
|
||||
|
||||
function observe(name)
|
||||
for i,name in ipairs(mp.get_property_native("property-list")) do
|
||||
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,19 +0,0 @@
|
||||
--makes mpv disable ontop when pausing and re-enable it again when resuming playback
|
||||
--please note that this won't do anything if ontop was not enabled before pausing
|
||||
|
||||
local was_ontop = false
|
||||
|
||||
mp.observe_property("pause", "bool", function(name, value)
|
||||
local ontop = mp.get_property_native("ontop")
|
||||
if value then
|
||||
if ontop then
|
||||
mp.set_property_native("ontop", false)
|
||||
was_ontop = true
|
||||
end
|
||||
else
|
||||
if was_ontop and not ontop then
|
||||
mp.set_property_native("ontop", true)
|
||||
end
|
||||
was_ontop = false
|
||||
end
|
||||
end)
|
||||
@@ -2,6 +2,8 @@
|
||||
-- if it's brought back again. If the player was already paused when minimizing,
|
||||
-- then try not to mess with the pause state.
|
||||
|
||||
-- Note: currently works with X11 only.
|
||||
|
||||
local did_minimize = false
|
||||
|
||||
mp.observe_property("window-minimized", "bool", function(name, value)
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
--[[
|
||||
|
||||
Automatically skip in files if video frames with pre-supplied fingerprints are
|
||||
detected. This will skip ahead by a pre-configured amount of time if a matching
|
||||
video frame is detected.
|
||||
|
||||
This requires the vf_fingerprint video filter to be compiled in. Read the
|
||||
documentation of this filter for caveats (which will automatically apply to
|
||||
this script as well), such as no support for zero-copy hardware decoding.
|
||||
|
||||
You need to manually gather and provide fingerprints for video frames and add
|
||||
them to a configuration file in script-opts/skip-logo.conf (the "script-opts"
|
||||
directory must be in the mpv configuration directory, typically ~/.config/mpv/).
|
||||
|
||||
Example script-opts/skip-logo.conf:
|
||||
|
||||
|
||||
cases = {
|
||||
{
|
||||
-- Skip ahead 10 seconds if a black frame was detected
|
||||
-- Note: this is dangerous non-sense. It's just for demonstration.
|
||||
name = "black frame", -- print if matched
|
||||
skip = 10, -- number of seconds to skip forward
|
||||
score = 0.3, -- required score
|
||||
fingerprint = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
{
|
||||
-- Skip ahead 20 seconds if a white frame was detected
|
||||
-- Note: this is dangerous non-sense. It's just for demonstration.
|
||||
name = "fun2",
|
||||
skip = 20,
|
||||
fingerprint = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
}
|
||||
|
||||
This is actually a lua file. Lua was chosen because it seemed less of a pain to
|
||||
parse. Future versions of this script may change the format.
|
||||
|
||||
The fingerprint is a video frame, converted to "gray" (8 bit per pixels), full
|
||||
range, each pixel concatenated into an array, converted to a hex string. You
|
||||
can produce these fingerprints by running this manually:
|
||||
|
||||
mpv --vf=fingerprint:print yourfile.mkv
|
||||
|
||||
This will log the fingerprint of each video frame to the console, along with its
|
||||
timestamp. You find the fingerprint of a unique-enough looking frame, and add
|
||||
it as entry to skip-logo.conf.
|
||||
|
||||
You can provide a score for "fuzziness". If no score is provided, a default
|
||||
value of 0.3 is used. The score is inverse: 0 means exactly the same, while a
|
||||
higher score means a higher difference. Currently, the score is computed as
|
||||
euclidean distance between the video frame and the pre-provided fingerprint,
|
||||
thus the highest score is 16. You probably want a score lower than 1 at least.
|
||||
(This algorithm is very primitive, but also simple and fast to compute.)
|
||||
|
||||
There's always the danger of false positives, which might be quite annoying.
|
||||
It's up to you what you hate more, the logo, or random skips if false positives
|
||||
are detected. Also, it's always active, and might eat too much CPU with files
|
||||
that have a high resolution or framerate. To temporarily disable the script,
|
||||
having a keybind like this in your input.conf will be helpful:
|
||||
|
||||
ctrl+k vf toggle @skip-logo
|
||||
|
||||
This will disable/enable the fingerprint filter, which the script automatically
|
||||
adds at start.
|
||||
|
||||
Another important caveat is that the script currently disables matching during
|
||||
seeking or playback initialization, which means it cannot match the first few
|
||||
frames of a video. This could be fixed, but the author was too lazy to do so.
|
||||
|
||||
--]]
|
||||
|
||||
local utils = require "mp.utils"
|
||||
local msg = require "mp.msg"
|
||||
|
||||
local label = "skip-logo"
|
||||
local meta_property = string.format("vf-metadata/%s", label)
|
||||
|
||||
local config = {}
|
||||
local cases = {}
|
||||
local cur_bmp
|
||||
local seeking = false
|
||||
local playback_start_pts = nil
|
||||
|
||||
-- Convert a hex string to an array. Convert each byte to a [0,1] float by
|
||||
-- interpreting it as normalized uint8_t.
|
||||
-- The data parameter, if not nil, may be used as storage (avoiding garbage).
|
||||
local function hex_to_norm8(hex, data)
|
||||
local size = math.floor(#hex / 2)
|
||||
if #hex ~= size * 2 then
|
||||
return nil
|
||||
end
|
||||
local res
|
||||
if (data ~= nil) and (#data == size) then
|
||||
res = data
|
||||
else
|
||||
res = {}
|
||||
end
|
||||
for i = 1, size do
|
||||
local num = tonumber(hex:sub(i * 2, i * 2 + 1), 16)
|
||||
if num == nil then
|
||||
return nil
|
||||
end
|
||||
res[i] = num / 255.0
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
local function compare_bmp(a, b)
|
||||
if #a ~= #b then
|
||||
return nil -- can't compare
|
||||
end
|
||||
local sum = 0
|
||||
for i = 1, #a do
|
||||
local diff = a[i] - b[i]
|
||||
sum = sum + diff * diff
|
||||
end
|
||||
return math.sqrt(sum)
|
||||
end
|
||||
|
||||
local function load_config()
|
||||
local conf_file = mp.find_config_file("script-opts/skip-logo.conf")
|
||||
local conf_fn
|
||||
local err = nil
|
||||
if conf_file then
|
||||
if setfenv then
|
||||
conf_fn, err = loadfile(conf_file)
|
||||
if conf_fn then
|
||||
setfenv(conf_fn, config)
|
||||
end
|
||||
else
|
||||
msg.warn("Lua 5.2 was not tested, this might go wrong.")
|
||||
conf_fn, err = loadfile(conf_file, "t", config)
|
||||
end
|
||||
else
|
||||
err = "config file not found"
|
||||
end
|
||||
|
||||
if conf_fn and (not err) then
|
||||
local ok, err2 = pcall(conf_fn)
|
||||
err = err2
|
||||
end
|
||||
|
||||
if err then
|
||||
msg.error("Failed to load config file:", err)
|
||||
end
|
||||
|
||||
if config.cases then
|
||||
for n, case in ipairs(config.cases) do
|
||||
local err = nil
|
||||
case.bitmap = hex_to_norm8(case.fingerprint)
|
||||
if case.bitmap == nil then
|
||||
err = "invalid or missing fingerprint field"
|
||||
end
|
||||
if case.score == nil then
|
||||
case.score = 0.3
|
||||
end
|
||||
if type(case.score) ~= "number" then
|
||||
err = "score field is not a number"
|
||||
end
|
||||
if type(case.skip) ~= "number" then
|
||||
err = "skip field is not a number or missing"
|
||||
end
|
||||
if case.name == nil then
|
||||
case.name = ("Entry %d"):format(n)
|
||||
end
|
||||
if err == nil then
|
||||
cases[#cases + 1] = case
|
||||
else
|
||||
msg.error(("Entry %s: %s, ignoring."):format(case.name, err))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
load_config()
|
||||
|
||||
-- Returns true on match and if something was done.
|
||||
local function check_fingerprint(hex, pts)
|
||||
local bmp = hex_to_norm8(hex, cur_bmp)
|
||||
cur_bmp = bmp
|
||||
|
||||
-- If parsing the filter's result failed (well, it shouldn't).
|
||||
assert(bmp ~= nil, "filter returned nonsense")
|
||||
|
||||
for _, case in ipairs(cases) do
|
||||
local score = compare_bmp(case.bitmap, bmp)
|
||||
if (score ~= nil) and (score <= case.score) then
|
||||
msg.warn(("Matching %s: score=%f (required: %f) at %s, skipping %f seconds"):
|
||||
format(case.name, score, case.score, mp.format_time(pts), case.skip))
|
||||
mp.commandv("seek", pts + case.skip, "absolute+exact")
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function read_frames()
|
||||
local result = mp.get_property_native(meta_property)
|
||||
if result == nil then
|
||||
return
|
||||
end
|
||||
|
||||
-- Try to get all entries. Out of laziness, assume that there are at most
|
||||
-- 100 entries. (In fact, vf_fingerprint limits it to 10.)
|
||||
for i = 0, 99 do
|
||||
local prefix = string.format("fp%d.", i)
|
||||
local hex = result[prefix .. "hex"]
|
||||
|
||||
local pts = tonumber(result[prefix .. "pts"])
|
||||
if (hex == nil) or (pts == nil) then
|
||||
break
|
||||
end
|
||||
|
||||
local skip = false -- blame Lua for not having "continue" or "goto", not me
|
||||
|
||||
-- If seeking just stopped, there will be frames before the seek target,
|
||||
-- ignore them by checking the timestamps.
|
||||
if playback_start_pts ~= nil then
|
||||
if pts >= playback_start_pts then
|
||||
playback_start_pts = nil -- just for robustness
|
||||
else
|
||||
skip = true
|
||||
end
|
||||
end
|
||||
|
||||
if not skip then
|
||||
if check_fingerprint(hex, pts) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mp.observe_property(meta_property, "none", function()
|
||||
-- Ignore frames that are decoded/filtered during seeking.
|
||||
if seeking then
|
||||
return
|
||||
end
|
||||
|
||||
read_frames()
|
||||
end)
|
||||
|
||||
mp.observe_property("seeking", "bool", function(name, val)
|
||||
seeking = val
|
||||
if seeking == false then
|
||||
playback_start_pts = mp.get_property_number("playback-time")
|
||||
read_frames()
|
||||
end
|
||||
end)
|
||||
|
||||
local filters = mp.get_property_native("option-info/vf/choices", {})
|
||||
local found = false
|
||||
for _, f in ipairs(filters) do
|
||||
if f == "fingerprint" then
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if found then
|
||||
mp.command(("no-osd vf add @%s:fingerprint"):format(label, filter))
|
||||
else
|
||||
msg.warn("vf_fingerprint not found")
|
||||
end
|
||||
@@ -1,7 +1,5 @@
|
||||
-- Rebuild the terminal status line as a lua script
|
||||
-- Be aware that this will require more cpu power!
|
||||
-- Also, this is based on a rather old version of the
|
||||
-- builtin mpv status line.
|
||||
|
||||
-- Add a string to the status line
|
||||
function atsl(s)
|
||||
@@ -18,10 +16,10 @@ function update_status_line()
|
||||
atsl("(Buffering) ")
|
||||
end
|
||||
|
||||
if mp.get_property("aid") ~= "no" then
|
||||
if mp.get_property("vid") ~= "no" then
|
||||
atsl("A")
|
||||
end
|
||||
if mp.get_property("vid") ~= "no" then
|
||||
if mp.get_property("aid") ~= "no" then
|
||||
atsl("V")
|
||||
end
|
||||
|
||||
@@ -30,7 +28,7 @@ function update_status_line()
|
||||
atsl(mp.get_property_osd("time-pos"))
|
||||
|
||||
atsl(" / ");
|
||||
atsl(mp.get_property_osd("duration"));
|
||||
atsl(mp.get_property_osd("length"));
|
||||
|
||||
atsl(" (")
|
||||
atsl(mp.get_property_osd("percent-pos", -1))
|
||||
@@ -43,7 +41,7 @@ function update_status_line()
|
||||
|
||||
r = mp.get_property_number("avsync", nil)
|
||||
if r ~= nil then
|
||||
atsl(string.format(" A-V: %f", r))
|
||||
atsl(string.format(" A-V: %7.3f", r))
|
||||
end
|
||||
|
||||
r = mp.get_property("total-avsync-change", 0)
|
||||
@@ -51,24 +49,12 @@ function update_status_line()
|
||||
atsl(string.format(" ct:%7.3f", r))
|
||||
end
|
||||
|
||||
r = mp.get_property_number("decoder-drop-frame-count", -1)
|
||||
r = mp.get_property_number("drop-frame-count", -1)
|
||||
if r > 0 then
|
||||
atsl(" Late: ")
|
||||
atsl(r)
|
||||
end
|
||||
|
||||
r = mp.get_property_osd("video-bitrate")
|
||||
if r ~= nil and r ~= "" then
|
||||
atsl(" Vb: ")
|
||||
atsl(r)
|
||||
end
|
||||
|
||||
r = mp.get_property_osd("audio-bitrate")
|
||||
if r ~= nil and r ~= "" then
|
||||
atsl(" Ab: ")
|
||||
atsl(r)
|
||||
end
|
||||
|
||||
r = mp.get_property_number("cache", 0)
|
||||
if r > 0 then
|
||||
atsl(string.format(" Cache: %d%% ", r))
|
||||
@@ -78,15 +64,6 @@ function update_status_line()
|
||||
mp.set_property("options/term-status-msg", newStatus)
|
||||
end
|
||||
|
||||
timer = mp.add_periodic_timer(1, update_status_line)
|
||||
-- Register the event
|
||||
mp.register_event("tick", update_status_line)
|
||||
|
||||
function on_pause_change(name, value)
|
||||
if value == false then
|
||||
timer:resume()
|
||||
else
|
||||
timer:stop()
|
||||
end
|
||||
mp.add_timeout(0.1, update_status_line)
|
||||
end
|
||||
mp.observe_property("pause", "bool", on_pause_change)
|
||||
mp.register_event("seek", update_status_line)
|
||||
Executable
+169
@@ -0,0 +1,169 @@
|
||||
#! /usr/bin/env perl
|
||||
|
||||
# Generate C definitions for parsing Matroska files.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/lib";
|
||||
use Parse::Matroska::Definitions;
|
||||
use Parse::Matroska::Reader;
|
||||
|
||||
use Getopt::Long;
|
||||
use List::Util qw{max};
|
||||
|
||||
my @global_elem_list = @Parse::Matroska::Definitions::global_elem_list;
|
||||
|
||||
Getopt::Long::Configure(qw{auto_version auto_help});
|
||||
my %opt;
|
||||
GetOptions(\%opt,
|
||||
"generate-header",
|
||||
"generate-definitions",
|
||||
"full",
|
||||
);
|
||||
|
||||
if ($opt{"generate-header"}) {
|
||||
generate_c_header();
|
||||
} elsif ($opt{"generate-definitions"}) {
|
||||
generate_c_definitions();
|
||||
} else {
|
||||
for (@ARGV) {
|
||||
my $reader = Parse::Matroska::Reader->new($_ eq '-' ? \*STDIN : $_) or die $!;
|
||||
while (my $elem = $reader->read_element($_ eq '-')) {
|
||||
process_elem($elem, $_ eq '-');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Generate declarations for libmpdemux/ebml_types.h
|
||||
sub generate_c_header {
|
||||
print "/* Generated by TOOLS/matroska.pl, do not edit manually */\n\n";
|
||||
|
||||
# Write a #define for the ElementID of each known element
|
||||
for my $el (@global_elem_list) {
|
||||
printf "#define %-40s 0x%s\n", $el->{definename}, $el->{elid};
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Define a struct for each ElementID that has child elements
|
||||
for my $el (@global_elem_list) {
|
||||
next unless $el->{subelements};
|
||||
print "\nstruct $el->{structname} {\n";
|
||||
|
||||
# Figure out the length of the longest variable name
|
||||
# Used for pretty-printing in the next step
|
||||
my $l = max(map { length $_->{valname} } values %{$el->{subelements}});
|
||||
|
||||
# Output each variable, with pointers for array (multiple) elements
|
||||
for my $subel (sort { $a->{definename} cmp $b->{definename} } values %{$el->{subelements}}) {
|
||||
printf " %-${l}s %s%s;\n",
|
||||
$subel->{valname}, $subel->{multiple}?'*':' ', $subel->{fieldname};
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Output a counter variable for each element
|
||||
# (presence/absence for scalars, item count for arrays)
|
||||
for my $subel (sort values %{$el->{subelements}}) {
|
||||
print " int n_$subel->{fieldname};\n"
|
||||
}
|
||||
print "};\n";
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Output extern references for ebml_elem_desc structs for each of the elements
|
||||
# These are defined by generate_c_definitions
|
||||
for my $el (@global_elem_list) {
|
||||
next unless $el->{subelements};
|
||||
print "extern const struct ebml_elem_desc $el->{structname}_desc;\n";
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Output the max number of sub-elements a known element might have
|
||||
printf "#define MAX_EBML_SUBELEMENTS %d\n",
|
||||
max(map { scalar keys %{$_->{subelements}} }
|
||||
grep { $_->{subelements} } @global_elem_list);
|
||||
}
|
||||
|
||||
# Generate definitions for libmpdemux/ebml_defs.c
|
||||
sub generate_c_definitions {
|
||||
print "/* Generated by TOOLS/matroska.pl, do not edit manually */\n\n";
|
||||
# ebml_defs.c uses macros declared in ebml.c
|
||||
for my $el (@global_elem_list) {
|
||||
print "\n";
|
||||
if ($el->{subelements}) {
|
||||
# set N for the next macros
|
||||
print "#define N $el->{fieldname}\n";
|
||||
|
||||
# define a struct ebml_$N_desc and gets ready to define fields
|
||||
# this secretly opens two scopes; hence the }}; at the end
|
||||
print "E_S(\"$el->{name}\", ".scalar(keys %{$el->{subelements}}).")\n";
|
||||
|
||||
# define a field for each subelement
|
||||
# also does lots of macro magic, but doesn't open a scope
|
||||
for my $subel (sort { $a->{definename} cmp $b->{definename} } values %{$el->{subelements}}) {
|
||||
print "F($subel->{definename}, $subel->{fieldname}, ".
|
||||
($subel->{multiple}?'1':'0').")\n";
|
||||
}
|
||||
# close the struct
|
||||
print "}};\n";
|
||||
|
||||
# unset N since we've used it
|
||||
print "#undef N\n";
|
||||
} else {
|
||||
print "E(\"$el->{name}\", $el->{fieldname}, $el->{ebmltype})\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub repr {
|
||||
my @ret;
|
||||
foreach (@_) {
|
||||
if (/'/) {
|
||||
s/"/\\"/g;
|
||||
push @ret, "\"$_\"";
|
||||
} else {
|
||||
push @ret, "'$_'";
|
||||
}
|
||||
}
|
||||
return @ret if wantarray;
|
||||
return pop @ret if defined wantarray;
|
||||
return;
|
||||
}
|
||||
|
||||
sub process_elem {
|
||||
my ($elem, $read_bin) = @_;
|
||||
unless ($opt{full}) {
|
||||
if ($elem->{name} eq 'Cluster' || $elem->{name} eq 'Cues') {
|
||||
$elem->skip;
|
||||
return;
|
||||
}
|
||||
}
|
||||
die unless $elem;
|
||||
|
||||
if ($elem->{type} ne 'skip') {
|
||||
print "$elem->{depth} $elem->{elid} $elem->{name} size: $elem->{content_len} value: ";
|
||||
}
|
||||
|
||||
if ($elem->{type} eq 'sub') {
|
||||
print "subelements:\n";
|
||||
while (my $chld = $elem->next_child($read_bin)) {
|
||||
process_elem($chld);
|
||||
}
|
||||
} elsif ($elem->{type} eq 'binary') {
|
||||
my $t = "<skipped $elem->{content_len} bytes>";
|
||||
if ($elem->{content_len} < 20) {
|
||||
$t = unpack "H*", $elem->get_value;
|
||||
}
|
||||
print "binary $t\n";
|
||||
delete $elem->{value};
|
||||
} elsif ($elem->{type} eq 'ebml_id') {
|
||||
print "binary $elem->{value}->{elid} (".($elem->{value}->{name}||"UNKNOWN").")\n";
|
||||
} elsif ($elem->{type} eq 'skip') {
|
||||
# skip
|
||||
} elsif ($elem->{type} eq 'str') {
|
||||
print "string ". repr($elem->get_value) . "\n";
|
||||
} else {
|
||||
print "$elem->{type} ". $elem->get_value ."\n";
|
||||
}
|
||||
}
|
||||
@@ -1,479 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate C definitions for parsing Matroska files.
|
||||
Can also be used to directly parse Matroska files and display their contents.
|
||||
"""
|
||||
|
||||
#
|
||||
# This file is part of mpv.
|
||||
#
|
||||
# mpv is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# mpv is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# for compatibility with Python 2.x
|
||||
from __future__ import print_function
|
||||
|
||||
elements_ebml = (
|
||||
'EBML, 1a45dfa3, sub', (
|
||||
'EBMLVersion, 4286, uint',
|
||||
'EBMLReadVersion, 42f7, uint',
|
||||
'EBMLMaxIDLength, 42f2, uint',
|
||||
'EBMLMaxSizeLength, 42f3, uint',
|
||||
'DocType, 4282, str',
|
||||
'DocTypeVersion, 4287, uint',
|
||||
'DocTypeReadVersion, 4285, uint',
|
||||
),
|
||||
|
||||
'CRC32, bf, binary',
|
||||
'Void, ec, binary',
|
||||
)
|
||||
|
||||
elements_matroska = (
|
||||
'Segment, 18538067, sub', (
|
||||
|
||||
'SeekHead*, 114d9b74, sub', (
|
||||
'Seek*, 4dbb, sub', (
|
||||
'SeekID, 53ab, ebml_id',
|
||||
'SeekPosition, 53ac, uint',
|
||||
),
|
||||
),
|
||||
|
||||
'Info*, 1549a966, sub', (
|
||||
'SegmentUID, 73a4, binary',
|
||||
'PrevUID, 3cb923, binary',
|
||||
'NextUID, 3eb923, binary',
|
||||
'TimecodeScale, 2ad7b1, uint',
|
||||
'DateUTC, 4461, sint',
|
||||
'Title, 7ba9, str',
|
||||
'MuxingApp, 4d80, str',
|
||||
'WritingApp, 5741, str',
|
||||
'Duration, 4489, float',
|
||||
),
|
||||
|
||||
'Cluster*, 1f43b675, sub', (
|
||||
'Timecode, e7, uint',
|
||||
'BlockGroup*, a0, sub', (
|
||||
'Block, a1, binary',
|
||||
'BlockDuration, 9b, uint',
|
||||
'ReferenceBlock*, fb, sint',
|
||||
'DiscardPadding, 75A2, sint',
|
||||
'BlockAdditions, 75A1, sub', (
|
||||
'BlockMore*, A6, sub', (
|
||||
'BlockAddID, EE, uint',
|
||||
'BlockAdditional, A5, binary',
|
||||
),
|
||||
),
|
||||
),
|
||||
'SimpleBlock*, a3, binary',
|
||||
),
|
||||
|
||||
'Tracks*, 1654ae6b, sub', (
|
||||
'TrackEntry*, ae, sub', (
|
||||
'TrackNumber, d7, uint',
|
||||
'TrackUID, 73c5, uint',
|
||||
'TrackType, 83, uint',
|
||||
'FlagEnabled, b9, uint',
|
||||
'FlagDefault, 88, uint',
|
||||
'FlagForced, 55aa, uint',
|
||||
'FlagLacing, 9c, uint',
|
||||
'MinCache, 6de7, uint',
|
||||
'MaxCache, 6df8, uint',
|
||||
'DefaultDuration, 23e383, uint',
|
||||
'TrackTimecodeScale, 23314f, float',
|
||||
'MaxBlockAdditionID, 55ee, uint',
|
||||
'Name, 536e, str',
|
||||
'Language, 22b59c, str',
|
||||
'CodecID, 86, str',
|
||||
'CodecPrivate, 63a2, binary',
|
||||
'CodecName, 258688, str',
|
||||
'CodecDecodeAll, aa, uint',
|
||||
'CodecDelay, 56aa, uint',
|
||||
'SeekPreRoll, 56bb, uint',
|
||||
'Video, e0, sub', (
|
||||
'FlagInterlaced, 9a, uint',
|
||||
'PixelWidth, b0, uint',
|
||||
'PixelHeight, ba, uint',
|
||||
'DisplayWidth, 54b0, uint',
|
||||
'DisplayHeight, 54ba, uint',
|
||||
'DisplayUnit, 54b2, uint',
|
||||
'FrameRate, 2383e3, float',
|
||||
'ColourSpace, 2eb524, binary',
|
||||
'StereoMode, 53b8, uint',
|
||||
'Colour, 55b0, sub', (
|
||||
'MatrixCoefficients, 55B1, uint',
|
||||
'BitsPerChannel, 55B2, uint',
|
||||
'ChromaSubsamplingHorz, 55B3, uint',
|
||||
'ChromaSubsamplingVert, 55B4, uint',
|
||||
'CbSubsamplingHorz, 55B5, uint',
|
||||
'CbSubsamplingVert, 55B6, uint',
|
||||
'ChromaSitingHorz, 55B7, uint',
|
||||
'ChromaSitingVert, 55B8, uint',
|
||||
'Range, 55B9, uint',
|
||||
'TransferCharacteristics, 55BA, uint',
|
||||
'Primaries, 55BB, uint',
|
||||
'MaxCLL, 55BC, uint',
|
||||
'MaxFALL, 55BD, uint',
|
||||
'MasteringMetadata, 55D0, sub', (
|
||||
'PrimaryRChromaticityX, 55D1, float',
|
||||
'PrimaryRChromaticityY, 55D2, float',
|
||||
'PrimaryGChromaticityX, 55D3, float',
|
||||
'PrimaryGChromaticityY, 55D4, float',
|
||||
'PrimaryBChromaticityX, 55D5, float',
|
||||
'PrimaryBChromaticityY, 55D6, float',
|
||||
'WhitePointChromaticityX, 55D7, float',
|
||||
'WhitePointChromaticityY, 55D8, float',
|
||||
'LuminanceMax, 55D9, float',
|
||||
'LuminanceMin, 55DA, float',
|
||||
),
|
||||
),
|
||||
'Projection, 7670, sub', (
|
||||
'ProjectionType, 7671, uint',
|
||||
'ProjectionPrivate, 7672, binary',
|
||||
'ProjectionPoseYaw, 7673, float',
|
||||
'ProjectionPosePitch, 7674, float',
|
||||
'ProjectionPoseRoll, 7675, float',
|
||||
),
|
||||
),
|
||||
'Audio, e1, sub', (
|
||||
'SamplingFrequency, b5, float',
|
||||
'OutputSamplingFrequency, 78b5, float',
|
||||
'Channels, 9f, uint',
|
||||
'BitDepth, 6264, uint',
|
||||
),
|
||||
'ContentEncodings, 6d80, sub', (
|
||||
'ContentEncoding*, 6240, sub', (
|
||||
'ContentEncodingOrder, 5031, uint',
|
||||
'ContentEncodingScope, 5032, uint',
|
||||
'ContentEncodingType, 5033, uint',
|
||||
'ContentCompression, 5034, sub', (
|
||||
'ContentCompAlgo, 4254, uint',
|
||||
'ContentCompSettings, 4255, binary',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
'Cues, 1c53bb6b, sub', (
|
||||
'CuePoint*, bb, sub', (
|
||||
'CueTime, b3, uint',
|
||||
'CueTrackPositions*, b7, sub', (
|
||||
'CueTrack, f7, uint',
|
||||
'CueClusterPosition, f1, uint',
|
||||
'CueRelativePosition, f0, uint',
|
||||
'CueDuration, b2, uint',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
'Attachments, 1941a469, sub', (
|
||||
'AttachedFile*, 61a7, sub', (
|
||||
'FileDescription, 467e, str',
|
||||
'FileName, 466e, str',
|
||||
'FileMimeType, 4660, str',
|
||||
'FileData, 465c, binary',
|
||||
'FileUID, 46ae, uint',
|
||||
),
|
||||
),
|
||||
|
||||
'Chapters, 1043a770, sub', (
|
||||
'EditionEntry*, 45b9, sub', (
|
||||
'EditionUID, 45bc, uint',
|
||||
'EditionFlagHidden, 45bd, uint',
|
||||
'EditionFlagDefault, 45db, uint',
|
||||
'EditionFlagOrdered, 45dd, uint',
|
||||
'ChapterAtom*, b6, sub', (
|
||||
'ChapterUID, 73c4, uint',
|
||||
'ChapterTimeStart, 91, uint',
|
||||
'ChapterTimeEnd, 92, uint',
|
||||
'ChapterFlagHidden, 98, uint',
|
||||
'ChapterFlagEnabled, 4598, uint',
|
||||
'ChapterSegmentUID, 6e67, binary',
|
||||
'ChapterSegmentEditionUID, 6ebc, uint',
|
||||
'ChapterDisplay*, 80, sub', (
|
||||
'ChapString, 85, str',
|
||||
'ChapLanguage*, 437c, str',
|
||||
'ChapCountry*, 437e, str',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'Tags*, 1254c367, sub', (
|
||||
'Tag*, 7373, sub', (
|
||||
'Targets, 63c0, sub', (
|
||||
'TargetTypeValue, 68ca, uint',
|
||||
'TargetType, 63ca, str',
|
||||
'TargetTrackUID, 63c5, uint',
|
||||
'TargetEditionUID, 63c9, uint',
|
||||
'TargetChapterUID, 63c4, uint',
|
||||
'TargetAttachmentUID, 63c6, uint',
|
||||
),
|
||||
'SimpleTag*, 67c8, sub', (
|
||||
'TagName, 45a3, str',
|
||||
'TagLanguage, 447a, str',
|
||||
'TagString, 4487, str',
|
||||
'TagDefault, 4484, uint',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
import sys
|
||||
from math import ldexp
|
||||
from binascii import hexlify
|
||||
|
||||
def byte2num(s):
|
||||
return int(hexlify(s), 16)
|
||||
|
||||
class EOF(Exception): pass
|
||||
|
||||
def camelcase_to_words(name):
|
||||
parts = []
|
||||
start = 0
|
||||
for i in range(1, len(name)):
|
||||
if name[i].isupper() and (name[i-1].islower() or
|
||||
name[i+1:i+2].islower()):
|
||||
parts.append(name[start:i])
|
||||
start = i
|
||||
parts.append(name[start:])
|
||||
return '_'.join(parts).lower()
|
||||
|
||||
class MatroskaElement(object):
|
||||
|
||||
def __init__(self, name, elid, valtype, namespace):
|
||||
self.name = name
|
||||
self.definename = '{0}_ID_{1}'.format(namespace, name.upper())
|
||||
self.fieldname = camelcase_to_words(name)
|
||||
self.structname = 'ebml_' + self.fieldname
|
||||
self.elid = elid
|
||||
self.valtype = valtype
|
||||
if valtype == 'sub':
|
||||
self.ebmltype = 'EBML_TYPE_SUBELEMENTS'
|
||||
self.valname = 'struct ' + self.structname
|
||||
else:
|
||||
self.ebmltype = 'EBML_TYPE_' + valtype.upper()
|
||||
try:
|
||||
self.valname = {'uint': 'uint64_t', 'str': 'char *',
|
||||
'binary': 'bstr', 'ebml_id': 'uint32_t',
|
||||
'float': 'double', 'sint': 'int64_t',
|
||||
}[valtype]
|
||||
except KeyError:
|
||||
raise SyntaxError('Unrecognized value type ' + valtype)
|
||||
self.subelements = ()
|
||||
|
||||
def add_subelements(self, subelements):
|
||||
self.subelements = subelements
|
||||
self.subids = set(x[0].elid for x in subelements)
|
||||
|
||||
elementd = {}
|
||||
elementlist = []
|
||||
def parse_elems(l, namespace):
|
||||
subelements = []
|
||||
for el in l:
|
||||
if isinstance(el, str):
|
||||
name, hexid, eltype = [x.strip() for x in el.split(',')]
|
||||
hexid = hexid.lower()
|
||||
multiple = name.endswith('*')
|
||||
name = name.strip('*')
|
||||
new = MatroskaElement(name, hexid, eltype, namespace)
|
||||
elementd[hexid] = new
|
||||
elementlist.append(new)
|
||||
subelements.append((new, multiple))
|
||||
else:
|
||||
new.add_subelements(parse_elems(el, namespace))
|
||||
return subelements
|
||||
|
||||
parse_elems(elements_ebml, 'EBML')
|
||||
parse_elems(elements_matroska, 'MATROSKA')
|
||||
|
||||
def printf(out, *args):
|
||||
out.write(u' '.join([str(x) for x in args]))
|
||||
out.write(u'\n')
|
||||
|
||||
def generate_C_header(out):
|
||||
printf(out, '// Generated by TOOLS/matroska.py, do not edit manually')
|
||||
printf(out)
|
||||
|
||||
for el in elementlist:
|
||||
printf(out, '#define {0.definename:40} 0x{0.elid}'.format(el))
|
||||
|
||||
printf(out)
|
||||
|
||||
for el in reversed(elementlist):
|
||||
if not el.subelements:
|
||||
continue
|
||||
printf(out)
|
||||
printf(out, 'struct {0.structname} {{'.format(el))
|
||||
l = max(len(subel.valname) for subel, multiple in el.subelements)+1
|
||||
for subel, multiple in el.subelements:
|
||||
printf(out, ' {e.valname:{l}} {star}{e.fieldname};'.format(
|
||||
e=subel, l=l, star=' *'[multiple]))
|
||||
printf(out)
|
||||
for subel, multiple in el.subelements:
|
||||
printf(out, ' int n_{0.fieldname};'.format(subel))
|
||||
printf(out, '};')
|
||||
|
||||
for el in elementlist:
|
||||
if not el.subelements:
|
||||
continue
|
||||
printf(out, 'extern const struct ebml_elem_desc {0.structname}_desc;'.format(el))
|
||||
|
||||
printf(out)
|
||||
printf(out, '#define MAX_EBML_SUBELEMENTS', max(len(el.subelements)
|
||||
for el in elementlist))
|
||||
|
||||
|
||||
def generate_C_definitions(out):
|
||||
printf(out, '// Generated by TOOLS/matroska.py, do not edit manually')
|
||||
printf(out)
|
||||
for el in reversed(elementlist):
|
||||
printf(out)
|
||||
if el.subelements:
|
||||
printf(out, '#define N', el.fieldname)
|
||||
printf(out, 'E_S("{0}", {1})'.format(el.name, len(el.subelements)))
|
||||
for subel, multiple in el.subelements:
|
||||
printf(out, 'F({0.definename}, {0.fieldname}, {1})'.format(
|
||||
subel, int(multiple)))
|
||||
printf(out, '}};')
|
||||
printf(out, '#undef N')
|
||||
else:
|
||||
printf(out, 'E("{0.name}", {0.fieldname}, {0.ebmltype})'.format(el))
|
||||
|
||||
def read(s, length):
|
||||
t = s.read(length)
|
||||
if len(t) != length:
|
||||
raise EOF
|
||||
return t
|
||||
|
||||
def read_id(s):
|
||||
t = read(s, 1)
|
||||
i = 0
|
||||
mask = 128
|
||||
if ord(t) == 0:
|
||||
raise SyntaxError
|
||||
while not ord(t) & mask:
|
||||
i += 1
|
||||
mask >>= 1
|
||||
t += read(s, i)
|
||||
return t
|
||||
|
||||
def read_vint(s):
|
||||
t = read(s, 1)
|
||||
i = 0
|
||||
mask = 128
|
||||
if ord(t) == 0:
|
||||
raise SyntaxError
|
||||
while not ord(t) & mask:
|
||||
i += 1
|
||||
mask >>= 1
|
||||
t = bytes((ord(t) & (mask - 1),))
|
||||
t += read(s, i)
|
||||
return i+1, byte2num(t)
|
||||
|
||||
def read_str(s, length):
|
||||
return read(s, length)
|
||||
|
||||
def read_uint(s, length):
|
||||
t = read(s, length)
|
||||
return byte2num(t)
|
||||
|
||||
def read_sint(s, length):
|
||||
i = read_uint(s, length)
|
||||
mask = 1 << (length * 8 - 1)
|
||||
if i & mask:
|
||||
i -= 2 * mask
|
||||
return i
|
||||
|
||||
def read_float(s, length):
|
||||
t = read(s, length)
|
||||
i = byte2num(t)
|
||||
if length == 4:
|
||||
f = ldexp((i & 0x7fffff) + (1 << 23), (i >> 23 & 0xff) - 150)
|
||||
if i & (1 << 31):
|
||||
f = -f
|
||||
elif length == 8:
|
||||
f = ldexp((i & ((1 << 52) - 1)) + (1 << 52), (i >> 52 & 0x7ff) - 1075)
|
||||
if i & (1 << 63):
|
||||
f = -f
|
||||
else:
|
||||
raise SyntaxError
|
||||
return f
|
||||
|
||||
def parse_one(s, depth, parent, maxlen):
|
||||
elid = hexlify(read_id(s)).decode('ascii')
|
||||
elem = elementd.get(elid)
|
||||
size, length = read_vint(s)
|
||||
this_length = len(elid) / 2 + size + length
|
||||
if elem is not None:
|
||||
if elem.valtype != 'skip':
|
||||
print(" " * depth, '[' + elid + ']', elem.name, 'size:', length, 'value:', end=' ')
|
||||
if elem.valtype == 'sub':
|
||||
print('subelements:')
|
||||
while length > 0:
|
||||
length -= parse_one(s, depth + 1, elem, length)
|
||||
if length < 0:
|
||||
raise SyntaxError
|
||||
elif elem.valtype == 'str':
|
||||
print('string', repr(read_str(s, length).decode('utf8', 'replace')))
|
||||
elif elem.valtype in ('binary', 'ebml_id'):
|
||||
t = read_str(s, length)
|
||||
dec = ''
|
||||
if elem.valtype == 'ebml_id':
|
||||
idelem = elementd.get(hexlify(t).decode('ascii'))
|
||||
if idelem is None:
|
||||
dec = '(UNKNOWN)'
|
||||
else:
|
||||
dec = '({0.name})'.format(idelem)
|
||||
if len(t) < 20:
|
||||
t = hexlify(t).decode('ascii')
|
||||
else:
|
||||
t = '<{0} bytes>'.format(len(t))
|
||||
print('binary', t, dec)
|
||||
elif elem.valtype == 'uint':
|
||||
print('uint', read_uint(s, length))
|
||||
elif elem.valtype == 'sint':
|
||||
print('sint', read_sint(s, length))
|
||||
elif elem.valtype == 'float':
|
||||
print('float', read_float(s, length))
|
||||
elif elem.valtype == 'skip':
|
||||
read(s, length)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
print(" " * depth, '[' + elid + '] Unknown element! size:', length)
|
||||
read(s, length)
|
||||
return this_length
|
||||
|
||||
if __name__ == "__main__":
|
||||
def parse_toplevel(s):
|
||||
parse_one(s, 0, None, 1 << 63)
|
||||
|
||||
if sys.argv[1] == '--generate-header':
|
||||
generate_C_header(sys.stdout)
|
||||
elif sys.argv[1] == '--generate-definitions':
|
||||
generate_C_definitions(sys.stdout)
|
||||
else:
|
||||
if sys.version_info.major < 3:
|
||||
raise Exception("Dumping requires Python 3.")
|
||||
s = open(sys.argv[1], "rb")
|
||||
while 1:
|
||||
start = s.tell()
|
||||
try:
|
||||
parse_toplevel(s)
|
||||
except EOF:
|
||||
if s.tell() != start:
|
||||
raise Exception("Unexpected end of file")
|
||||
break
|
||||
@@ -1,6 +0,0 @@
|
||||
StartChar: .notdef
|
||||
Encoding: 65536 -1 0
|
||||
Width: 400
|
||||
Flags: W
|
||||
LayerCount: 2
|
||||
EndChar
|
||||
@@ -1,77 +0,0 @@
|
||||
SplineFontDB: 3.0
|
||||
FontName: mpv-osd-symbols-Regular
|
||||
FullName: mpv-osd-symbols Regular
|
||||
FamilyName: mpv-osd-symbols
|
||||
Weight: Normal
|
||||
Copyright: This is generated file.
|
||||
Version: 001.000
|
||||
ItalicAngle: 0
|
||||
UnderlinePosition: -133
|
||||
UnderlineWidth: 50
|
||||
Ascent: 800
|
||||
Descent: 200
|
||||
InvalidEm: 0
|
||||
sfntRevision: 0x00010000
|
||||
LayerCount: 2
|
||||
Layer: 0 0 "Back" 1
|
||||
Layer: 1 0 "Fore" 0
|
||||
XUID: [1021 879 -1597228462 15927]
|
||||
StyleMap: 0x0040
|
||||
FSType: 8
|
||||
OS2Version: 3
|
||||
OS2_WeightWidthSlopeOnly: 0
|
||||
OS2_UseTypoMetrics: 0
|
||||
CreationTime: 1408646554
|
||||
ModificationTime: 1492879730
|
||||
PfmFamily: 81
|
||||
TTFWeight: 400
|
||||
TTFWidth: 5
|
||||
LineGap: 0
|
||||
VLineGap: 0
|
||||
Panose: 0 0 5 0 0 0 0 0 0 0
|
||||
OS2TypoAscent: 800
|
||||
OS2TypoAOffset: 0
|
||||
OS2TypoDescent: -200
|
||||
OS2TypoDOffset: 0
|
||||
OS2TypoLinegap: 90
|
||||
OS2WinAscent: 1000
|
||||
OS2WinAOffset: 0
|
||||
OS2WinDescent: 200
|
||||
OS2WinDOffset: 0
|
||||
HheadAscent: 1000
|
||||
HheadAOffset: 0
|
||||
HheadDescent: -200
|
||||
HheadDOffset: 0
|
||||
OS2SubXSize: 650
|
||||
OS2SubYSize: 600
|
||||
OS2SubXOff: 0
|
||||
OS2SubYOff: 75
|
||||
OS2SupXSize: 650
|
||||
OS2SupYSize: 600
|
||||
OS2SupXOff: 0
|
||||
OS2SupYOff: 350
|
||||
OS2StrikeYSize: 50
|
||||
OS2StrikeYPos: 220
|
||||
OS2Vendor: 'PfEd'
|
||||
OS2CodePages: 00000001.00000000
|
||||
OS2UnicodeRanges: 00000000.00000000.00000000.00000000
|
||||
DEI: 91125
|
||||
LangName: 1033 "" "" "Regular" "1.000;PfEd;mpv-osd-symbols-Regular" "mpv-osd-symbols" "Version 1.000;PS 001.000;hotconv 1.0.70;makeotf.lib2.5.58329"
|
||||
Encoding: UnicodeBmp
|
||||
UnicodeInterp: none
|
||||
NameList: AGL For New Fonts
|
||||
DisplaySize: -72
|
||||
AntiAlias: 1
|
||||
FitToEm: 0
|
||||
WinInfo: 57600 8 2
|
||||
BeginPrivate: 8
|
||||
BlueValues 31 [-10 0 640 650 720 730 800 810]
|
||||
BlueScale 5 0.037
|
||||
BlueShift 1 0
|
||||
BlueFuzz 1 0
|
||||
StdHW 4 [65]
|
||||
StdVW 4 [65]
|
||||
StemSnapH 8 [65 800]
|
||||
StemSnapV 8 [65 150]
|
||||
EndPrivate
|
||||
EndSplineFont
|
||||
@@ -1,16 +0,0 @@
|
||||
StartChar: uniE001
|
||||
Encoding: 57345 57345 1
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 780 20G<200 200>
|
||||
VStem: 200 375<400 400 400 800>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
575 400 m 1
|
||||
200 0 l 1
|
||||
200 800 l 1
|
||||
575 400 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,22 +0,0 @@
|
||||
StartChar: uniE002
|
||||
Encoding: 57346 57346 2
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 0 800<200 350 200 350 200 500 500 650>
|
||||
VStem: 200 150<0 800 0 800> 500 150<0 800 0 800>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
350 800 m 1
|
||||
350 0 l 1
|
||||
200 0 l 1
|
||||
200 800 l 1
|
||||
350 800 l 1
|
||||
650 800 m 1
|
||||
650 0 l 1
|
||||
500 0 l 1
|
||||
500 800 l 1
|
||||
650 800 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,17 +0,0 @@
|
||||
StartChar: uniE003
|
||||
Encoding: 57347 57347 3
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 0 720<110 775 110 775>
|
||||
VStem: 110 665<0 720 0 720>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
775 720 m 1
|
||||
775 0 l 1
|
||||
110 0 l 1
|
||||
110 720 l 1
|
||||
775 720 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,20 +0,0 @@
|
||||
StartChar: uniE004
|
||||
Encoding: 57348 57348 4
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 780 20G<423 423 813 813>
|
||||
VStem: 48 765<400 400>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
423 800 m 1
|
||||
423 0 l 1
|
||||
48 400 l 1
|
||||
423 800 l 1
|
||||
813 800 m 1
|
||||
813 0 l 1
|
||||
438 400 l 1
|
||||
813 800 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,20 +0,0 @@
|
||||
StartChar: uniE005
|
||||
Encoding: 57349 57349 5
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 780 20G<95 95 485 485>
|
||||
VStem: 95 765<400 400 400 800 400 800>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
470 400 m 1
|
||||
95 0 l 1
|
||||
95 800 l 1
|
||||
470 400 l 1
|
||||
860 400 m 1
|
||||
485 0 l 1
|
||||
485 800 l 1
|
||||
860 400 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,47 +0,0 @@
|
||||
StartChar: uniE006
|
||||
Encoding: 57350 57350 6
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: -10 11<396 461 396 543> 196 171<397 461 396 462> 401 31 801 9<397 462 397 397>
|
||||
VStem: 20 9<369 434 369 513> 224 173<369 408 367 434 367 434> 363 34 397 65<367 404 367 408 367 404 606 801> 462 173<368 404 404 404> 830 10<368 433 433 433>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
430 810 m 0x9940
|
||||
656 810 840 626 840 400 c 0
|
||||
840 174 656 -10 430 -10 c 0
|
||||
204 -10 20 174 20 400 c 0
|
||||
20 626 204 810 430 810 c 0x9940
|
||||
397 606 m 1x5280
|
||||
462 606 l 1
|
||||
462 801 l 1
|
||||
397 801 l 1
|
||||
397 606 l 1x5280
|
||||
462 367 m 1
|
||||
462 404 l 1
|
||||
710 627 l 1
|
||||
683 657 l 1
|
||||
439 437 l 1
|
||||
363 592 l 1
|
||||
318 570 l 1x4280
|
||||
397 408 l 1
|
||||
397 367 l 1x44
|
||||
462 367 l 1
|
||||
224 434 m 1
|
||||
29 434 l 1
|
||||
29 369 l 1
|
||||
224 369 l 1
|
||||
224 434 l 1
|
||||
830 368 m 1
|
||||
830 433 l 1
|
||||
635 433 l 1
|
||||
635 368 l 1
|
||||
830 368 l 1
|
||||
461 196 m 1
|
||||
396 196 l 1
|
||||
396 1 l 1
|
||||
461 1 l 1
|
||||
461 196 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,21 +0,0 @@
|
||||
StartChar: uniE007
|
||||
Encoding: 57351 57351 7
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: -10 80<339 430 339 543> 730 80<339 430>
|
||||
VStem: 20 80<309 491 309 513>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
430 -10 m 0
|
||||
204 -10 20 174 20 400 c 0
|
||||
20 626 204 810 430 810 c 0
|
||||
656 810 840 626 840 400 c 0
|
||||
840 174 656 -10 430 -10 c 0
|
||||
430 70 m 1
|
||||
430 730 l 1
|
||||
248 730 100 582 100 400 c 0
|
||||
100 218 248 70 430 70 c 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,37 +0,0 @@
|
||||
StartChar: uniE008
|
||||
Encoding: 57352 57352 8
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: -10 80<339 521 339 543> 240 160<269 313 546 590> 480 160<408 452> 730 80<339 521>
|
||||
VStem: 20 80<309 491 309 513> 211 160<298 342> 350 160<538 582> 488 160<298 342> 760 80<309 491>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
430 -10 m 0xfa80
|
||||
204 -10 20 174 20 400 c 0
|
||||
20 626 204 810 430 810 c 0
|
||||
656 810 840 626 840 400 c 0
|
||||
840 174 656 -10 430 -10 c 0xfa80
|
||||
430 70 m 0
|
||||
612 70 760 218 760 400 c 0
|
||||
760 582 612 730 430 730 c 0
|
||||
248 730 100 582 100 400 c 0
|
||||
100 218 248 70 430 70 c 0
|
||||
430 480 m 0
|
||||
386 480 350 516 350 560 c 0
|
||||
350 604 386 640 430 640 c 0
|
||||
474 640 510 604 510 560 c 0
|
||||
510 516 474 480 430 480 c 0
|
||||
291 240 m 0xfd80
|
||||
247 240 211 276 211 320 c 0
|
||||
211 364 247 400 291 400 c 0
|
||||
335 400 371 364 371 320 c 0
|
||||
371 276 335 240 291 240 c 0xfd80
|
||||
568 240 m 0
|
||||
524 240 488 276 488 320 c 0
|
||||
488 364 524 400 568 400 c 0
|
||||
612 400 648 364 648 320 c 0
|
||||
648 276 612 240 568 240 c 0
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,17 +0,0 @@
|
||||
StartChar: uniE009
|
||||
Encoding: 57353 57353 9
|
||||
Width: 880
|
||||
Flags: HMW
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
716 10 m 1
|
||||
378 244 l 1
|
||||
165 244 l 1
|
||||
165 559 l 1
|
||||
379 559 l 1
|
||||
716 793 l 1
|
||||
716 10 l 1
|
||||
EndSplineSet
|
||||
Validated: 1
|
||||
EndChar
|
||||
@@ -1,50 +0,0 @@
|
||||
StartChar: uniE00A
|
||||
Encoding: 57354 57354 10
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 252 48<406 406 456 456> 375 50<57 282 57 282 578 805> 500 48<406 406> 627 20G<149 149 713 713>
|
||||
VStem: 282 48<375 375 425 425> 406 50<26 252 26 252 548 774> 530 48<375 375>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
805 375 m 1
|
||||
578 375 l 1
|
||||
574 352 565 331 553 313 c 1
|
||||
713 153 l 1
|
||||
678 118 l 1
|
||||
518 278 l 1
|
||||
500 265 479 256 456 252 c 1
|
||||
456 26 l 1
|
||||
406 26 l 1
|
||||
406 252 l 1
|
||||
383 256 362 265 343 277 c 1
|
||||
184 118 l 1
|
||||
149 153 l 1
|
||||
308 312 l 1
|
||||
295 330 286 352 282 375 c 1
|
||||
57 375 l 1
|
||||
57 425 l 1
|
||||
282 425 l 1
|
||||
286 448 295 470 308 488 c 1
|
||||
149 647 l 1
|
||||
184 682 l 1
|
||||
343 523 l 1
|
||||
362 535 383 544 406 548 c 1
|
||||
406 774 l 1
|
||||
456 774 l 1
|
||||
456 548 l 1
|
||||
479 544 500 535 518 522 c 1
|
||||
678 682 l 1
|
||||
713 647 l 1
|
||||
553 487 l 1
|
||||
565 469 574 448 578 425 c 1
|
||||
805 425 l 1
|
||||
805 375 l 1
|
||||
430 300 m 0
|
||||
485 300 530 345 530 400 c 0
|
||||
530 455 485 500 430 500 c 0
|
||||
375 500 330 455 330 400 c 0
|
||||
330 345 375 300 430 300 c 0
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,27 +0,0 @@
|
||||
StartChar: uniE00B
|
||||
Encoding: 57355 57355 11
|
||||
Width: 880
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: -10 244<341 519 341 543> 566 54<413.5 446.5 413.5 519> 740 70<413.5 446.5>
|
||||
VStem: 20 88<354 446 354 513> 752 88<354 446>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
430 -10 m 0
|
||||
204 -10 20 174 20 400 c 0
|
||||
20 626 204 810 430 810 c 0
|
||||
656 810 840 626 840 400 c 0
|
||||
840 174 656 -10 430 -10 c 0
|
||||
430 620 m 0
|
||||
463 620 490 647 490 680 c 0
|
||||
490 713 463 740 430 740 c 0
|
||||
397 740 370 713 370 680 c 0
|
||||
370 647 397 620 430 620 c 0
|
||||
430 234 m 0
|
||||
608 234 752 308 752 400 c 0
|
||||
752 492 608 566 430 566 c 0
|
||||
252 566 108 492 108 400 c 0
|
||||
108 308 252 234 430 234 c 0
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,21 +0,0 @@
|
||||
StartChar: uniE010
|
||||
Encoding: 57360 57360 12
|
||||
Width: 334
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 0 90<221 258 221 258> 550 90<221 258 221 221>
|
||||
VStem: 76 145<90 550 90 640 90 640>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
258 640 m 1
|
||||
258 550 l 1
|
||||
221 550 l 1
|
||||
221 90 l 1
|
||||
258 90 l 1
|
||||
258 0 l 1
|
||||
76 0 l 1
|
||||
76 640 l 1
|
||||
258 640 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,17 +0,0 @@
|
||||
StartChar: uniE011
|
||||
Encoding: 57361 57361 13
|
||||
Width: 334
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 0 640<84 250 84 250>
|
||||
VStem: 84 166<0 640 0 640>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
250 640 m 1
|
||||
250 0 l 1
|
||||
84 0 l 1
|
||||
84 640 l 1
|
||||
250 640 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,21 +0,0 @@
|
||||
StartChar: uniE012
|
||||
Encoding: 57362 57362 14
|
||||
Width: 334
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 0 90<76 113 76 258 76 113> 550 90<76 113 76 258>
|
||||
VStem: 113 145<90 550 550 550>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
113 90 m 1
|
||||
113 550 l 1
|
||||
76 550 l 1
|
||||
76 640 l 1
|
||||
258 640 l 1
|
||||
258 0 l 1
|
||||
76 0 l 1
|
||||
76 90 l 1
|
||||
113 90 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
@@ -1,17 +0,0 @@
|
||||
StartChar: uniE013
|
||||
Encoding: 57363 57363 15
|
||||
Width: 334
|
||||
GlyphClass: 2
|
||||
Flags: MW
|
||||
HStem: 255 130<102 232 102 232>
|
||||
VStem: 102 130<255 385 255 385>
|
||||
LayerCount: 2
|
||||
Fore
|
||||
SplineSet
|
||||
232 385 m 1
|
||||
232 255 l 1
|
||||
102 255 l 1
|
||||
102 385 l 1
|
||||
232 385 l 1
|
||||
EndSplineSet
|
||||
EndChar
|
||||
Loaded 100 of 854 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user