X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavutil%2Fhwcontext_vaapi.c;h=cf117640f283d5c857672051327afb5e180304f8;hb=e1b5620b62ef0e3d04a6c4f3d837328076ed2a9b;hp=8624369bb9f14b61fe49b1b9fd4ea5d2e3bbb053;hpb=c2631dfd0a0a12050cc1765fd41702c5e93abee5;p=ffmpeg diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 8624369bb9f..cf117640f28 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -27,6 +27,7 @@ #if CONFIG_LIBDRM # include +# include # include # ifndef DRM_FORMAT_MOD_INVALID # define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) @@ -1469,6 +1470,8 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, { VAAPIDevicePriv *priv; VADisplay display = NULL; + const AVDictionaryEntry *ent; + int try_drm, try_x11, try_all; priv = av_mallocz(sizeof(*priv)); if (!priv) @@ -1479,8 +1482,95 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, ctx->user_opaque = priv; ctx->free = vaapi_device_free; + ent = av_dict_get(opts, "connection_type", NULL, 0); + if (ent) { + try_all = try_drm = try_x11 = 0; + if (!strcmp(ent->value, "drm")) { + try_drm = 1; + } else if (!strcmp(ent->value, "x11")) { + try_x11 = 1; + } else { + av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n", + ent->value); + return AVERROR(EINVAL); + } + } else { + try_all = 1; + try_drm = HAVE_VAAPI_DRM; + try_x11 = HAVE_VAAPI_X11; + } + +#if HAVE_VAAPI_DRM + while (!display && try_drm) { + // If the device is specified, try to open it as a DRM device node. + // If not, look for a usable render node, possibly restricted to those + // using a specified kernel driver. + int loglevel = try_all ? AV_LOG_VERBOSE : AV_LOG_ERROR; + if (device) { + priv->drm_fd = open(device, O_RDWR); + if (priv->drm_fd < 0) { + av_log(ctx, loglevel, "Failed to open %s as " + "DRM device node.\n", device); + break; + } + } else { + char path[64]; + int n, max_devices = 8; +#if CONFIG_LIBDRM + const AVDictionaryEntry *kernel_driver; + kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0); +#endif + for (n = 0; n < max_devices; n++) { + snprintf(path, sizeof(path), + "/dev/dri/renderD%d", 128 + n); + priv->drm_fd = open(path, O_RDWR); + if (priv->drm_fd < 0) { + av_log(ctx, AV_LOG_VERBOSE, "Cannot open " + "DRM render node for device %d.\n", n); + break; + } +#if CONFIG_LIBDRM + if (kernel_driver) { + drmVersion *info; + info = drmGetVersion(priv->drm_fd); + if (strcmp(kernel_driver->value, info->name)) { + av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d " + "with non-matching kernel driver (%s).\n", + n, info->name); + drmFreeVersion(info); + close(priv->drm_fd); + priv->drm_fd = -1; + continue; + } + av_log(ctx, AV_LOG_VERBOSE, "Trying to use " + "DRM render node for device %d, " + "with matching kernel driver (%s).\n", + n, info->name); + drmFreeVersion(info); + } else +#endif + { + av_log(ctx, AV_LOG_VERBOSE, "Trying to use " + "DRM render node for device %d.\n", n); + } + break; + } + if (n >= max_devices) + break; + } + + display = vaGetDisplayDRM(priv->drm_fd); + if (!display) { + av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display " + "from DRM device %s.\n", device); + return AVERROR_EXTERNAL; + } + break; + } +#endif + #if HAVE_VAAPI_X11 - if (!display && !(device && device[0] == '/')) { + if (!display && try_x11) { // Try to open the device as an X11 display. priv->x11_display = XOpenDisplay(device); if (!priv->x11_display) { @@ -1500,34 +1590,31 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, } #endif -#if HAVE_VAAPI_DRM if (!display) { - // Try to open the device as a DRM path. - // Default to using the first render node if the user did not - // supply a path. - const char *path = device ? device : "/dev/dri/renderD128"; - priv->drm_fd = open(path, O_RDWR); - if (priv->drm_fd < 0) { - av_log(ctx, AV_LOG_VERBOSE, "Cannot open DRM device %s.\n", - path); - } else { - display = vaGetDisplayDRM(priv->drm_fd); - if (!display) { - av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " - "from DRM device %s.\n", path); - return AVERROR_UNKNOWN; - } + if (device) + av_log(ctx, AV_LOG_ERROR, "No VA display found for " + "device %s.\n", device); + else + av_log(ctx, AV_LOG_ERROR, "No VA display found for " + "any default device.\n"); + return AVERROR(EINVAL); + } - av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " - "DRM device %s.\n", path); + ent = av_dict_get(opts, "driver", NULL, 0); + if (ent) { +#if VA_CHECK_VERSION(0, 38, 0) + VAStatus vas; + vas = vaSetDriverName(display, ent->value); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to " + "%s: %d (%s).\n", ent->value, vas, vaErrorStr(vas)); + vaTerminate(display); + return AVERROR_EXTERNAL; } - } +#else + av_log(ctx, AV_LOG_WARNING, "Driver name setting is not " + "supported with this VAAPI version.\n"); #endif - - if (!display) { - av_log(ctx, AV_LOG_ERROR, "No VA display found for " - "device: %s.\n", device ? device : ""); - return AVERROR(EINVAL); } return vaapi_device_connect(ctx, display);