vo_opengl, vo_opengl_cb: better hwdec interop backend selection

Introduce the --opengl-hwdec-interop option, which replaces
--hwdec-preload. The new option allows explicit selection of the interop
backend.

This is relatively complex, and I would have preferred not to add this,
but it's probably useful to debug certain problems. In exchange, the
"new" option documents that pretty much any but the simplest use of it
will not be forward compatible.
This commit is contained in:
wm4 2017-01-17 14:51:08 +01:00
parent e94890a5d6
commit 9d68d8fb0f
9 changed files with 109 additions and 23 deletions

View File

@ -19,6 +19,12 @@ Interface changes
::
--- 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.
--- mpv 0.23.0 ---
- remove deprecated vf_vdpaurb (use "--hwdec=vdpau-copy" instead)
- the following properties now have new semantics:

View File

@ -1331,8 +1331,8 @@ Property list
This is known only once the VO has opened (and possibly later). With some
VOs (like ``opengl``), this might be never known in advance, but only when
the decoder attempted to create the hw decoder successfully. (Using
``--hwdec-preload`` can load it eagerly.) If there are multiple drivers
loaded, they will be separated by ``,``.
``--opengl-hwdec-interop`` can load it eagerly.) If there are multiple
drivers loaded, they will be separated by ``,``.
If no VO is active or no interop driver is known, this property is
unavailable.
@ -1341,6 +1341,9 @@ Property list
multiple interop drivers for the same hardware decoder, depending on
platform and VO.
This is somewhat similar to the ``--opengl-hwdec-interop`` option, but
it returns the actually loaded backend, not the value of this option.
``video-format``
Video format as string.

View File

@ -746,12 +746,12 @@ Video
In particular, ``auto-copy`` will only select safe modes
(although potentially slower than other methods).
``--hwdec-preload=<api>``
``--opengl-hwdec-interop=<name>``
This is useful for the ``opengl`` and ``opengl-cb`` VOs for creating the
hardware decoding OpenGL interop context, but without actually enabling
hardware decoding itself (like ``--hwdec`` does).
If set to ``no`` (default), the ``--hwdec`` option is used.
If set to an empty string (default), the ``--hwdec`` option is used.
For ``opengl``, if set, do not create the interop context on demand, but
when the VO is created.
@ -762,6 +762,19 @@ Video
to temporarily set the ``hwdec`` option just during OpenGL context
initialization with ``mpv_opengl_cb_init_gl()``.
See ``--opengl-hwdec-interop=help`` for accepted values. This lists the
interop backend, with the ``--hwdec`` alias after it in ``[...]``. Consider
all values except the proper interop backend name, ``auto``, and ``no`` as
silently deprecated and subject to change. Also, if you use this in
application code (e.g. via libmpv), any value other than ``auto`` and ``no``
should be avoided, as backends can change.
Currently the option sets a single value. It is possible that the option
type changes to a list in the future.
The old alias ``--hwdec-preload`` has different behavior if the option value
is ``no``.
``--videotoolbox-format=<name>``
Set the internal pixel format used by ``--hwdec=videotoolbox`` on OSX. The
choice of the format can influence performance considerably. On the other

View File

