int flags;
} VAAPIMapping;
-#define MAP(va, rt, av) { \
+typedef struct VAAPIFormat {
+ unsigned int fourcc;
+ unsigned int rt_format;
+ enum AVPixelFormat pix_fmt;
+ int chroma_planes_swapped;
+} VAAPIFormatDescriptor;
+
+#define MAP(va, rt, av, swap_uv) { \
VA_FOURCC_ ## va, \
VA_RT_FORMAT_ ## rt, \
- AV_PIX_FMT_ ## av \
+ AV_PIX_FMT_ ## av, \
+ swap_uv, \
}
// The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V
// plane swap cases. The frame handling below tries to hide these.
-static const struct {
- unsigned int fourcc;
- unsigned int rt_format;
- enum AVPixelFormat pix_fmt;
-} vaapi_format_map[] = {
- MAP(NV12, YUV420, NV12),
- MAP(YV12, YUV420, YUV420P), // With U/V planes swapped.
- MAP(IYUV, YUV420, YUV420P),
+static const VAAPIFormatDescriptor vaapi_format_map[] = {
+ MAP(NV12, YUV420, NV12, 0),
#ifdef VA_FOURCC_I420
- MAP(I420, YUV420, YUV420P),
+ MAP(I420, YUV420, YUV420P, 0),
#endif
+ MAP(YV12, YUV420, YUV420P, 1),
+ MAP(IYUV, YUV420, YUV420P, 0),
+ MAP(422H, YUV422, YUV422P, 0),
#ifdef VA_FOURCC_YV16
- MAP(YV16, YUV422, YUV422P), // With U/V planes swapped.
+ MAP(YV16, YUV422, YUV422P, 1),
#endif
- MAP(422H, YUV422, YUV422P),
- MAP(UYVY, YUV422, UYVY422),
- MAP(YUY2, YUV422, YUYV422),
- MAP(411P, YUV411, YUV411P),
- MAP(422V, YUV422, YUV440P),
- MAP(444P, YUV444, YUV444P),
- MAP(Y800, YUV400, GRAY8),
+ MAP(UYVY, YUV422, UYVY422, 0),
+ MAP(YUY2, YUV422, YUYV422, 0),
+ MAP(411P, YUV411, YUV411P, 0),
+ MAP(422V, YUV422, YUV440P, 0),
+ MAP(444P, YUV444, YUV444P, 0),
+ MAP(Y800, YUV400, GRAY8, 0),
#ifdef VA_FOURCC_P010
- MAP(P010, YUV420_10BPP, P010),
+ MAP(P010, YUV420_10BPP, P010, 0),
#endif
- MAP(BGRA, RGB32, BGRA),
- MAP(BGRX, RGB32, BGR0),
- MAP(RGBA, RGB32, RGBA),
- MAP(RGBX, RGB32, RGB0),
+ MAP(BGRA, RGB32, BGRA, 0),
+ MAP(BGRX, RGB32, BGR0, 0),
+ MAP(RGBA, RGB32, RGBA, 0),
+ MAP(RGBX, RGB32, RGB0, 0),
#ifdef VA_FOURCC_ABGR
- MAP(ABGR, RGB32, ABGR),
- MAP(XBGR, RGB32, 0BGR),
+ MAP(ABGR, RGB32, ABGR, 0),
+ MAP(XBGR, RGB32, 0BGR, 0),
#endif
- MAP(ARGB, RGB32, ARGB),
- MAP(XRGB, RGB32, 0RGB),
+ MAP(ARGB, RGB32, ARGB, 0),
+ MAP(XRGB, RGB32, 0RGB, 0),
};
#undef MAP
-static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
+static const VAAPIFormatDescriptor *
+ vaapi_format_from_fourcc(unsigned int fourcc)
{
int i;
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
if (vaapi_format_map[i].fourcc == fourcc)
- return vaapi_format_map[i].pix_fmt;
- return AV_PIX_FMT_NONE;
+ return &vaapi_format_map[i];
+ return NULL;
+}
+
+static const VAAPIFormatDescriptor *
+ vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt)
+{
+ int i;
+ for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
+ if (vaapi_format_map[i].pix_fmt == pix_fmt)
+ return &vaapi_format_map[i];
+ return NULL;
+}
+
+static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
+{
+ const VAAPIFormatDescriptor *desc;
+ desc = vaapi_format_from_fourcc(fourcc);
+ if (desc)
+ return desc->pix_fmt;
+ else
+ return AV_PIX_FMT_NONE;
}
static int vaapi_get_image_format(AVHWDeviceContext *hwdev,
const char *match_string;
unsigned int quirks;
} vaapi_driver_quirks_table[] = {
+#if !VA_CHECK_VERSION(1, 0, 0)
+ // The i965 driver did not conform before version 2.0.
{
"Intel i965 (Quick Sync)",
"i965",
AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS,
},
+#endif
{
"Intel iHD",
"ubit",
}
}
+ vendor_string = vaQueryVendorString(hwctx->display);
+ if (vendor_string)
+ av_log(hwdev, AV_LOG_VERBOSE, "VAAPI driver: %s.\n", vendor_string);
+
if (hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_USER_SET) {
- av_log(hwdev, AV_LOG_VERBOSE, "Not detecting driver: "
- "quirks set by user.\n");
+ av_log(hwdev, AV_LOG_VERBOSE, "Using quirks set by user (%#x).\n",
+ hwctx->driver_quirks);
} else {
// Detect the driver in use and set quirk flags if necessary.
- vendor_string = vaQueryVendorString(hwctx->display);
hwctx->driver_quirks = 0;
if (vendor_string) {
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) {
if (strstr(vendor_string,
vaapi_driver_quirks_table[i].match_string)) {
- av_log(hwdev, AV_LOG_VERBOSE, "Matched \"%s\" as known "
- "driver \"%s\".\n", vendor_string,
- vaapi_driver_quirks_table[i].friendly_name);
+ av_log(hwdev, AV_LOG_VERBOSE, "Matched driver string "
+ "as known nonstandard driver \"%s\", setting "
+ "quirks (%#x).\n",
+ vaapi_driver_quirks_table[i].friendly_name,
+ vaapi_driver_quirks_table[i].quirks);
hwctx->driver_quirks |=
vaapi_driver_quirks_table[i].quirks;
break;
}
}
if (!(i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table))) {
- av_log(hwdev, AV_LOG_VERBOSE, "Unknown driver \"%s\", "
- "assuming standard behaviour.\n", vendor_string);
+ av_log(hwdev, AV_LOG_VERBOSE, "Driver not found in known "
+ "nonstandard list, using standard behaviour.\n");
}
+ } else {
+ av_log(hwdev, AV_LOG_VERBOSE, "Driver has no vendor string, "
+ "assuming standard behaviour.\n");
}
}
AVVAAPIFramesContext *avfc = hwfc->hwctx;
VAAPIFramesContext *ctx = hwfc->internal->priv;
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
+ const VAAPIFormatDescriptor *desc;
VAImageFormat *expected_format;
AVBufferRef *test_surface = NULL;
VASurfaceID test_surface_id;
VAImage test_image;
VAStatus vas;
int err, i;
- unsigned int fourcc, rt_format;
- for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
- if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) {
- fourcc = vaapi_format_map[i].fourcc;
- rt_format = vaapi_format_map[i].rt_format;
- break;
- }
- }
- if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) {
+ desc = vaapi_format_from_pix_fmt(hwfc->sw_format);
+ if (!desc) {
av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
av_get_pix_fmt_name(hwfc->sw_format));
return AVERROR(EINVAL);
.type = VASurfaceAttribPixelFormat,
.flags = VA_SURFACE_ATTRIB_SETTABLE,
.value.type = VAGenericValueTypeInteger,
- .value.value.i = fourcc,
+ .value.value.i = desc->fourcc,
};
}
av_assert0(i == ctx->nb_attributes);
ctx->nb_attributes = 0;
}
- ctx->rt_format = rt_format;
+ ctx->rt_format = desc->rt_format;
if (hwfc->initial_pool_size > 0) {
// This pool will be usable as a render target, so we need to store
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
VAAPIFramesContext *ctx = hwfc->internal->priv;
VASurfaceID surface_id;
+ const VAAPIFormatDescriptor *desc;
VAImageFormat *image_format;
VAAPIMapping *map;
VAStatus vas;
dst->data[i] = (uint8_t*)address + map->image.offsets[i];
dst->linesize[i] = map->image.pitches[i];
}
- if (
-#ifdef VA_FOURCC_YV16
- map->image.format.fourcc == VA_FOURCC_YV16 ||
-#endif
- map->image.format.fourcc == VA_FOURCC_YV12) {
+
+ desc = vaapi_format_from_fourcc(map->image.format.fourcc);
+ if (desc && desc->chroma_planes_swapped) {
// Chroma planes are YVU rather than YUV, so swap them.
FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
}
(AVHWFramesContext*)dst->hw_frames_ctx->data;
AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
const AVDRMFrameDescriptor *desc;
+ const VAAPIFormatDescriptor *format_desc;
VASurfaceID surface_id;
VAStatus vas;
- uint32_t va_fourcc, va_rt_format;
+ uint32_t va_fourcc;
int err, i, j, k;
unsigned long buffer_handle;
av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as "
"%08x.\n", desc->objects[0].fd, va_fourcc);
- for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
- if (vaapi_format_map[i].fourcc == va_fourcc)
- va_rt_format = vaapi_format_map[i].rt_format;
- }
+ format_desc = vaapi_format_from_fourcc(va_fourcc);
+ av_assert0(format_desc);
buffer_handle = desc->objects[0].fd;
buffer_desc.pixel_format = va_fourcc;
}
buffer_desc.num_planes = k;
- vas = vaCreateSurfaces(dst_dev->display, va_rt_format,
+ if (format_desc->chroma_planes_swapped &&
+ buffer_desc.num_planes == 3) {
+ FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
+ FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
+ }
+
+ vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
src->width, src->height,
&surface_id, 1,
attrs, FF_ARRAY_ELEMS(attrs));
}
#endif
+#if VA_CHECK_VERSION(0, 36, 0)
typedef struct VAAPIDRMImageBufferMapping {
VAImage image;
VABufferInfo buffer_info;
av_freep(&mapping);
return err;
}
+#endif
static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
const AVFrame *src, int flags)
if (err != AVERROR(ENOSYS))
return err;
#endif
+#if VA_CHECK_VERSION(0, 36, 0)
return vaapi_map_to_drm_abh(hwfc, dst, src, flags);
+#endif
+ return AVERROR(ENOSYS);
}
#endif /* CONFIG_LIBDRM */