summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-12-24 09:24:22 +0100
committerwm4 <wm4@nowhere>2019-12-24 09:24:22 +0100
commit380f01567d183a4dd5c4f86a58470145a29f578d (patch)
tree9146b216d3ad249744e8a63ce9b6ad6b45b092a4
parente7add205d8fdfcb31a569e282284b10db83130b9 (diff)
downloadmpv-380f01567d183a4dd5c4f86a58470145a29f578d.tar.bz2
mpv-380f01567d183a4dd5c4f86a58470145a29f578d.tar.xz
vd_lavc: more hwdec autoselect nonsense
Add an "auto-safe" mode, mostly triggered by Ubuntu's nonsense to force hwdec=vaapi in the global config file in their mpv package. But to be honest it's probably something more people want. This is implemented as explicit whitelist. On Windows, HEVC/Intel is sometimes broken, but it's still whitelisted, and in theory we'd need a detailed whitelist of device names etc. (like for example browsers tend to do). On OSX, videotoolbox is a pretty bad choice, but unfortunately the only one, so it's whitelisted too. There may be a larger number of hwdec wrappers that work anyway, and I'm for example ignoring Android.
-rw-r--r--DOCS/man/options.rst40
-rw-r--r--video/decode/vd_lavc.c66
2 files changed, 85 insertions, 21 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 8ff149d86d..522656625d 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -998,7 +998,10 @@ Video
Always enabling HW decoding by putting it into the config file is
discouraged. If you use the Ubuntu package, delete ``/etc/mpv/mpv.conf``,
- as the package tries to enable HW decoding by default.
+ as the package tries to enable HW decoding by default by setting
+ ``hwdec=vaapi`` (which is less than ideal, and may even cause
+ sub-optimal wrappers to be used). Or at least change it to
+ ``hwdec=auto-safe``.
Use one of the auto modes if you want to enable hardware decoding.
Explicitly selecting the mode is mostly meant for testing and debugging.
@@ -1010,11 +1013,25 @@ Video
Even if enabled, hardware decoding is still only white-listed for some
codecs. See ``--hwdec-codecs`` to enable hardware decoding in more cases.
+ .. admonition:: Which method to choose?
+
+ - If you only want to enable hardware decoding at runtime, don't set the
+ parameter, or put ``hwdec=no`` into your ``mpv.conf`` (relevant on
+ distros which force-enable it by default, such as on Ubuntu). Use the
+ ``Ctrl+h`` default binding to enable it at runtime.
+ - If you're not sure, but want hardware decoding always enabled by
+ default, put ``hwdec=auto-safe`` into your ``mpv.conf``, and
+ acknowledge that this use case is not "really" supported and may cause
+ problems.
+ - If you want to test available hardware decoding methods, pass
+ ``--hwdec=auto --hwdec-codecs`` and look at the terminal output.
+
``<api>`` can be one of the following:
:no: always use software decoding (default)
- :auto: enable best hw decoder (see below)
+ :auto: forcibly enable any hw decoder found (see below)
:yes: exactly the same as ``auto``
+ :auto-safe: enable any whitelisted hw decoder (see below)
:auto-copy: enable best hw decoder with copy-back (see below)
:vdpau: requires ``--vo=gpu`` with X11, or ``--vo=vdpau`` (Linux only)
:vdpau-copy: copies video back into system RAM (Linux with some GPUs only)
@@ -1048,6 +1065,20 @@ Video
work, it will always fall back to software decoding, instead of trying the
next method (might matter on some Linux systems).
+ ``auto-safe`` is similar to ``auto``, but allows only whitelisted methods
+ that are considered "safe". This is supposed to be a reasonable way to
+ enable hardware decdoding by default in a config file (even though you
+ shouldn't do that anyway; prefer runtime enabling with ``Ctrl+h``). Unlike
+ ``auto``, this will not try to enable unknown or known-to-be-bad methods. In
+ addition, this may disable hardware decoding in other situations when it's
+ known to cause problems, but currently this mechanism is quite primitive.
+ (As an example for something that still causes problems: certain
+ combinations of HEVC and Intel chips on Windows tend to cause mpv to crash,
+ most likely due to driver bugs.)
+
+ ``auto-copy-safe`` selects the union of methods selected with ``auto-safe``
+ and ``auto-copy``.
+
``auto-copy`` selects only modes that copy the video data back to system
memory after decoding. This selects modes like ``vaapi-copy`` (and so on).
If none of these work, hardware decoding is disabled. This mode is usually
@@ -1074,8 +1105,9 @@ Video
output path. To use this deinterlacing you must pass the option:
``vd-lavc-o=deint=[weave|bob|adaptive]``.
Pass ``weave`` (or leave the option unset) to not attempt any
- deinterlacing. ``cuda`` should always be preferred unless the ``gpu``
- vo is not being used or filters are required.
+ deinterlacing. ``cuda`` should always be preferred over ``cuda-copy`` unless
+ the ``gpu`` vo is not being used or filters are required. Using ``nvdec``
+ should be preferred on Nvidia hardware.
``nvdec`` is a newer implementation of CUVID/CUDA decoding, which uses the
FFmpeg decoders for file parsing. Experimental, is known not to correctly
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 3f0eedc47c..985a2b6d2e 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -155,6 +155,7 @@ struct hwdec_info {
enum AVPixelFormat pix_fmt; // if not NONE, select in get_format
bool use_hw_frames; // set AVCodecContext.hw_frames_ctx
bool use_hw_device; // set AVCodecContext.hw_device_ctx
+ unsigned int flags; // HWDEC_FLAG_*
// for internal sorting
int auto_pos;
@@ -216,19 +217,33 @@ typedef struct lavc_ctx {
struct mp_decoder public;
} vd_ffmpeg_ctx;
+enum {
+ HWDEC_FLAG_AUTO = (1 << 0), // prioritize in autoprobe order
+ HWDEC_FLAG_WHITELIST = (1 << 1), // whitelist for auto-safe
+};
+
+struct autoprobe_info {
+ const char *method_name;
+ unsigned int flags; // HWDEC_FLAG_*
+};
+
// Things not included in this list will be tried last, in random order.
-static const char *const hwdec_autoprobe_order[] = {
- "d3d11va",
- "dxva2",
- "dxva2-copy",
- "d3d11va-copy",
- "nvdec",
- "nvdec-copy",
- "vaapi",
- "vaapi-copy",
- "vdpau",
- "vdpau-copy",
- 0
+const struct autoprobe_info hwdec_autoprobe_info[] = {
+ {"d3d11va", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"dxva2", HWDEC_FLAG_AUTO},
+ {"dxva2-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"d3d11va-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"nvdec", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"nvdec-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"vaapi", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"vaapi-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"vdpau", HWDEC_FLAG_AUTO},
+ {"vdpau-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"mmal", HWDEC_FLAG_AUTO},
+ {"mmal-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"videotoolbox", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {"videotoolbox-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
+ {0}
};
static int hwdec_compare(const void *p1, const void *p2)
@@ -266,9 +281,14 @@ static void add_hwdec_item(struct hwdec_info **infos, int *num_infos,
info.rank = *num_infos;
info.auto_pos = INT_MAX;
- for (int x = 0; hwdec_autoprobe_order[x]; x++) {
- if (strcmp(hwdec_autoprobe_order[x], info.method_name) == 0)
- info.auto_pos = x;
+
+ for (int x = 0; hwdec_autoprobe_info[x].method_name; x++) {
+ const struct autoprobe_info *entry = &hwdec_autoprobe_info[x];
+ if (strcmp(entry->method_name, info.method_name) == 0) {
+ info.flags |= entry->flags;
+ if (info.flags & HWDEC_FLAG_AUTO)
+ info.auto_pos = x;
+ }
}
MP_TARRAY_APPEND(NULL, *infos, *num_infos, info);
@@ -434,8 +454,11 @@ static void select_and_set_hwdec(struct mp_filter *vd)
bool hwdec_auto_all = bstr_equals0(opt, "auto") ||
bstr_equals0(opt, "yes") ||
bstr_equals0(opt, "");
- bool hwdec_auto_copy = bstr_equals0(opt, "auto-copy");
- bool hwdec_auto = hwdec_auto_all || hwdec_auto_copy;
+ bool hwdec_auto_safe = bstr_equals0(opt, "auto-safe") ||
+ bstr_equals0(opt, "auto-copy-safe");
+ bool hwdec_auto_copy = bstr_equals0(opt, "auto-copy") ||
+ bstr_equals0(opt, "auto-copy-safe");
+ bool hwdec_auto = hwdec_auto_all || hwdec_auto_copy || hwdec_auto_safe;
if (!hwdec_requested) {
MP_VERBOSE(vd, "No hardware decoding requested.\n");
@@ -460,6 +483,9 @@ static void select_and_set_hwdec(struct mp_filter *vd)
bstr_equals0(opt, hwdec->name)))
continue;
+ if (hwdec_auto_safe && !(hwdec->flags & HWDEC_FLAG_WHITELIST))
+ continue;
+
MP_VERBOSE(vd, "Looking at hwdec %s...\n", hwdec->name);
if (hwdec_auto_copy && !hwdec->copying) {
@@ -530,6 +556,12 @@ static int hwdec_validate_opt(struct mp_log *log, const m_option_t *opt,
talloc_free(hwdecs);
+ mp_info(log, " auto (yes '')\n");
+ mp_info(log, " no\n");
+ mp_info(log, " auto-safe\n");
+ mp_info(log, " auto-copy\n");
+ mp_info(log, " auto-copy-safe\n");
+
return M_OPT_EXIT;
}
return 0;