Skip to content

Commit

Permalink
vaapi: add option to select a non-default device path
Browse files Browse the repository at this point in the history
On machines with multiple GPUs, /dev/dri/renderD128 isn't guaranteed
to point to a valid vaapi device. This just adds the option to specify
what path to use.

The old fallback /dev/dri/card0 is gone but that's not a loss as its
a legacy interface no longer accepted as valid by libva.

Fixes #4320
  • Loading branch information
Rostislav Pehlivanov authored and kevmitch committed Mar 30, 2018
1 parent af9c6c1 commit e3e2c79
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 27 deletions.
5 changes: 5 additions & 0 deletions options/options.c
Expand Up @@ -89,6 +89,7 @@ extern const struct m_sub_options angle_conf;
extern const struct m_sub_options cocoa_conf;
extern const struct m_sub_options macos_conf;
extern const struct m_sub_options android_conf;
extern const struct m_sub_options vaapi_conf;

static const struct m_sub_options screenshot_conf = {
.opts = image_writer_opts,
Expand Down Expand Up @@ -756,6 +757,10 @@ const m_option_t mp_opts[] = {
0, INT_MAX, ({"auto", -1})),
#endif

#if HAVE_VAAPI
OPT_SUBSTRUCT("vaapi", vaapi_opts, vaapi_conf, 0),
#endif

#if HAVE_ENCODING
OPT_SUBSTRUCT("", encode_opts, encode_config, 0),
#endif
Expand Down
1 change: 1 addition & 0 deletions options/options.h
Expand Up @@ -347,6 +347,7 @@ typedef struct MPOpts {
struct macos_opts *macos_opts;
struct android_opts *android_opts;
struct dvd_opts *dvd_opts;
struct vaapi_opts *vaapi_opts;

int cuda_device;
} MPOpts;
Expand Down
73 changes: 46 additions & 27 deletions video/vaapi.c
Expand Up @@ -26,10 +26,27 @@
#include "mp_image.h"
#include "img_format.h"
#include "mp_image_pool.h"
#include "options/m_config.h"

#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_vaapi.h>

struct vaapi_opts {
char *path;
};

#define OPT_BASE_STRUCT struct vaapi_opts
const struct m_sub_options vaapi_conf = {
.opts = (const struct m_option[]) {
OPT_STRING("device", path, 0),
{0},
},
.defaults = &(const struct vaapi_opts) {
.path = "/dev/dri/renderD128",
},
.size = sizeof(struct vaapi_opts),
};

int va_get_colorspace_flag(enum mp_csp csp)
{
switch (csp) {
Expand Down Expand Up @@ -216,7 +233,8 @@ bool va_guess_if_emulated(struct mp_vaapi_ctx *ctx)
}

struct va_native_display {
void (*create)(VADisplay **out_display, void **out_native_ctx);
void (*create)(VADisplay **out_display, void **out_native_ctx,
const char *path);
void (*destroy)(void *native_ctx);
};

Expand All @@ -229,7 +247,8 @@ static void x11_destroy(void *native_ctx)
XCloseDisplay(native_ctx);
}

static void x11_create(VADisplay **out_display, void **out_native_ctx)
static void x11_create(VADisplay **out_display, void **out_native_ctx,
const char *path)
{
void *native_display = XOpenDisplay(NULL);
if (!native_display)
Expand Down Expand Up @@ -264,30 +283,23 @@ static void drm_destroy(void *native_ctx)
talloc_free(ctx);
}

static void drm_create(VADisplay **out_display, void **out_native_ctx)
static void drm_create(VADisplay **out_display, void **out_native_ctx,
const char *path)
{
static const char *drm_device_paths[] = {
"/dev/dri/renderD128",
"/dev/dri/card0",
NULL
};

for (int i = 0; drm_device_paths[i]; i++) {
int drm_fd = open(drm_device_paths[i], O_RDWR);
if (drm_fd < 0)
continue;

struct va_native_display_drm *ctx = talloc_ptrtype(NULL, ctx);
ctx->drm_fd = drm_fd;
*out_display = vaGetDisplayDRM(drm_fd);
if (out_display) {
*out_native_ctx = ctx;
return;
}
int drm_fd = open(path, O_RDWR);
if (drm_fd < 0)
return;

close(drm_fd);
talloc_free(ctx);
struct va_native_display_drm *ctx = talloc_ptrtype(NULL, ctx);
ctx->drm_fd = drm_fd;
*out_display = vaGetDisplayDRM(drm_fd);
if (out_display) {
*out_native_ctx = ctx;
return;
}

close(drm_fd);
talloc_free(ctx);
}

static const struct va_native_display disp_drm = {
Expand All @@ -309,24 +321,31 @@ static const struct va_native_display *const native_displays[] = {
static struct AVBufferRef *va_create_standalone(struct mpv_global *global,
struct mp_log *log, struct hwcontext_create_dev_params *params)
{
struct AVBufferRef *ret = NULL;
struct vaapi_opts *opts = mp_get_config_group(NULL, global, &vaapi_conf);

for (int n = 0; native_displays[n]; n++) {
VADisplay *display = NULL;
void *native_ctx = NULL;
native_displays[n]->create(&display, &native_ctx);
native_displays[n]->create(&display, &native_ctx, opts->path);
if (display) {
struct mp_vaapi_ctx *ctx =
va_initialize(display, log, params->probing);
if (!ctx) {
vaTerminate(display);
native_displays[n]->destroy(native_ctx);
return NULL;
goto end;
}
ctx->native_ctx = native_ctx;
ctx->destroy_native_ctx = native_displays[n]->destroy;
return ctx->hwctx.av_device_ref;
ret = ctx->hwctx.av_device_ref;
goto end;
}
}
return NULL;

end:
talloc_free(opts);
return ret;
}

const struct hwcontext_fns hwcontext_fns_vaapi = {
Expand Down

1 comment on commit e3e2c79

@kkkrackpot
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no configuration option exposed to users or it's simply undocumented?

Please sign in to comment.