#endif
MAP(UYVY, YUV422, UYVY422, 0),
MAP(YUY2, YUV422, YUYV422, 0),
+#ifdef VA_FOURCC_Y210
+ MAP(Y210, YUV422_10, Y210, 0),
+#endif
MAP(411P, YUV411, YUV411P, 0),
MAP(422V, YUV422, YUV440P, 0),
MAP(444P, YUV444, YUV444P, 0),
#endif
MAP(ARGB, RGB32, ARGB, 0),
MAP(XRGB, RGB32, 0RGB, 0),
+#ifdef VA_FOURCC_X2R10G10B10
+ MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
+#endif
};
#undef MAP
}
for (i = j = 0; i < attr_count; i++) {
+ int k;
+
if (attr_list[i].type != VASurfaceAttribPixelFormat)
continue;
fourcc = attr_list[i].value.value.i;
pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
- if (pix_fmt != AV_PIX_FMT_NONE)
+
+ if (pix_fmt == AV_PIX_FMT_NONE)
+ continue;
+
+ for (k = 0; k < j; k++) {
+ if (constraints->valid_sw_formats[k] == pix_fmt)
+ break;
+ }
+
+ if (k == j)
constraints->valid_sw_formats[j++] = pix_fmt;
}
- av_assert0(j == pix_fmt_count);
constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
}
} else {
err = AVERROR(ENOMEM);
goto fail;
}
- for (i = 0; i < ctx->nb_formats; i++)
- constraints->valid_sw_formats[i] = ctx->formats[i].pix_fmt;
- constraints->valid_sw_formats[i] = AV_PIX_FMT_NONE;
+ for (i = j = 0; i < ctx->nb_formats; i++) {
+ int k;
+
+ for (k = 0; k < j; k++) {
+ if (constraints->valid_sw_formats[k] == ctx->formats[i].pix_fmt)
+ break;
+ }
+
+ if (k == j)
+ constraints->valid_sw_formats[j++] = ctx->formats[i].pix_fmt;
+ }
+
+ constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
}
constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt));
}
}
-static AVBufferRef *vaapi_pool_alloc(void *opaque, int size)
+static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size)
{
AVHWFramesContext *hwfc = opaque;
VAAPIFramesContext *ctx = hwfc->internal->priv;
try_x11 = HAVE_VAAPI_X11;
}
-#if HAVE_VAAPI_X11
- if (!display && try_x11) {
- // Try to open the device as an X11 display.
- priv->x11_display = XOpenDisplay(device);
- if (!priv->x11_display) {
- av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
- "%s.\n", XDisplayName(device));
- } else {
- display = vaGetDisplay(priv->x11_display);
- if (!display) {
- 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_DRM
while (!display && try_drm) {
// If the device is specified, try to open it as a DRM device node.
break;
}
} else {
- const AVDictionaryEntry *kernel_driver;
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);
}
#endif
+#if HAVE_VAAPI_X11
+ if (!display && try_x11) {
+ // Try to open the device as an X11 display.
+ priv->x11_display = XOpenDisplay(device);
+ if (!priv->x11_display) {
+ av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
+ "%s.\n", XDisplayName(device));
+ } else {
+ display = vaGetDisplay(priv->x11_display);
+ if (!display) {
+ 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 (!display) {
if (device)
av_log(ctx, AV_LOG_ERROR, "No VA display found for "
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);
}
static int vaapi_device_derive(AVHWDeviceContext *ctx,
- AVHWDeviceContext *src_ctx, int flags)
+ AVHWDeviceContext *src_ctx,
+ AVDictionary *opts, int flags)
{
#if HAVE_VAAPI_DRM
if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
VADisplay *display;
VAAPIDevicePriv *priv;
+ int fd;
if (src_hwctx->fd < 0) {
av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated "
return AVERROR(EINVAL);
}
+#if CONFIG_LIBDRM
+ {
+ int node_type = drmGetNodeTypeFromFd(src_hwctx->fd);
+ char *render_node;
+ if (node_type < 0) {
+ av_log(ctx, AV_LOG_ERROR, "DRM instance fd does not appear "
+ "to refer to a DRM device.\n");
+ return AVERROR(EINVAL);
+ }
+ if (node_type == DRM_NODE_RENDER) {
+ fd = src_hwctx->fd;
+ } else {
+ render_node = drmGetRenderDeviceNameFromFd(src_hwctx->fd);
+ if (!render_node) {
+ av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
+ "because the device does not have an "
+ "associated render node.\n");
+ fd = src_hwctx->fd;
+ } else {
+ fd = open(render_node, O_RDWR);
+ if (fd < 0) {
+ av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
+ "because the associated render node "
+ "could not be opened.\n");
+ fd = src_hwctx->fd;
+ } else {
+ av_log(ctx, AV_LOG_VERBOSE, "Using render node %s "
+ "in place of non-render DRM device.\n",
+ render_node);
+ }
+ free(render_node);
+ }
+ }
+ }
+#else
+ fd = src_hwctx->fd;
+#endif
+
priv = av_mallocz(sizeof(*priv));
- if (!priv)
+ if (!priv) {
+ if (fd != src_hwctx->fd) {
+ // The fd was opened in this function.
+ close(fd);
+ }
return AVERROR(ENOMEM);
+ }
- // Inherits the fd from the source context, which will close it.
- priv->drm_fd = -1;
+ if (fd == src_hwctx->fd) {
+ // The fd is inherited from the source context and we are holding
+ // a reference to that, we don't want to close it from here.
+ priv->drm_fd = -1;
+ } else {
+ priv->drm_fd = fd;
+ }
ctx->user_opaque = priv;
ctx->free = &vaapi_device_free;
- display = vaGetDisplayDRM(src_hwctx->fd);
+ display = vaGetDisplayDRM(fd);
if (!display) {
av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
"DRM device.\n");