[FFmpeg-devel] [PATCH v1] hwcontext_vaapi: Fix VAAPI initialization failure.
zhoupeng
zhoupeng at loongson.cn
Mon May 26 09:53:13 EEST 2025
Fix VA-API initialization failure caused by defaulting to VAAPI_DRM when hardware drivers only support VAAPI_X11.
Each VAAPI scheme checks driver support through the successful return of vaInitialize.If unsupported, it continues to the next scheme without immediate failure.
---
libavutil/hwcontext_vaapi.c | 104 +++++++++++++++++++-----------------
1 file changed, 56 insertions(+), 48 deletions(-)
diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
index 95aa38d9d2..eacb7ae00f 100644
--- a/libavutil/hwcontext_vaapi.c
+++ b/libavutil/hwcontext_vaapi.c
@@ -1666,12 +1666,23 @@ static void vaapi_device_log_info(void *context, const char *message)
#endif
static int vaapi_device_connect(AVHWDeviceContext *ctx,
- VADisplay display)
+ VADisplay display, char *driver_name)
{
AVVAAPIDeviceContext *hwctx = ctx->hwctx;
int major, minor;
VAStatus vas;
+#if VA_CHECK_VERSION(0, 38, 0)
+ if (driver_name) {
+ vas = vaSetDriverName(display, driver_name);
+ if (vas != VA_STATUS_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to "
+ "%s: %d (%s).\n", driver_name, vas, vaErrorStr(vas));
+ return AVERROR_EXTERNAL;
+ }
+ }
+#endif
+
#if CONFIG_VAAPI_1
vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
@@ -1698,6 +1709,8 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
VADisplay display = NULL;
const AVDictionaryEntry *ent;
int try_drm, try_x11, try_win32, try_all;
+ char *driver_name = NULL;
+ int ret = -1;
priv = av_mallocz(sizeof(*priv));
if (!priv)
@@ -1729,8 +1742,14 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
try_win32 = HAVE_VAAPI_WIN32;
}
+#if VA_CHECK_VERSION(0, 38, 0)
+ ent = av_dict_get(opts, "driver", NULL, 0);
+ if (ent)
+ driver_name = ent->value;
+#endif
+
#if HAVE_VAAPI_DRM
- while (!display && try_drm) {
+ while ((ret < 0) && 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.
@@ -1844,17 +1863,23 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
}
display = vaGetDisplayDRM(priv->drm_fd);
- if (!display) {
+ if (display) {
+ ret = vaapi_device_connect(ctx, display, driver_name);
+ if (ret < 0) {
+ close(priv->drm_fd);
+ priv->drm_fd = -1;
+ vaTerminate(display);
+ display = NULL;
+ }
+ } else
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 && try_x11) {
+ if ((ret < 0) && try_x11) {
// Try to open the device as an X11 display.
priv->x11_display = XOpenDisplay(device);
if (!priv->x11_display) {
@@ -1862,20 +1887,26 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
"%s.\n", XDisplayName(device));
} else {
display = vaGetDisplay(priv->x11_display);
- if (!display) {
+ if (display) {
+ av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
+ "X11 display %s.\n", XDisplayName(device));
+
+ ret = vaapi_device_connect(ctx, display, driver_name);
+ if (ret < 0) {
+ vaTerminate(display);
+ XCloseDisplay(priv->x11_display);
+ display = NULL;
+ priv->x11_display = NULL;
+ }
+ } else
av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
"from X11 display %s.\n", XDisplayName(device));
- return AVERROR_UNKNOWN;
- }
-
- av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
- "X11 display %s.\n", XDisplayName(device));
}
}
#endif
#if HAVE_VAAPI_WIN32
- if (!display && try_win32) {
+ if ((ret < 0) && try_win32) {
// Try to create a display from the specified device, if any.
if (!device) {
display = vaGetDisplayWin32(NULL);
@@ -1925,45 +1956,22 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
#endif
}
- if (!display) {
+ if (display) {
+ av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
+ "Win32 display.\n");
+
+ ret = vaapi_device_connect(ctx, display, driver_name);
+ if (ret < 0) {
+ vaTerminate(display);
+ display = NULL;
+ }
+ } else
av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
"from Win32 display.\n");
- return AVERROR_UNKNOWN;
- }
-
- av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
- "Win32 display.\n");
- }
-#endif
-
- if (!display) {
- 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);
}
-
- 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
- }
- return vaapi_device_connect(ctx, display);
+ return ret;
}
static int vaapi_device_derive(AVHWDeviceContext *ctx,
@@ -2048,7 +2056,7 @@ static int vaapi_device_derive(AVHWDeviceContext *ctx,
return AVERROR(EIO);
}
- return vaapi_device_connect(ctx, display);
+ return vaapi_device_connect(ctx, display, NULL);
}
#endif
return AVERROR(ENOSYS);
--
2.20.1
More information about the ffmpeg-devel
mailing list