From 5b1c3e4b500c69c5c07a6e6b2b65902ea4ce56a4 Mon Sep 17 00:00:00 2001 From: robin007bond Date: Mon, 13 Apr 2015 14:22:36 +0200 Subject: OSX/mpv.app/mpv.conf: Use pseudo-gui The player is now forced to use the pseudo-gui profile. Fixes #1808 and #1754. Signed-off-by: wm4 --- TOOLS/osxbundle/mpv.app/Contents/Resources/mpv.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TOOLS/osxbundle/mpv.app/Contents/Resources/mpv.conf b/TOOLS/osxbundle/mpv.app/Contents/Resources/mpv.conf index ff78dfacf6..7527de0d1b 100644 --- a/TOOLS/osxbundle/mpv.app/Contents/Resources/mpv.conf +++ b/TOOLS/osxbundle/mpv.app/Contents/Resources/mpv.conf @@ -1,3 +1,2 @@ screenshot-template=~/Desktop/shot%n -quiet -idle=once +profile=pseudo-gui -- cgit v1.2.3 From 3b2cc79d2f42eefebf4390ccf722e1bb02d6f734 Mon Sep 17 00:00:00 2001 From: robin007bond Date: Mon, 13 Apr 2015 14:51:03 +0200 Subject: DOCS/contribute.md: Add guideline for pull requests This commit is to prevent changes being merged into upstream, without being known if it is tested or not. Signed-off-by: wm4 --- DOCS/contribute.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DOCS/contribute.md b/DOCS/contribute.md index 224c52494c..11b5e33d50 100644 --- a/DOCS/contribute.md +++ b/DOCS/contribute.md @@ -14,6 +14,9 @@ Sending patches ``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. +- When creating pull requests, be sure to test your changes. If you didn't, please + say so in the pull request message. + - Write informative commit messages. Use present tense to describe the situation with the patch applied, and past tense for the situation before the change. -- cgit v1.2.3 From 77c96f111c3b9471bdbf19769049dadf348a14a8 Mon Sep 17 00:00:00 2001 From: Martin Herkt Date: Mon, 13 Apr 2015 18:30:11 +0200 Subject: man/options: make --audio-display easier to find MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I tried to find that option by searching for terms like “cover art” and got nothing. I imagine most users would look for similar terms. Hope this helps. --- DOCS/man/options.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index b380db9ffb..bca089c61b 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -983,8 +983,9 @@ Audio ``--audio-display=`` Setting this option to ``attachment`` (default) will display image - attachments when playing audio files. It will display the first image - found, and additional images are available as video tracks. + attachments (e.g. album cover art) when playing audio files. It will + display the first image found, and additional images are available as + video tracks. Setting this option to ``no`` disables display of video entirely when playing audio files. -- cgit v1.2.3 From 3823d5eb7efad4d35c5c8e49f95656ec781c5584 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 13 Apr 2015 18:33:06 +0200 Subject: vo_rpi: explicitly reference MMAL VC driver This is optional, but ensures that linking with -Wl,--as-needed does not drop the MMAL VC driver. The driver normally "registers" itself in the library constructor, but since no symbols are explicitly referenced, the linker could remove it with as-needed enabled. --- video/out/vo_rpi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/video/out/vo_rpi.c b/video/out/vo_rpi.c index 48827b8a67..c60218d575 100644 --- a/video/out/vo_rpi.c +++ b/video/out/vo_rpi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -488,6 +489,8 @@ static void uninit(struct vo *vo) if (p->display) vc_dispmanx_display_close(p->display); + + mmal_vc_deinit(); } static int preinit(struct vo *vo) @@ -500,6 +503,11 @@ static int preinit(struct vo *vo) bcm_host_init(); + if (mmal_vc_init()) { + MP_FATAL(vo, "Could not initialize MMAL.\n"); + return -1; + } + p->display = vc_dispmanx_display_open(p->display_nr); p->update = vc_dispmanx_update_start(0); if (!p->display || !p->update) { -- cgit v1.2.3 From 9e0cd3b3e75e0970b1d6eb2cbcba770fc5112f9e Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 13 Apr 2015 20:30:17 +0200 Subject: options: don't let --vf-clr etc. take an argument It was ignored before. Passing an argument makes no sense, and might be mistaken for some form of --vf-del, so complain about it. This also affects --af-clr and the vf/af commands. --- options/m_option.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/options/m_option.c b/options/m_option.c index 165656500d..b5c865b8b4 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -2934,6 +2934,11 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, } if (op == OP_CLR) { + if (param.len) { + mp_err(log, "Option %.*s: -clr does not take an argument.\n", + BSTR_P(name)); + return M_OPT_INVALID; + } if (dst) free_obj_settings_list(dst); return 0; -- cgit v1.2.3 From d704d61c61ad3f3660d579a830704e6f2396ad6e Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 14 Apr 2015 14:29:05 +0200 Subject: vo_opengl: change dwmflush option values Use a choice instead of an integer. This is incompatible, but I'm not adding any compatibility since this option was added recently. --- DOCS/man/vo.rst | 7 ++++--- video/out/vo_opengl.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index 2447a8c455..4ac1dd8740 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -548,10 +548,11 @@ Available video output drivers are: X11/GLX only. - ``dwmflush`` - Calls ``DwmFlush`` after swapping buffers on Windows (default: 0). + ``dwmflush=`` + Calls ``DwmFlush`` after swapping buffers on Windows (default: no). It also sets ``SwapInterval(0)`` to ignore the OpenGL timing. Values - are: 0 (disabled), 1 (only in windowed mode), 2 (also in full screen). + are: no (disabled), windowed (only in windowed mode), yes (also in + full screen). This may help getting more consistent frame intervals, especially with high-fps clips - which might also reduce dropped frames. Typically a value of 1 should be enough since full screen may bypass the DWM. diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 136ad03c9f..e409eaa18d 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -507,7 +507,8 @@ static const struct m_option options[] = { OPT_FLAG("glfinish", use_glFinish, 0), OPT_FLAG("waitvsync", waitvsync, 0), OPT_INT("swapinterval", swap_interval, 0, OPTDEF_INT(1)), - OPT_INT("dwmflush", dwm_flush, 0, OPTDEF_INT(0)), + OPT_CHOICE("dwmflush", dwm_flush, 0, + ({"no", 0}, {"windowed", 1}, {"yes", 2})), OPT_FLAG("debug", use_gl_debug, 0), OPT_STRING_VALIDATE("backend", backend, 0, mpgl_validate_backend_opt), OPT_FLAG("sw", allow_sw, 0), -- cgit v1.2.3 From 0ded54dd89b6ac8fa5fe6caf6e26bd7e9342ab84 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 14 Apr 2015 14:33:37 +0200 Subject: input.conf: unmap menu key This was mapped to a broken command, so it did nothing but printing an error message. The intended binding (cycling OSD level) doesn't seem to useful either, so just drop it. --- etc/input.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/etc/input.conf b/etc/input.conf index 02b396956f..73be521c74 100644 --- a/etc/input.conf +++ b/etc/input.conf @@ -125,7 +125,6 @@ # cycle video aspect ratios; "-1" is the container aspect #A cycle_values video-aspect "16:9" "4:3" "2.35:1" "-1" #POWER quit -#MENU cycle osd #PLAY cycle pause #PAUSE cycle pause #PLAYPAUSE cycle pause -- cgit v1.2.3 From d8a0356b3bf8751938da7696b49da25bce5cd791 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 14 Apr 2015 14:36:15 +0200 Subject: player: silence spam in verbose mode when playing audio with cover art When playing cover art, it conceptually reaches EOF as soon as the image was put on the VO, causing the EOF message to be repeated every time new audio was decoded. Just silence the message. --- player/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/player/video.c b/player/video.c index 6c41593c72..2d3840b6b3 100644 --- a/player/video.c +++ b/player/video.c @@ -784,7 +784,7 @@ void write_video(struct MPContext *mpctx, double endpts) vo_still_displaying(vo) ? STATUS_DRAINING : STATUS_EOF; mpctx->delay = 0; mpctx->last_av_difference = 0; - MP_VERBOSE(mpctx, "video EOF (status=%d)\n", mpctx->video_status); + MP_DBG(mpctx, "video EOF (status=%d)\n", mpctx->video_status); return; } -- cgit v1.2.3 From 7d40a33ed9a707d1e6dcfa70ff96bd09f23a82be Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 14 Apr 2015 21:18:36 +0200 Subject: mapage: update --hwdec=vaapi description again Supposedly this is not an issue anymore after we've changed the code to use texture-from-pixmap. --- DOCS/man/options.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index bca089c61b..31461817a9 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -566,8 +566,7 @@ Video The ``vaapi-copy`` mode allows you to use vaapi with any VO. Because this copies the decoded video back to system RAM, it's likely less efficient - than the ``vaapi`` mode. But there are reports that this is actually faster - as well, and avoids many issues with ``vaapi``. + than the ``vaapi`` mode. .. note:: -- cgit v1.2.3 From 2896afaa39856f22da0ed7439dbd16edc225c2c4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 14 Apr 2015 21:19:01 +0200 Subject: ao_alsa: fallback to stereo channel layout if everything else fails mp_chmap_from_channels_alsa() doesn't always succeed - there are a bunch of channel counts for which no defined ALSA layout exists. Fallback to stereo in this case. (Normally, this code path shouldn't happen at all.) --- audio/out/ao_alsa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index f26c4cedb0..f4565da0dc 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -492,8 +492,11 @@ static int init_device(struct ao *ao) } if (num_channels != ao->channels.num) { - MP_ERR(ao, "Couldn't get requested number of channels.\n"); mp_chmap_from_channels_alsa(&ao->channels, num_channels); + if (!mp_chmap_is_valid(&ao->channels)) + mp_chmap_from_channels(&ao->channels, 2); + MP_ERR(ao, "Couldn't get requested number of channels, fallback to %s.\n", + mp_chmap_to_str(&ao->channels)); } // Some ALSA drivers have broken delay reporting, so disable the ALSA -- cgit v1.2.3 From e1e46cc81afcf75fbf3533215fe847c55927d0e5 Mon Sep 17 00:00:00 2001 From: Kevin Mitchell Date: Wed, 15 Apr 2015 03:50:00 -0700 Subject: manpage: remove extra newline at end of af.rst --- DOCS/man/af.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/DOCS/man/af.rst b/DOCS/man/af.rst index 1ae3c092df..2d227faad7 100644 --- a/DOCS/man/af.rst +++ b/DOCS/man/af.rst @@ -629,4 +629,3 @@ Available filters are: ``o=`` AVOptions. - -- cgit v1.2.3 From 3f8b8b8c0c6781771f83a726a389dc4b784b70ce Mon Sep 17 00:00:00 2001 From: Kevin Mitchell Date: Wed, 15 Apr 2015 03:48:05 -0700 Subject: manpage: clarify --af=format --- DOCS/man/af.rst | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/DOCS/man/af.rst b/DOCS/man/af.rst index 2d227faad7..96e50686ae 100644 --- a/DOCS/man/af.rst +++ b/DOCS/man/af.rst @@ -225,14 +225,21 @@ Available filters are: 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. + 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. All parameters are optional. The first 3 parameters restrict what the filter - 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. + 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. ```` Force conversion to this format. Use ``--af=format=format=help`` to get @@ -252,14 +259,9 @@ Available filters are: ```` - 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. + *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. ``convert24`` Filter for internal use only. Converts between 24-bit and 32-bit sample -- cgit v1.2.3 From e6d7e550125873f46126f3d23c4970df1976a269 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 15 Apr 2015 14:26:54 +0200 Subject: options: --hr-seek=always is the same as --hr-seek=yes It seems this choice was never documented. "always" is actually older than "yes", so just declare it a compatibility value for "yes". (Also move it before "always" in the C code to make this clear.) --- DOCS/man/options.rst | 1 + options/options.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 31461817a9..9fcb143ccc 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -181,6 +181,7 @@ Playback Control file, such as a chapter seek, but not for relative seeks like the default behavior of arrow keys (default). :yes: Use precise seeks whenever possible. + :always: Same as ``yes`` (for compatibility). ``--hr-seek-demuxer-offset=`` This option exists to work around failures to do precise seeks (as in diff --git a/options/options.c b/options/options.c index 8dc5cab255..4906d500a4 100644 --- a/options/options.c +++ b/options/options.c @@ -511,7 +511,7 @@ const m_option_t mp_opts[] = { ({"auto", 0}, {"decoder", 1}, {"sort", 2})), OPT_FLAG("initial-audio-sync", initial_audio_sync, 0), OPT_CHOICE("hr-seek", hr_seek, 0, - ({"no", -1}, {"absolute", 0}, {"always", 1}, {"yes", 1})), + ({"no", -1}, {"absolute", 0}, {"yes", 1}, {"always", 1})), OPT_FLOATRANGE("hr-seek-demuxer-offset", hr_seek_demuxer_offset, 0, -9, 99), OPT_FLAG("hr-seek-framedrop", hr_seek_framedrop, 0), OPT_CHOICE_OR_INT("autosync", autosync, 0, 0, 10000, -- cgit v1.2.3 From dd12040ebe7c4006eab56c0d4a18d495274cf37d Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 15 Apr 2015 22:39:01 +0200 Subject: x11: actually disable screensaver We already use 2 screensaver APIs when attempting to disable the screensaver: XResetScreenSaver() (from xlib) and XScreenSaverSuspend (from the X11 Screen Saver extension). None of these actually work. On modern desktop Linux, we are expected to make dbus calls using some freedesktop-defined protocol (and possibly we'd have to fallback to a Gnome specific one). At least xscreensaver doesn't respect the "old" APIs either. Solve this by running the xdg-screensaver script. It's a terrible, ugly piece of shit (just read the script if you disagree), but at least it appears to work everywhere. It's also simpler than involving various dbus client libraries. I hope this can replace the --heartbeat-cmd option, and maybe we could remove our own DPMS/XSS code too. --- video/out/x11_common.c | 67 +++++++++++++++++++++++++++++++++++++++++--------- video/out/x11_common.h | 6 +++++ 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 392da3cee0..36a497055a 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -38,6 +38,10 @@ #include "vo.h" #include "win_state.h" #include "osdep/timer.h" +#include "osdep/subprocess.h" + +// Specifically for mp_cancel +#include "stream/stream.h" #include #include @@ -470,6 +474,30 @@ static void vo_x11_get_bounding_monitors(struct vo_x11_state *x11, long b[4]) #endif } +static void *screensaver_thread(void *arg) +{ + struct vo_x11_state *x11 = arg; + + for (;;) { + sem_wait(&x11->screensaver_sem); + // don't queue multiple wakeups + while (!sem_trywait(&x11->screensaver_sem)) {} + + if (mp_cancel_test(x11->screensaver_terminate)) + break; + + char *args[] = {"xdg-screensaver", "reset", NULL}; + if (mp_subprocess(args, x11->screensaver_terminate, NULL, NULL, + NULL, &(char*){0})) + { + MP_WARN(x11, "Disabling screensaver failed.\n"); + break; + } + } + + return NULL; +} + int vo_x11_init(struct vo *vo) { struct mp_vo_opts *opts = vo->opts; @@ -487,6 +515,14 @@ int vo_x11_init(struct vo *vo) }; vo->x11 = x11; + x11->screensaver_terminate = mp_cancel_new(x11); + sem_init(&x11->screensaver_sem, 0, 0); + if (pthread_create(&x11->screensaver_thread, NULL, screensaver_thread, x11)) { + x11->screensaver_terminate = NULL; + sem_destroy(&x11->screensaver_sem); + goto error; + } + x11_error_output = x11->log; XSetErrorHandler(x11_errorhandler); @@ -498,13 +534,7 @@ int vo_x11_init(struct vo *vo) if (!x11->display) { MP_MSG(x11, vo->probing ? MSGL_V : MSGL_ERR, "couldn't open the X11 display (%s)!\n", dispName); - - x11_error_output = NULL; - XSetErrorHandler(NULL); - - talloc_free(x11); - vo->x11 = NULL; - return 0; + goto error; } x11->screen = DefaultScreen(x11->display); // screen ID x11->rootwin = RootWindow(x11->display, x11->screen); // root window ID @@ -543,6 +573,10 @@ int vo_x11_init(struct vo *vo) vo_x11_update_geometry(vo); return 1; + +error: + vo_x11_uninit(vo); + return 0; } static const struct mp_keymap keymap[] = { @@ -691,9 +725,18 @@ void vo_x11_uninit(struct vo *vo) MP_VERBOSE(x11, "uninit ...\n"); if (x11->xim) XCloseIM(x11->xim); - x11_error_output = NULL; - XSetErrorHandler(NULL); - XCloseDisplay(x11->display); + if (x11->display) { + x11_error_output = NULL; + XSetErrorHandler(NULL); + XCloseDisplay(x11->display); + } + + if (x11->screensaver_terminate) { + mp_cancel_trigger(x11->screensaver_terminate); + sem_post(&x11->screensaver_sem); + pthread_join(x11->screensaver_thread, NULL); + sem_destroy(&x11->screensaver_sem); + } talloc_free(x11); vo->x11 = NULL; @@ -1766,7 +1809,7 @@ static void xscreensaver_heartbeat(struct vo_x11_state *x11) (time - x11->screensaver_time_last) >= 10) { x11->screensaver_time_last = time; - + sem_post(&x11->screensaver_sem); XResetScreenSaver(x11->display); } } @@ -1790,7 +1833,7 @@ static int xss_suspend(Display *mDisplay, Bool suspend) static void set_screensaver(struct vo_x11_state *x11, bool enabled) { Display *mDisplay = x11->display; - if (x11->screensaver_enabled == enabled) + if (!mDisplay || x11->screensaver_enabled == enabled) return; MP_VERBOSE(x11, "%s screensaver.\n", enabled ? "Enabling" : "Disabling"); x11->screensaver_enabled = enabled; diff --git a/video/out/x11_common.h b/video/out/x11_common.h index f6d73dae00..eeff773bef 100644 --- a/video/out/x11_common.h +++ b/video/out/x11_common.h @@ -20,9 +20,12 @@ #include #include +#include #include #include +#include "osdep/semaphore.h" + #include "common/common.h" struct vo; @@ -57,6 +60,9 @@ struct vo_x11_state { bool screensaver_enabled; bool dpms_touched; double screensaver_time_last; + pthread_t screensaver_thread; + sem_t screensaver_sem; + struct mp_cancel *screensaver_terminate; XIM xim; XIC xic; -- cgit v1.2.3 From 95c1487c93b2193680c5e0f064bbb8fb3b71ff2c Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 15 Apr 2015 22:42:20 +0200 Subject: subprocess-posix: always connect stdin to /dev/null It appears youtube-dl sometimes asks for a password on stdin. This won't work, because mpv already uses the terminal. (I wonder if this could be simpler, like simply closing FD 0, but let's not. The FD would be reused by something random.) --- osdep/subprocess-posix.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osdep/subprocess-posix.c b/osdep/subprocess-posix.c index c2120b2aa8..9d565f411e 100644 --- a/osdep/subprocess-posix.c +++ b/osdep/subprocess-posix.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,7 @@ int mp_subprocess(char **args, struct mp_cancel *cancel, void *ctx, int status = -1; int p_stdout[2] = {-1, -1}; int p_stderr[2] = {-1, -1}; + int devnull = -1; pid_t pid = -1; if (on_stdout && mp_make_cloexec_pipe(p_stdout) < 0) @@ -70,10 +72,16 @@ int mp_subprocess(char **args, struct mp_cancel *cancel, void *ctx, if (on_stderr && mp_make_cloexec_pipe(p_stderr) < 0) goto done; + devnull = open("/dev/null", O_RDONLY | O_CLOEXEC); + if (devnull < 0) + goto done; + if (posix_spawn_file_actions_init(&fa)) goto done; fa_destroy = true; - // redirect stdout and stderr + // redirect stdin/stdout/stderr + if (posix_spawn_file_actions_adddup2(&fa, devnull, 0)) + goto done; if (p_stdout[1] >= 0 && posix_spawn_file_actions_adddup2(&fa, p_stdout[1], 1)) goto done; if (p_stderr[1] >= 0 && posix_spawn_file_actions_adddup2(&fa, p_stderr[1], 2)) @@ -88,6 +96,8 @@ int mp_subprocess(char **args, struct mp_cancel *cancel, void *ctx, p_stdout[1] = -1; close(p_stderr[1]); p_stderr[1] = -1; + close(devnull); + devnull = -1; int *read_fds[2] = {&p_stdout[0], &p_stderr[0]}; subprocess_read_cb read_cbs[2] = {on_stdout, on_stderr}; @@ -133,6 +143,7 @@ done: close(p_stdout[1]); close(p_stderr[0]); close(p_stderr[1]); + close(devnull); if (WIFEXITED(status) && WEXITSTATUS(status) != 127) { *error = NULL; -- cgit v1.2.3 From d55c41501f3500d5d301f3cb4ea5c40816f9baae Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 15 Apr 2015 22:43:02 +0200 Subject: subprocess: move implementation for deatched subprocesses --- old-makefile | 1 + osdep/subprocess.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ osdep/subprocess.h | 3 +++ player/command.c | 35 +-------------------------------- wscript_build.py | 1 + 5 files changed, 63 insertions(+), 34 deletions(-) create mode 100644 osdep/subprocess.c diff --git a/old-makefile b/old-makefile index 2ec33455d3..876c1fe0d7 100644 --- a/old-makefile +++ b/old-makefile @@ -196,6 +196,7 @@ SOURCES = audio/audio.c \ options/path.c \ osdep/io.c \ osdep/semaphore_osx.c \ + osdep/subprocess.c \ osdep/subprocess-posix.c \ osdep/terminal-unix.c \ osdep/timer.c \ diff --git a/osdep/subprocess.c b/osdep/subprocess.c new file mode 100644 index 0000000000..84a1b52fe6 --- /dev/null +++ b/osdep/subprocess.c @@ -0,0 +1,57 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see . + */ + +#include + +#include "common/common.h" +#include "common/msg.h" +#include "common/msg_control.h" + +#include "subprocess.h" + +struct subprocess_args { + struct mp_log *log; + char **args; +}; + +static void *run_subprocess(void *ptr) +{ + struct subprocess_args *p = ptr; + pthread_detach(pthread_self()); + + mp_msg_flush_status_line(p->log); + + char *err = NULL; + if (mp_subprocess(p->args, NULL, NULL, NULL, NULL, &err) < 0) + mp_err(p->log, "Running subprocess failed: %s\n", err); + + talloc_free(p); + return NULL; +} + +void mp_subprocess_detached(struct mp_log *log, char **args) +{ + struct subprocess_args *p = talloc_zero(NULL, struct subprocess_args); + p->log = mp_log_new(p, log, NULL); + int num_args = 0; + for (int n = 0; args[n]; n++) + MP_TARRAY_APPEND(p, p->args, num_args, talloc_strdup(p, args[n])); + MP_TARRAY_APPEND(p, p->args, num_args, NULL); + pthread_t thread; + if (pthread_create(&thread, NULL, run_subprocess, p)) + talloc_free(p); +} diff --git a/osdep/subprocess.h b/osdep/subprocess.h index 09c07da981..1bd5afe1f8 100644 --- a/osdep/subprocess.h +++ b/osdep/subprocess.h @@ -29,4 +29,7 @@ int mp_subprocess(char **args, struct mp_cancel *cancel, void *ctx, subprocess_read_cb on_stdout, subprocess_read_cb on_stderr, char **error); +struct mp_log; +void mp_subprocess_detached(struct mp_log *log, char **args); + #endif diff --git a/player/command.c b/player/command.c index 88b3164436..6db3b2100b 100644 --- a/player/command.c +++ b/player/command.c @@ -3960,39 +3960,6 @@ static void overlay_uninit(struct MPContext *mpctx) osd_set_external2(mpctx->osd, NULL); } -struct subprocess_args { - struct mp_log *log; - char **args; -}; - -static void *run_subprocess(void *ptr) -{ - struct subprocess_args *p = ptr; - pthread_detach(pthread_self()); - - mp_msg_flush_status_line(p->log); - - char *err = NULL; - if (mp_subprocess(p->args, NULL, NULL, NULL, NULL, &err) < 0) - mp_err(p->log, "Running subprocess failed: %s\n", err); - - talloc_free(p); - return NULL; -} - -static void subprocess_detached(struct mp_log *log, char **args) -{ - struct subprocess_args *p = talloc_zero(NULL, struct subprocess_args); - p->log = mp_log_new(p, log, NULL); - int num_args = 0; - for (int n = 0; args[n]; n++) - MP_TARRAY_APPEND(p, p->args, num_args, talloc_strdup(p, args[n])); - MP_TARRAY_APPEND(p, p->args, num_args, NULL); - pthread_t thread; - if (pthread_create(&thread, NULL, run_subprocess, p)) - talloc_free(p); -} - struct cycle_counter { char **args; int counter; @@ -4599,7 +4566,7 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd) char *args[MP_CMD_MAX_ARGS + 1] = {0}; for (int n = 0; n < cmd->nargs; n++) args[n] = cmd->args[n].v.s; - subprocess_detached(mpctx->log, args); + mp_subprocess_detached(mpctx->log, args); break; } diff --git a/wscript_build.py b/wscript_build.py index 4478725596..e13a78107c 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -375,6 +375,7 @@ def build(ctx): ( "osdep/macosx_application.m", "cocoa-application" ), ( "osdep/macosx_events.m", "cocoa" ), ( "osdep/semaphore_osx.c" ), + ( "osdep/subprocess.c" ), ( "osdep/subprocess-posix.c", "posix-spawn" ), ( "osdep/subprocess-win.c", "os-win32" ), ( "osdep/path-macosx.m", "cocoa" ), -- cgit v1.2.3 From 7ee18376a9df40bc7aa4253f5e58203f788d73bc Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Wed, 15 Apr 2015 18:14:14 +0200 Subject: vo_drm: add KMS/DRM renderer support Signed-off-by: wm4 --- video/out/vo.c | 4 + video/out/vo_drm.c | 513 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wscript | 4 + wscript_build.py | 1 + 4 files changed, 522 insertions(+) create mode 100644 video/out/vo_drm.c diff --git a/video/out/vo.c b/video/out/vo.c index 4600205cb7..0e42193dbf 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -57,6 +57,7 @@ extern const struct vo_driver video_out_null; extern const struct vo_driver video_out_image; extern const struct vo_driver video_out_lavc; extern const struct vo_driver video_out_caca; +extern const struct vo_driver video_out_drm; extern const struct vo_driver video_out_direct3d; extern const struct vo_driver video_out_direct3d_shaders; extern const struct vo_driver video_out_sdl; @@ -97,6 +98,9 @@ const struct vo_driver *const video_out_drivers[] = #if HAVE_CACA &video_out_caca, #endif +#if HAVE_DRM + &video_out_drm, +#endif #if HAVE_ENCODING &video_out_lavc, #endif diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c new file mode 100644 index 0000000000..f05e6eb940 --- /dev/null +++ b/video/out/vo_drm.c @@ -0,0 +1,513 @@ +/* + * video output driver for libdrm + * + * by rr- + * + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/msg.h" +#include "sub/osd.h" +#include "video/fmt-conversion.h" +#include "video/mp_image.h" +#include "video/sws_utils.h" +#include "vo.h" + +#define BUF_COUNT 2 + +struct modeset_buf { + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t size; + uint32_t handle; + uint8_t *map; + uint32_t fb; +}; + +struct modeset_dev { + struct modeset_buf bufs[BUF_COUNT]; + drmModeModeInfo mode; + uint32_t conn; + uint32_t crtc; + int front_buf; +}; + +struct priv { + int fd; + struct modeset_dev *dev; + drmModeCrtc *old_crtc; + + char *device_path; + int connector_id; + + int32_t device_w; + int32_t device_h; + int32_t x, y; + struct mp_image *last_input; + struct mp_image *cur_frame; + struct mp_rect src; + struct mp_rect dst; + struct mp_osd_res osd; + struct mp_sws_context *sws; +}; + +static int modeset_open(struct vo *vo, int *out, const char *node) +{ + int fd = open(node, O_RDWR | O_CLOEXEC); + if (fd < 0) { + MP_ERR(vo, "Cannot open \"%s\": %s.\n", node, mp_strerror(errno)); + return -errno; + } + + uint64_t has_dumb; + if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0) { + MP_ERR(vo, "Device \"%s\" does not support dumb buffers.\n", node); + return -EOPNOTSUPP; + } + + *out = fd; + return 0; +} + +static void modeset_destroy_fb(int fd, struct modeset_buf *buf) +{ + if (buf->map) { + munmap(buf->map, buf->size); + } + if (buf->fb) { + drmModeRmFB(fd, buf->fb); + } + if (buf->handle) { + struct drm_mode_destroy_dumb dreq = { + .handle = buf->handle, + }; + drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); + } +} + +static int modeset_create_fb(struct vo *vo, int fd, struct modeset_buf *buf) +{ + int ret = 0; + + buf->handle = 0; + + // create dumb buffer + struct drm_mode_create_dumb creq = { + .width = buf->width, + .height = buf->height, + .bpp = 32, + }; + ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); + if (ret < 0) { + MP_ERR(vo, "Cannot create dumb buffer: %s\n", mp_strerror(errno)); + ret = -errno; + goto end; + } + buf->stride = creq.pitch; + buf->size = creq.size; + buf->handle = creq.handle; + + // create framebuffer object for the dumb-buffer + ret = drmModeAddFB(fd, buf->width, buf->height, 24, 32, buf->stride, + buf->handle, &buf->fb); + if (ret) { + MP_ERR(vo, "Cannot create framebuffer: %s\n", mp_strerror(errno)); + ret = -errno; + goto end; + } + + // prepare buffer for memory mapping + struct drm_mode_map_dumb mreq = { + .handle = buf->handle, + }; + ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); + if (ret) { + MP_ERR(vo, "Cannot map dumb buffer: %s\n", mp_strerror(errno)); + ret = -errno; + goto end; + } + + // perform actual memory mapping + buf->map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, mreq.offset); + if (buf->map == MAP_FAILED) { + MP_ERR(vo, "Cannot map dumb buffer: %s\n", mp_strerror(errno)); + ret = -errno; + goto end; + } + + memset(buf->map, 0, buf->size); + +end: + if (ret == 0) { + return 0; + } + + modeset_destroy_fb(fd, buf); + return ret; +} + +static int modeset_find_crtc(struct vo *vo, int fd, drmModeRes *res, + drmModeConnector *conn, struct modeset_dev *dev) +{ + for (unsigned int i = 0; i < conn->count_encoders; ++i) { + drmModeEncoder *enc = drmModeGetEncoder(fd, conn->encoders[i]); + if (!enc) { + MP_WARN(vo, "Cannot retrieve encoder %u:%u: %s\n", + i, conn->encoders[i], mp_strerror(errno)); + continue; + } + + // iterate all global CRTCs + for (unsigned int j = 0; j < res->count_crtcs; ++j) { + // check whether this CRTC works with the encoder + if (!(enc->possible_crtcs & (1 << j))) + continue; + + drmModeFreeEncoder(enc); + dev->crtc = res->crtcs[j]; + return 0; + } + + drmModeFreeEncoder(enc); + } + + MP_ERR(vo, "Connector %u has no suitable CRTC\n", conn->connector_id); + return -ENOENT; +} + +static bool is_connector_valid(struct vo *vo, int conn_id, + drmModeConnector *conn, bool silent) +{ + if (!conn) { + if (!silent) { + MP_ERR(vo, "Cannot get connector %d: %s\n", conn_id, + mp_strerror(errno)); + } + return false; + } + + if (conn->connection != DRM_MODE_CONNECTED) { + if (!silent) { + MP_ERR(vo, "Connector %d is disconnected\n", conn_id); + } + return false; + } + + if (conn->count_modes == 0) { + if (!silent) { + MP_ERR(vo, "Connector %d has no valid modes\n", conn_id); + } + return false; + } + + return true; +} + +static int modeset_prepare_dev(struct vo *vo, int fd, int conn_id, + struct modeset_dev **out) +{ + struct modeset_dev *dev = NULL; + drmModeConnector *conn = NULL; + + int ret = 0; + *out = NULL; + + drmModeRes *res = drmModeGetResources(fd); + if (!res) { + MP_ERR(vo, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno)); + ret = -errno; + goto end; + } + + if (conn_id == -1) { + // get the first connected connector + for (int i = 0; i < res->count_connectors; i++) { + conn = drmModeGetConnector(fd, res->connectors[i]); + if (is_connector_valid(vo, i, conn, true)) { + conn_id = i; + break; + } + if (conn) { + drmModeFreeConnector(conn); + conn = NULL; + } + } + if (conn_id == -1) { + MP_ERR(vo, "No connected connectors found\n"); + ret = -ENODEV; + goto end; + } + } + + if (conn_id < 0 || conn_id >= res->count_connectors) { + MP_ERR(vo, "Bad connector ID. Max valid connector ID = %u\n", + res->count_connectors); + ret = -ENODEV; + goto end; + } + + conn = drmModeGetConnector(fd, res->connectors[conn_id]); + if (!is_connector_valid(vo, conn_id, conn, true)) { + ret = -ENODEV; + goto end; + } + + dev = talloc_zero(vo->priv, struct modeset_dev); + dev->conn = conn->connector_id; + dev->front_buf = 0; + dev->mode = conn->modes[0]; + dev->bufs[0].width = conn->modes[0].hdisplay; + dev->bufs[0].height = conn->modes[0].vdisplay; + dev->bufs[1].width = conn->modes[0].hdisplay; + dev->bufs[1].height = conn->modes[0].vdisplay; + + MP_INFO(vo, "Connector using mode %ux%u\n", + dev->bufs[0].width, dev->bufs[0].height); + + ret = modeset_find_crtc(vo, fd, res, conn, dev); + if (ret) { + MP_ERR(vo, "Connector %d has no valid CRTC\n", conn_id); + goto end; + } + + for (unsigned int i = 0; i < BUF_COUNT; i++) { + ret = modeset_create_fb(vo, fd, &dev->bufs[i]); + if (ret) { + MP_ERR(vo, "Cannot create framebuffer for connector %d\n", + conn_id); + for (unsigned int j = 0; j < i; j++) { + modeset_destroy_fb(fd, &dev->bufs[j]); + } + goto end; + } + } + +end: + if (conn) { + drmModeFreeConnector(conn); + conn = NULL; + } + if (res) { + drmModeFreeResources(res); + res = NULL; + } + if (ret == 0) { + *out = dev; + } else { + talloc_free(dev); + } + return ret; +} + + + +static int reconfig(struct vo *vo, struct mp_image_params *params, int flags) +{ + struct priv *p = vo->priv; + + vo->dwidth = p->device_w; + vo->dheight = p->device_h; + vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd); + + int32_t w = p->dst.x1 - p->dst.x0; + int32_t h = p->dst.y1 - p->dst.y0; + + // p->osd contains the parameters assuming OSD rendering in window + // coordinates, but OSD can only be rendered in the intersection + // between window and video rectangle (i.e. not into panscan borders). + p->osd.w = w; + p->osd.h = h; + p->osd.mt = MPMIN(0, p->osd.mt); + p->osd.mb = MPMIN(0, p->osd.mb); + p->osd.mr = MPMIN(0, p->osd.mr); + p->osd.ml = MPMIN(0, p->osd.ml); + + p->x = (p->device_w - w) >> 1; + p->y = (p->device_h - h) >> 1; + + mp_sws_set_from_cmdline(p->sws, vo->opts->sws_opts); + p->sws->src = *params; + p->sws->dst = (struct mp_image_params) { + .imgfmt = IMGFMT_BGR0, + .w = w, + .h = h, + .d_w = w, + .d_h = h, + }; + + talloc_free(p->cur_frame); + p->cur_frame = mp_image_alloc(IMGFMT_BGR0, p->device_w, p->device_h); + mp_image_params_guess_csp(&p->sws->dst); + mp_image_set_params(p->cur_frame, &p->sws->dst); + + if (mp_sws_reinit(p->sws) < 0) + return -1; + + vo->want_redraw = true; + return 0; +} + +static void draw_image(struct vo *vo, mp_image_t *mpi) +{ + struct priv *p = vo->priv; + + struct mp_rect src_rc = p->src; + src_rc.x0 = MP_ALIGN_DOWN(src_rc.x0, mpi->fmt.align_x); + src_rc.y0 = MP_ALIGN_DOWN(src_rc.y0, mpi->fmt.align_y); + mp_image_crop_rc(mpi, src_rc); + + mp_sws_scale(p->sws, p->cur_frame, mpi); + + osd_draw_on_image(vo->osd, p->osd, mpi ? mpi->pts : 0, 0, p->cur_frame); + + struct modeset_buf *front_buf = &p->dev->bufs[p->dev->front_buf]; + int32_t shift = (p->device_w * p->y + p->x) * 4; + memcpy_pic(front_buf->map + shift, + p->cur_frame->planes[0], + (p->dst.x1 - p->dst.x0) * 4, + p->dst.y1 - p->dst.y0, + p->device_w * 4, + p->cur_frame->stride[0]); + + if (mpi != p->last_input) { + talloc_free(p->last_input); + p->last_input = mpi; + } +} + +static void flip_page(struct vo *vo) +{ + struct priv *p = vo->priv; + + int ret = drmModeSetCrtc(p->fd, p->dev->crtc, + p->dev->bufs[p->dev->front_buf].fb, + 0, 0, &p->dev->conn, 1, &p->dev->mode); + if (ret) { + MP_WARN(vo, "Cannot flip page for connector\n"); + } else { + p->dev->front_buf++; + p->dev->front_buf %= BUF_COUNT; + } +} + +static int preinit(struct vo *vo) +{ + struct priv *p = vo->priv; + p->sws = mp_sws_alloc(vo); + + int ret; + + ret = modeset_open(vo, &p->fd, p->device_path); + if (ret) + return -1; + + ret = modeset_prepare_dev(vo, p->fd, p->connector_id, &p->dev); + if (ret) + return -1; + + assert(p->dev); + p->device_w = p->dev->bufs[0].width; + p->device_h = p->dev->bufs[0].height; + + p->old_crtc = drmModeGetCrtc(p->fd, p->dev->crtc); + ret = drmModeSetCrtc(p->fd, p->dev->crtc, + p->dev->bufs[p->dev->front_buf + BUF_COUNT - 1].fb, + 0, 0, &p->dev->conn, 1, &p->dev->mode); + if (ret) { + MP_ERR(vo, "Cannot set CRTC for connector %u: %s\n", p->connector_id, + mp_strerror(errno)); + return -1; + } + + return 0; +} + +static void uninit(struct vo *vo) +{ + struct priv *p = vo->priv; + + if (p->dev) { + if (p->old_crtc) { + drmModeSetCrtc(p->fd, + p->old_crtc->crtc_id, + p->old_crtc->buffer_id, + p->old_crtc->x, + p->old_crtc->y, + &p->dev->conn, + 1, + &p->dev->mode); + drmModeFreeCrtc(p->old_crtc); + } + + modeset_destroy_fb(p->fd, &p->dev->bufs[1]); + modeset_destroy_fb(p->fd, &p->dev->bufs[0]); + } + + talloc_free(p->last_input); + talloc_free(p->cur_frame); + talloc_free(p->dev); +} + +static int query_format(struct vo *vo, int format) +{ + return sws_isSupportedInput(imgfmt2pixfmt(format)); +} + +static int control(struct vo *vo, uint32_t request, void *data) +{ + struct priv *p = vo->priv; + switch (request) { + case VOCTRL_REDRAW_FRAME: + draw_image(vo, p->last_input); + return VO_TRUE; + } + return VO_NOTIMPL; +} + +#define OPT_BASE_STRUCT struct priv + +const struct vo_driver video_out_drm = { + .name = "drm", + .description = "Direct Rendering Manager", + .preinit = preinit, + .query_format = query_format, + .reconfig = reconfig, + .control = control, + .draw_image = draw_image, + .flip_page = flip_page, + .uninit = uninit, + .priv_size = sizeof(struct priv), + .options = (const struct m_option[]) { + OPT_STRING("devpath", device_path, 0), + OPT_INT("connector", connector_id, 0), + {0}, + }, + .priv_defaults = &(const struct priv) { + .device_path = "/dev/dri/card0", + .connector_id = -1, + }, +}; diff --git a/wscript b/wscript index 4cf92d977d..7597bdc58b 100644 --- a/wscript +++ b/wscript @@ -631,6 +631,10 @@ video_output_features = [ 'name': '--caca', 'desc': 'CACA', 'func': check_pkg_config('caca', '>= 0.99.beta18'), + }, { + 'name': '--drm', + 'desc': 'DRM', + 'func': check_pkg_config('libdrm'), }, { 'name': '--jpeg', 'desc': 'JPEG support', diff --git a/wscript_build.py b/wscript_build.py index e13a78107c..7f65125ef5 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -344,6 +344,7 @@ def build(ctx): ( "video/out/gl_x11egl.c", "egl-x11" ), ( "video/out/vo.c" ), ( "video/out/vo_caca.c", "caca" ), + ( "video/out/vo_drm.c", "drm" ), ( "video/out/vo_direct3d.c", "direct3d" ), ( "video/out/vo_image.c" ), ( "video/out/vo_lavc.c", "encoding" ), -- cgit v1.2.3 From 9cabef39747e955eb9837d1d0c15d2956d8c5c3d Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Thu, 16 Apr 2015 21:43:01 +0200 Subject: vo_drm: add missing documentation --- DOCS/man/vo.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index 4ac1dd8740..b398d4f57d 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -920,3 +920,16 @@ Available video output drivers are: (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. + +``drm`` (Direct Rendering Manager) + Video output driver using Kernel Mode Setting / Direct Rendering Manager. + Does not support hardware acceleration. Should be used when one doesn't + want to install full-blown graphical environment (e.g. no X). + + ``connector=`` + Select the connector to use (usually this is a monitor.) If set to -1, + mpv renders the output on the first available connector. (default: -1) + + ``devpath=`` + Path to graphic card device. + (default: /dev/dri/card0) -- cgit v1.2.3 From 533b0c70e1f2cf5c1358c7147ae5546fcf1f6a64 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 16 Apr 2015 21:55:10 +0200 Subject: video: do not show decoder framedrops if they're not requested libavcodec makes it impossible to distinguish dropped frames (requested with AVCodecContext.skip_frame), and cases when the decoder simply does not return a frame by default (such as with VP9, which has invisible reference frames). This confuses users when decoding VP9 video. It's basically a cosmetic issue, so just paint it over by ignoring them if framedropping is disabled. --- DOCS/man/mpv.rst | 7 +++---- player/video.c | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DOCS/man/mpv.rst b/DOCS/man/mpv.rst index ca1e87105e..a530725548 100644 --- a/DOCS/man/mpv.rst +++ b/DOCS/man/mpv.rst @@ -517,10 +517,9 @@ listed. rendering is too slow. Also can be incremented on "hiccups" and when the video frame couldn't be displayed on time. (``vo-drop-frame-count`` property.) If the decoder drops frames, the number of decoder-dropped frames is appended - to the display as well, e.g.: ``Dropped: 4/34``. This should almost never - happen, unless decoder-framedropping is enabled with one of the - ``--framedrop`` options, the stream contains errors, or a weird codec is in - use. (``drop-frame-count`` property.) + to the display as well, e.g.: ``Dropped: 4/34``. This happens only if + decoder-framedropping is enabled with the ``--framedrop`` options. + (``drop-frame-count`` property.) - Cache state, e.g. ``Cache: 2s+134KB``. Visible if the stream cache is enabled. The first value shows the amount of video buffered in the demuxer in seconds, the second value shows *additional* data buffered in the stream cache in diff --git a/player/video.c b/player/video.c index 2d3840b6b3..978790b31c 100644 --- a/player/video.c +++ b/player/video.c @@ -405,7 +405,8 @@ static int decode_image(struct MPContext *mpctx) talloc_free(pkt); if (had_packet && !d_video->waiting_decoded_mpi && - mpctx->video_status == STATUS_PLAYING) + mpctx->video_status == STATUS_PLAYING && + (mpctx->opts->frame_dropping & 2)) { mpctx->dropped_frames_total++; mpctx->dropped_frames++; -- cgit v1.2.3 From 547976633f41c245b9accd6906166bb450e13557 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 16 Apr 2015 22:06:47 +0200 Subject: command: let screenshot_to_file command overwrite files The old behavior does not make too much sense after all. If you don't want to file to be overwritten, the user can check this manually. This is a change in behavior - let's hope nobody actually relied on it. --- DOCS/man/input.rst | 3 +-- player/screenshot.c | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index a3bad3706b..7209f508d9 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -187,8 +187,7 @@ List of Input Commands The second argument is like the first argument to ``screenshot``. - This command tries to never overwrite files. If the file already exists, - it fails. + If the file already exists, it's overwritten. Like all input command parameters, the filename is subject to property expansion as described in `Property Expansion`_. diff --git a/player/screenshot.c b/player/screenshot.c index ec01adffaa..3a1a41a4ca 100644 --- a/player/screenshot.c +++ b/player/screenshot.c @@ -370,11 +370,6 @@ void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode, bool old_osd = ctx->osd; ctx->osd = osd; - if (mp_path_exists(filename)) { - screenshot_msg(ctx, SMSG_ERR, "Screenshot: file '%s' already exists.", - filename); - goto end; - } char *ext = mp_splitext(filename, NULL); if (ext) opts.format = ext; -- cgit v1.2.3 From f4292ebf52fb2e58a1ddbefb06bccd47a38bdc99 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 16 Apr 2015 22:16:04 +0200 Subject: vf_screenshot: remove this filter It's entirely useless, especially now that vo.c handles screenshots in a generic way, and requires no special VO support. There are some potential weird use-cases, but actually I've never seen it being used. --- DOCS/man/mpv.rst | 7 ++--- DOCS/man/vf.rst | 6 ---- old-makefile | 1 - player/screenshot.c | 7 +---- video/filter/vf.c | 3 -- video/filter/vf.h | 1 - video/filter/vf_screenshot.c | 74 -------------------------------------------- wscript_build.py | 1 - 8 files changed, 3 insertions(+), 97 deletions(-) delete mode 100644 video/filter/vf_screenshot.c diff --git a/DOCS/man/mpv.rst b/DOCS/man/mpv.rst index a530725548..f8db13c336 100644 --- a/DOCS/man/mpv.rst +++ b/DOCS/man/mpv.rst @@ -475,11 +475,8 @@ A screenshot will usually contain the unscaled video contents at the end of the video filter chain and subtitles. By default, ``S`` takes screenshots without subtitles, while ``s`` includes subtitles. -The ``screenshot`` video filter is not required when using a recommended GUI -video output driver. It should normally not be added to the config file, as -taking screenshots is handled by the VOs, and adding the screenshot filter will -break hardware decoding. (The filter may still be useful for taking screenshots -at a certain point within the video chain when using multiple video filters.) +Unlike with MPlayer, the ``screenshot`` video filter is not required. This +filter was never required in mpv, and has been removed. TERMINAL STATUS LINE ==================== diff --git a/DOCS/man/vf.rst b/DOCS/man/vf.rst index be7daee09e..3739716340 100644 --- a/DOCS/man/vf.rst +++ b/DOCS/man/vf.rst @@ -561,12 +561,6 @@ Available filters are: ``show`` Draw a rectangle showing the area defined by x/y/w/h. -``screenshot`` - Optional filter for screenshot support. This is only needed if the video - output does not provide working direct screenshot support. Note that it is - not always safe to insert this filter by default. See `TAKING SCREENSHOTS`_ - for details. - ``sub=[=bottom-margin:top-margin]`` Moves subtitle rendering to an arbitrary point in the filter chain, or force subtitle rendering in the video filter as opposed to using video output OSD diff --git a/old-makefile b/old-makefile index 876c1fe0d7..7adc45d712 100644 --- a/old-makefile +++ b/old-makefile @@ -263,7 +263,6 @@ SOURCES = audio/audio.c \ video/filter/vf_mirror.c \ video/filter/vf_noformat.c \ video/filter/vf_scale.c \ - video/filter/vf_screenshot.c \ video/filter/vf_stereo3d.c \ video/filter/vf_sub.c \ video/out/bitmap_packer.c \ diff --git a/player/screenshot.c b/player/screenshot.c index 3a1a41a4ca..f722b9561f 100644 --- a/player/screenshot.c +++ b/player/screenshot.c @@ -32,7 +32,6 @@ #include "options/path.h" #include "video/mp_image.h" #include "video/decode/dec_video.h" -#include "video/filter/vf.h" #include "video/out/vo.h" #include "video/image_writer.h" #include "sub/osd.h" @@ -330,11 +329,7 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode) if (mode == MODE_SUBTITLES && osd_get_render_subs_in_filter(mpctx->osd)) mode = 0; - // vf_screenshot - if (mpctx->d_video && mpctx->d_video->vfilter) - vf_control_any(mpctx->d_video->vfilter, VFCTRL_SCREENSHOT, &image); - - if (!image && mpctx->video_out && mpctx->video_out->config_ok) { + if (mpctx->video_out && mpctx->video_out->config_ok) { vo_wait_frame(mpctx->video_out); // important for each-frame mode if (mode != MODE_FULL_WINDOW) diff --git a/video/filter/vf.c b/video/filter/vf.c index 888e937fa5..9bbe126823 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -54,7 +54,6 @@ extern const vf_info_t vf_info_hqdn3d; extern const vf_info_t vf_info_dsize; extern const vf_info_t vf_info_pullup; extern const vf_info_t vf_info_delogo; -extern const vf_info_t vf_info_screenshot; extern const vf_info_t vf_info_sub; extern const vf_info_t vf_info_yadif; extern const vf_info_t vf_info_stereo3d; @@ -88,8 +87,6 @@ static const vf_info_t *const filter_list[] = { &vf_info_yadif, #endif - &vf_info_screenshot, - &vf_info_eq, &vf_info_dsize, &vf_info_sub, diff --git a/video/filter/vf.h b/video/filter/vf.h index f7ee9d011b..76835528b5 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -144,7 +144,6 @@ enum vf_ctrl { VFCTRL_SEEK_RESET = 1, // reset on picture and PTS discontinuities VFCTRL_SET_EQUALIZER, // set color options (brightness,contrast etc) VFCTRL_GET_EQUALIZER, // get color options (brightness,contrast etc) - VFCTRL_SCREENSHOT, // Take screenshot, arg is mp_image** VFCTRL_INIT_OSD, // Filter OSD renderer present? VFCTRL_SET_DEINTERLACE, // Set deinterlacing status VFCTRL_GET_DEINTERLACE, // Get deinterlacing status diff --git a/video/filter/vf_screenshot.c b/video/filter/vf_screenshot.c deleted file mode 100644 index 57cd9fbb0b..0000000000 --- a/video/filter/vf_screenshot.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "talloc.h" - -#include "video/img_format.h" -#include "video/mp_image.h" -#include "video/sws_utils.h" -#include "video/out/vo.h" - -#include "vf.h" - -struct vf_priv_s { - struct mp_image *current; -}; - -static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) -{ - mp_image_unrefp(&vf->priv->current); - vf->priv->current = talloc_steal(vf, mp_image_new_ref(mpi)); - return mpi; -} - -static int control (vf_instance_t *vf, int request, void *data) -{ - if (request == VFCTRL_SCREENSHOT && vf->priv->current) { - *(struct mp_image **)data = mp_image_new_ref(vf->priv->current); - return CONTROL_TRUE; - } - return CONTROL_UNKNOWN; -} - -static int query_format(struct vf_instance *vf, unsigned int fmt) -{ - if (mp_sws_supported_format(fmt)) - return vf_next_query_format(vf, fmt); - return 0; -} - -static int vf_open(vf_instance_t *vf) -{ - vf->control = control; - vf->filter = filter; - vf->query_format = query_format; - vf->priv = talloc_zero(vf, struct vf_priv_s); - return 1; -} - -const vf_info_t vf_info_screenshot = { - .description = "screenshot to file", - .name = "screenshot", - .open = vf_open, -}; diff --git a/wscript_build.py b/wscript_build.py index 7f65125ef5..280e6a62ae 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -311,7 +311,6 @@ def build(ctx): ( "video/filter/vf_pullup.c", "libavfilter"), ( "video/filter/vf_rotate.c", "libavfilter"), ( "video/filter/vf_scale.c" ), - ( "video/filter/vf_screenshot.c" ), ( "video/filter/vf_stereo3d.c" ), ( "video/filter/vf_sub.c" ), ( "video/filter/vf_unsharp.c", "libavfilter"), -- cgit v1.2.3 From e0bb60a7085775b02b7c7ef33e07cfaeda1bff32 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 16 Apr 2015 22:29:25 +0200 Subject: vo: cosmetics: reindent VO list And also undoxygenify a comment. (There used to be some inconsistent doxygen comments in MPlayer time; they are being removed on sight.) --- video/out/vo.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/video/out/vo.c b/video/out/vo.c index 0e42193dbf..3a193c38e8 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -68,50 +68,50 @@ extern const struct vo_driver video_out_rpi; const struct vo_driver *const video_out_drivers[] = { #if HAVE_RPI - &video_out_rpi, + &video_out_rpi, #endif #if HAVE_GL - &video_out_opengl, + &video_out_opengl, #endif #if HAVE_VDPAU - &video_out_vdpau, + &video_out_vdpau, #endif #if HAVE_DIRECT3D - &video_out_direct3d_shaders, - &video_out_direct3d, + &video_out_direct3d_shaders, + &video_out_direct3d, #endif #if HAVE_XV - &video_out_xv, + &video_out_xv, #endif #if HAVE_SDL2 - &video_out_sdl, + &video_out_sdl, #endif #if HAVE_VAAPI - &video_out_vaapi, + &video_out_vaapi, #endif #if HAVE_X11 - &video_out_x11, + &video_out_x11, #endif - &video_out_null, - // should not be auto-selected - &video_out_image, + &video_out_null, + // should not be auto-selected + &video_out_image, #if HAVE_CACA - &video_out_caca, + &video_out_caca, #endif #if HAVE_DRM - &video_out_drm, + &video_out_drm, #endif #if HAVE_ENCODING - &video_out_lavc, + &video_out_lavc, #endif #if HAVE_GL - &video_out_opengl_hq, - &video_out_opengl_cb, + &video_out_opengl_hq, + &video_out_opengl_cb, #endif #if HAVE_WAYLAND - &video_out_wayland, + &video_out_wayland, #endif - NULL + NULL }; struct vo_internal { @@ -987,10 +987,10 @@ struct mp_image *vo_get_current_frame(struct vo *vo) return r; } -/** - * \brief lookup an integer in a table, table must have 0 as the last key - * \param key key to search for - * \result translation corresponding to key or "to" value of last mapping +/* + * lookup an integer in a table, table must have 0 as the last key + * param: key key to search for + * returns translation corresponding to key or "to" value of last mapping * if not found. */ int lookup_keymap_table(const struct mp_keymap *map, int key) -- cgit v1.2.3 From baaa27d6dbb22b5e4cb1bf06e5b4b8178849cba5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 16 Apr 2015 22:31:09 +0200 Subject: vo: fix non-sense in init code I assume this was intended to generate an initial change event in order to make the user read the initial values. --- video/out/vo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/out/vo.c b/video/out/vo.c index 3a193c38e8..70f682263e 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -755,7 +755,7 @@ static void *vo_thread(void *ptr) return NULL; update_display_fps(vo); - vo_event(vo, VO_WIN_STATE_MINIMIZED); + vo_event(vo, VO_EVENT_WIN_STATE); while (1) { mp_dispatch_queue_process(vo->in->dispatch, 0); -- cgit v1.2.3 From e207c24b32a457859ab6e3a5b1f5f9eaeea36ed1 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 16 Apr 2015 22:42:31 +0200 Subject: vf_mirror: replace internal implementation with libavfilter Currently, libavfilter's equivalent vf_hflip is probably not faster or anything, but there's still no reason to keep the internal code. --- video/filter/vf_mirror.c | 89 +++--------------------------------------------- 1 file changed, 4 insertions(+), 85 deletions(-) diff --git a/video/filter/vf_mirror.c b/video/filter/vf_mirror.c index d92f320235..342c6abd2a 100644 --- a/video/filter/vf_mirror.c +++ b/video/filter/vf_mirror.c @@ -15,93 +15,14 @@ * with mpv. If not, see . */ -#include -#include -#include -#include +#include -#include "config.h" -#include "common/msg.h" - -#include "video/img_format.h" -#include "video/mp_image.h" #include "vf.h" +#include "vf_lavfi.h" -static int config(struct vf_instance *vf, int width, int height, - int d_width, int d_height, - unsigned int flags, unsigned int fmt) -{ - struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(fmt); - int a_w = MP_ALIGN_DOWN(width, desc.align_x); - vf_rescale_dsize(&d_width, &d_height, width, height, a_w, height); - return vf_next_config(vf, a_w, height, d_width, d_height, flags, fmt); -} - -static inline void mirror_4_m(uint8_t *dst, uint8_t *src, int p, - int c0, int c1, int c2, int c3) -{ - for (int x = 0; x < p; x++) { - dst[x * 4 + 0] = src[(p - x - 1) * 4 + c0]; - dst[x * 4 + 1] = src[(p - x - 1) * 4 + c1]; - dst[x * 4 + 2] = src[(p - x - 1) * 4 + c2]; - dst[x * 4 + 3] = src[(p - x - 1) * 4 + c3]; - } -} - -static inline void mirror(uint8_t *dst, uint8_t *src, int bp, int w) -{ - for (int x = 0; x < w; x++) - memcpy(dst + x * bp, src + (w - x - 1) * bp, bp); -} - -static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +static int vf_open(vf_instance_t *vf) { - mp_image_t *dmpi = vf_alloc_out_image(vf); - if (!dmpi) - retur