@ -40,6 +40,7 @@
#include "stream/stream.h"
#include "video/csputils.h"
#include "video/hwdec.h"
#include "video/out/opengl/hwdec.h"
#include "video/image_writer.h"
#include "sub/osd.h"
#include "audio/filter/af.h"
@ -150,7 +151,6 @@ const struct m_sub_options stream_cache_conf = {
static const m_option_t mp_vo_opt_list[] = {
OPT_SETTINGSLIST("vo", video_driver_list, 0, &vo_obj_list, ),
OPT_CHOICE_C("hwdec-preload", hwdec_preload_api, 0, mp_hwdec_names),
OPT_SUBSTRUCT("sws", sws_opts, sws_conf, 0),
OPT_FLAG("taskbar-progress", taskbar_progress, 0),
OPT_FLAG("ontop", ontop, 0),
@ -199,7 +199,11 @@ static const m_option_t mp_vo_opt_list[] = {
0, drm_validate_connector_opt),
OPT_INT("drm-mode", drm_mode_id, 0),
#endif
#if HAVE_GL
OPT_STRING_VALIDATE("opengl-hwdec-interop", gl_hwdec_interop, 0,
gl_hwdec_validate_opt),
OPT_REPLACED("hwdec-preload", "opengl-hwdec-interop"),
#endif
{0}
};

View File

@ -50,7 +50,7 @@ typedef struct mp_vo_opts {
// vo_wayland, vo_drm
struct sws_opts *sws_opts;
// vo_opengl, vo_opengl_cb
int hwdec_preload_api;
char *gl_hwdec_interop;
// vo_drm
char *drm_connector_spec;
int drm_mode_id;

View File

@ -22,6 +22,7 @@
#include "common/common.h"
#include "common/msg.h"
#include "options/m_config.h"
#include "hwdec.h"
extern const struct gl_hwdec_driver gl_hwdec_vaegl;
@ -110,6 +111,68 @@ struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl,
return NULL;
}
// Load by option name.
struct gl_hwdec *gl_hwdec_load(struct mp_log *log, GL *gl,
struct mpv_global *g,
struct mp_hwdec_devices *devs,
const char *name)
{
int g_hwdec_api;
mp_read_option_raw(g, "hwdec", &m_option_type_choice, &g_hwdec_api);
if (!name || !name[0])
name = m_opt_choice_str(mp_hwdec_names, g_hwdec_api);
int api_id = HWDEC_NONE;
for (int n = 0; mp_hwdec_names[n].name; n++) {
if (name && strcmp(mp_hwdec_names[n].name, name) == 0)
api_id = mp_hwdec_names[n].value;
}
for (int n = 0; mpgl_hwdec_drivers[n]; n++) {
const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n];
if (name && strcmp(drv->name, name) == 0) {
struct gl_hwdec *r = load_hwdec_driver(log, gl, g, devs, drv, false);
if (r)
return r;
}
}
return gl_hwdec_load_api(log, gl, g, devs, api_id);
}
int gl_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param)
{
bool help = bstr_equals0(param, "help");
if (help)
mp_info(log, "Available hwdecs:\n");
for (int n = 0; mpgl_hwdec_drivers[n]; n++) {
const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n];
const char *api_name = m_opt_choice_str(mp_hwdec_names, drv->api);
if (help) {
mp_info(log, " %s [%s]\n", drv->name, api_name);
} else if (bstr_equals0(param, drv->name) ||
bstr_equals0(param, api_name))
{
return 1;
}
}
if (help) {
mp_info(log, " auto (loads best)\n"
" (other --hwdec values)\n"
"Setting an empty string means use --hwdec.\n");
return M_OPT_EXIT;
}
if (!param.len)
return 1; // "" is treated specially
for (int n = 0; mp_hwdec_names[n].name; n++) {
if (bstr_equals0(param, mp_hwdec_names[n].name))
return 1;
}
mp_fatal(log, "No hwdec backend named '%.*s' found!\n", BSTR_P(param));
return M_OPT_INVALID;
}
void gl_hwdec_uninit(struct gl_hwdec *hwdec)
{
if (hwdec)

View File

@ -81,6 +81,14 @@ struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl,
struct mp_hwdec_devices *devs,
enum hwdec_type api);
struct gl_hwdec *gl_hwdec_load(struct mp_log *log, GL *gl,
struct mpv_global *g,
struct mp_hwdec_devices *devs,
const char *name);
int gl_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param);
void gl_hwdec_uninit(struct gl_hwdec *hwdec);
bool gl_hwdec_test_format(struct gl_hwdec *hwdec, int imgfmt);

View File

@ -411,14 +411,9 @@ static int preinit(struct vo *vo)
hwdec_devices_set_loader(vo->hwdec_devs, call_request_hwdec_api, vo);
int hwdec = vo->opts->hwdec_preload_api;
if (hwdec == HWDEC_NONE)
hwdec = vo->global->opts->hwdec_api;
if (hwdec != HWDEC_NONE) {
p->hwdec = gl_hwdec_load_api(p->vo->log, p->gl, vo->global,
vo->hwdec_devs, hwdec);
gl_video_set_hwdec(p->renderer, p->hwdec);
}
p->hwdec = gl_hwdec_load(p->vo->log, p->gl, vo->global,
vo->hwdec_devs, vo->opts->gl_hwdec_interop);
gl_video_set_hwdec(p->renderer, p->hwdec);
return 0;

View File

@ -167,15 +167,9 @@ int mpv_opengl_cb_init_gl(struct mpv_opengl_cb_context *ctx, const char *exts,
m_config_cache_update(ctx->vo_opts_cache);
int g_hwdec_api;
mp_read_option_raw(ctx->global, "hwdec", &m_option_type_choice, &g_hwdec_api);
ctx->hwdec_devs = hwdec_devices_create();
int hwdec_api = ctx->vo_opts->hwdec_preload_api;
if (hwdec_api == HWDEC_NONE)
hwdec_api = g_hwdec_api;
ctx->hwdec = gl_hwdec_load_api(ctx->log, ctx->gl, ctx->global,
ctx->hwdec_devs, hwdec_api);
ctx->hwdec = gl_hwdec_load(ctx->log, ctx->gl, ctx->global,
ctx->hwdec_devs, ctx->vo_opts->gl_hwdec_interop);
gl_video_set_hwdec(ctx->renderer, ctx->hwdec);
pthread_mutex_lock(&ctx->lock);