27# include <va/va_win32.h>
31# include <va/va_x11.h>
34# include <va/va_drm.h>
38# include <va/va_drmcommon.h>
40# include <drm_fourcc.h>
41# ifndef DRM_FORMAT_MOD_INVALID
42# define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
114typedef struct VAAPIFormat {
121#define MAP(va, rt, av, swap_uv) { \
123 VA_RT_FORMAT_ ## rt, \
130 MAP(NV12, YUV420, NV12, 0),
132 MAP(I420, YUV420, YUV420P, 0),
134 MAP(YV12, YUV420, YUV420P, 1),
135 MAP(IYUV, YUV420, YUV420P, 0),
136 MAP(422
H, YUV422, YUV422P, 0),
138 MAP(YV16, YUV422, YUV422P, 1),
140 MAP(UYVY, YUV422, UYVY422, 0),
141 MAP(YUY2, YUV422, YUYV422, 0),
143 MAP(Y210, YUV422_10, Y210, 0),
146 MAP(Y212, YUV422_12, Y212, 0),
148 MAP(411
P, YUV411, YUV411P, 0),
149 MAP(422
V, YUV422, YUV440P, 0),
150 MAP(444
P, YUV444, YUV444P, 0),
152 MAP(XYUV, YUV444, VUYX, 0),
154 MAP(Y800, YUV400, GRAY8, 0),
156 MAP(P010, YUV420_10BPP, P010, 0),
159 MAP(P012, YUV420_12, P012, 0),
161 MAP(BGRA, RGB32, BGRA, 0),
162 MAP(BGRX, RGB32, BGR0, 0),
164 MAP(RGBX, RGB32, RGB0, 0),
166 MAP(ABGR, RGB32, ABGR, 0),
167 MAP(XBGR, RGB32, 0BGR, 0),
169 MAP(ARGB, RGB32, ARGB, 0),
170 MAP(XRGB, RGB32, 0
RGB, 0),
171#ifdef VA_FOURCC_X2R10G10B10
172 MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
177 MAP(Y410, YUV444_10, XV30, 0),
182 MAP(Y412, YUV444_12, XV36, 0),
206 for (; prev < end; prev++)
217 return desc->pix_fmt;
225 VAImageFormat **image_format)
232 for (
i = 0;
i <
ctx->nb_formats;
i++) {
233 if (
ctx->formats[
i].fourcc ==
desc->fourcc) {
237 *image_format = &
ctx->formats[
i].image_format;
248 VAImageFormat **image_format)
256 const void *hwconfig,
262 VASurfaceAttrib *attr_list =
NULL;
266 int err,
i, j, attr_count, pix_fmt_count;
271 vas = vaQuerySurfaceAttributes(hwctx->
display, config->config_id,
273 if (vas != VA_STATUS_SUCCESS) {
275 "%d (%s).\n", vas, vaErrorStr(vas));
280 attr_list =
av_malloc(attr_count *
sizeof(*attr_list));
286 vas = vaQuerySurfaceAttributes(hwctx->
display, config->config_id,
287 attr_list, &attr_count);
288 if (vas != VA_STATUS_SUCCESS) {
290 "%d (%s).\n", vas, vaErrorStr(vas));
296 for (
i = 0;
i < attr_count;
i++) {
297 switch (attr_list[
i].
type) {
298 case VASurfaceAttribPixelFormat:
299 fourcc = attr_list[
i].value.value.i;
307 case VASurfaceAttribMinWidth:
308 constraints->
min_width = attr_list[
i].value.value.i;
310 case VASurfaceAttribMinHeight:
311 constraints->
min_height = attr_list[
i].value.value.i;
313 case VASurfaceAttribMaxWidth:
314 constraints->
max_width = attr_list[
i].value.value.i;
316 case VASurfaceAttribMaxHeight:
317 constraints->
max_height = attr_list[
i].value.value.i;
321 if (pix_fmt_count == 0) {
333 for (
i = j = 0;
i < attr_count;
i++) {
336 if (attr_list[
i].
type != VASurfaceAttribPixelFormat)
338 fourcc = attr_list[
i].value.value.i;
344 for (k = 0; k < j; k++) {
363 for (
i = j = 0;
i <
ctx->nb_formats;
i++) {
366 for (k = 0; k < j; k++) {
397#if !VA_CHECK_VERSION(1, 0, 0)
400 "Intel i965 (Quick Sync)",
412 "Splitted-Desktop Systems VDPAU backend for VA-API",
421 VAImageFormat *image_list =
NULL;
423 const char *vendor_string;
424 int err,
i, image_count;
428 image_count = vaMaxNumImageFormats(hwctx->
display);
429 if (image_count <= 0) {
433 image_list =
av_malloc(image_count *
sizeof(*image_list));
438 vas = vaQueryImageFormats(hwctx->
display, image_list, &image_count);
439 if (vas != VA_STATUS_SUCCESS) {
450 for (
i = 0;
i < image_count;
i++) {
461 ctx->formats[
ctx->nb_formats].image_format = image_list[
i];
466 vendor_string = vaQueryVendorString(hwctx->
display);
478 if (strstr(vendor_string,
481 "as known nonstandard driver \"%s\", setting "
492 "nonstandard list, using standard behaviour.\n");
496 "assuming standard behaviour.\n");
519 VASurfaceID surface_id;
522 surface_id = (VASurfaceID)(uintptr_t)
data;
524 vas = vaDestroySurfaces(hwctx->
display, &surface_id, 1);
525 if (vas != VA_STATUS_SUCCESS) {
527 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
537 VASurfaceID surface_id;
545 vas = vaCreateSurfaces(hwctx->
display,
ctx->rt_format,
548 ctx->attributes,
ctx->nb_attributes);
549 if (vas != VA_STATUS_SUCCESS) {
551 "%d (%s).\n", vas, vaErrorStr(vas));
560 vaDestroySurfaces(hwctx->
display, &surface_id, 1);
581 VAImageFormat *expected_format =
NULL;
583 VASurfaceID test_surface_id;
589 &
desc, &expected_format);
602 int need_pixel_format = 1;
604 if (avfc->
attributes[
i].type == VASurfaceAttribMemoryType)
605 need_memory_type = 0;
606 if (avfc->
attributes[
i].type == VASurfaceAttribPixelFormat)
607 need_pixel_format = 0;
613 sizeof(*
ctx->attributes));
614 if (!
ctx->attributes) {
621 if (need_memory_type) {
622 ctx->attributes[
i++] = (VASurfaceAttrib) {
623 .type = VASurfaceAttribMemoryType,
624 .flags = VA_SURFACE_ATTRIB_SETTABLE,
625 .value.type = VAGenericValueTypeInteger,
626 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
629 if (need_pixel_format) {
630 ctx->attributes[
i++] = (VASurfaceAttrib) {
631 .type = VASurfaceAttribPixelFormat,
632 .flags = VA_SURFACE_ATTRIB_SETTABLE,
633 .value.type = VAGenericValueTypeInteger,
634 .value.value.i =
desc->fourcc,
640 ctx->nb_attributes = 0;
643 ctx->rt_format =
desc->rt_format;
679 "user-configured buffer pool.\n");
687 "internal buffer pool.\n");
692 test_surface_id = (VASurfaceID)(uintptr_t)test_surface->
data;
694 ctx->derive_works = 0;
695 if (expected_format) {
696 vas = vaDeriveImage(hwctx->
display, test_surface_id, &test_image);
697 if (vas == VA_STATUS_SUCCESS) {
698 if (expected_format->fourcc == test_image.format.fourcc) {
700 ctx->derive_works = 1;
703 "derived image format %08x does not match "
704 "expected format %08x.\n",
705 expected_format->fourcc, test_image.format.fourcc);
707 vaDestroyImage(hwctx->
display, test_image.image_id);
710 "deriving image does not work: "
711 "%d (%s).\n", vas, vaErrorStr(vas));
715 "image format is not supported.\n");
757 int i, k, sw_format_available;
759 sw_format_available = 0;
760 for (
i = 0;
i <
ctx->nb_formats;
i++) {
762 sw_format_available = 1;
769 if (sw_format_available) {
775 for (
i = 0;
i <
ctx->nb_formats;
i++) {
792 VASurfaceID surface_id;
795 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
798 vas = vaUnmapBuffer(hwctx->
display,
map->image.buf);
799 if (vas != VA_STATUS_SUCCESS) {
801 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
806 vas = vaPutImage(hwctx->
display, surface_id,
map->image.image_id,
809 if (vas != VA_STATUS_SUCCESS) {
811 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
815 vas = vaDestroyImage(hwctx->
display,
map->image.image_id);
816 if (vas != VA_STATUS_SUCCESS) {
818 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
829 VASurfaceID surface_id;
831 VAImageFormat *image_format;
834 void *address =
NULL;
836#if VA_CHECK_VERSION(1, 21, 0)
837 uint32_t vaflags = 0;
840 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
864 map->image.image_id = VA_INVALID_ID;
866 vas = vaSyncSurface(hwctx->
display, surface_id);
867 if (vas != VA_STATUS_SUCCESS) {
869 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
883 vas = vaDeriveImage(hwctx->
display, surface_id, &
map->image);
884 if (vas != VA_STATUS_SUCCESS) {
886 "surface %#x: %d (%s).\n",
887 surface_id, vas, vaErrorStr(vas));
891 if (
map->image.format.fourcc != image_format->fourcc) {
893 "is in wrong format: expected %#08x, got %#08x.\n",
894 surface_id, image_format->fourcc,
map->image.format.fourcc);
900 vas = vaCreateImage(hwctx->
display, image_format,
902 if (vas != VA_STATUS_SUCCESS) {
904 "surface %#x: %d (%s).\n",
905 surface_id, vas, vaErrorStr(vas));
910 vas = vaGetImage(hwctx->
display, surface_id, 0, 0,
912 if (vas != VA_STATUS_SUCCESS) {
914 "surface %#x: %d (%s).\n",
915 surface_id, vas, vaErrorStr(vas));
922#if VA_CHECK_VERSION(1, 21, 0)
924 vaflags |= VA_MAPBUFFER_FLAG_READ;
926 vaflags |= VA_MAPBUFFER_FLAG_WRITE;
928 vas = vaMapBuffer2(hwctx->
display,
map->image.buf, &address, vaflags);
930 vas = vaMapBuffer(hwctx->
display,
map->image.buf, &address);
932 if (vas != VA_STATUS_SUCCESS) {
934 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
945 dst->height =
src->height;
947 for (
i = 0;
i <
map->image.num_planes;
i++) {
948 dst->data[
i] = (uint8_t*)address +
map->image.offsets[
i];
949 dst->linesize[
i] =
map->image.pitches[
i];
953 if (
desc &&
desc->chroma_planes_swapped) {
963 vaUnmapBuffer(hwctx->
display,
map->image.buf);
964 if (
map->image.image_id != VA_INVALID_ID)
965 vaDestroyImage(hwctx->
display,
map->image.image_id);
983 map->format =
dst->format;
990 map->height =
dst->height;
1014 map->format =
src->format;
1021 map->height =
src->height;
1051#define DRM_MAP(va, layers, ...) { \
1056static const struct {
1058 int nb_layer_formats;
1060} vaapi_drm_format_map[] = {
1062 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
1063 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88),
1065 DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
1066#if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
1067 DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1069#if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
1070 DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1072 DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
1073 DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
1074 DRM_MAP(
RGBA, 1, DRM_FORMAT_ABGR8888),
1075 DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
1076#ifdef VA_FOURCC_ABGR
1077 DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
1078 DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
1080 DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
1081 DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
1082#if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
1083 DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
1085#if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
1086 DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
1088#if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
1089 DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
1091#if defined(VA_FOURCC_X2R10G10B10) && defined(DRM_FORMAT_XRGB2101010)
1092 DRM_MAP(X2R10G10B10, 1, DRM_FORMAT_XRGB2101010),
1102 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->
priv;
1106 vaDestroySurfaces(dst_dev->
display, &surface_id, 1);
1112#if VA_CHECK_VERSION(1, 1, 0)
1123 VASurfaceID surface_id;
1124 VAStatus vas = VA_STATUS_SUCCESS;
1128#if !VA_CHECK_VERSION(1, 1, 0)
1129 unsigned long buffer_handle;
1130 VASurfaceAttribExternalBuffers buffer_desc;
1131 VASurfaceAttrib attrs[2] = {
1133 .type = VASurfaceAttribMemoryType,
1134 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1135 .value.type = VAGenericValueTypeInteger,
1136 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1139 .type = VASurfaceAttribExternalBufferDescriptor,
1140 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1141 .value.type = VAGenericValueTypePointer,
1142 .value.value.p = &buffer_desc,
1149 if (
desc->nb_objects != 1) {
1151 "made from a single DRM object.\n");
1157 if (
desc->nb_layers != vaapi_drm_format_map[
i].nb_layer_formats)
1159 for (j = 0; j <
desc->nb_layers; j++) {
1160 if (
desc->layers[j].format !=
1161 vaapi_drm_format_map[
i].layer_formats[j])
1164 if (j !=
desc->nb_layers)
1166 va_fourcc = vaapi_drm_format_map[
i].va_fourcc;
1176 "%08x.\n",
desc->objects[0].fd, va_fourcc);
1181#if VA_CHECK_VERSION(1, 1, 0)
1182 use_prime2 = !src_vafc->prime_2_import_unsupported &&
1185 VADRMPRIMESurfaceDescriptor prime_desc;
1186 VASurfaceAttrib prime_attrs[2] = {
1188 .type = VASurfaceAttribMemoryType,
1189 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1190 .value.type = VAGenericValueTypeInteger,
1191 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1194 .type = VASurfaceAttribExternalBufferDescriptor,
1195 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1196 .value.type = VAGenericValueTypePointer,
1197 .value.value.p = &prime_desc,
1200 prime_desc.fourcc = va_fourcc;
1201 prime_desc.width = src_fc->width;
1202 prime_desc.height = src_fc->height;
1203 prime_desc.num_objects =
desc->nb_objects;
1204 for (
i = 0;
i <
desc->nb_objects; ++
i) {
1205 prime_desc.objects[
i].fd =
desc->objects[
i].fd;
1206 prime_desc.objects[
i].size =
desc->objects[
i].size;
1207 prime_desc.objects[
i].drm_format_modifier =
1208 desc->objects[
i].format_modifier;
1211 prime_desc.num_layers =
desc->nb_layers;
1212 for (
i = 0;
i <
desc->nb_layers; ++
i) {
1213 prime_desc.layers[
i].drm_format =
desc->layers[
i].format;
1214 prime_desc.layers[
i].num_planes =
desc->layers[
i].nb_planes;
1215 for (j = 0; j <
desc->layers[
i].nb_planes; ++j) {
1216 prime_desc.layers[
i].object_index[j] =
1217 desc->layers[
i].planes[j].object_index;
1218 prime_desc.layers[
i].offset[j] =
desc->layers[
i].planes[j].offset;
1219 prime_desc.layers[
i].pitch[j] =
desc->layers[
i].planes[j].pitch;
1222 if (format_desc->chroma_planes_swapped &&
1223 desc->layers[
i].nb_planes == 3) {
1224 FFSWAP(uint32_t, prime_desc.layers[
i].pitch[1],
1225 prime_desc.layers[
i].pitch[2]);
1226 FFSWAP(uint32_t, prime_desc.layers[
i].offset[1],
1227 prime_desc.layers[
i].offset[2]);
1237 vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1238 src->width,
src->height, &surface_id, 1,
1240 if (vas != VA_STATUS_SUCCESS)
1241 src_vafc->prime_2_import_unsupported = 1;
1244 if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1246 uintptr_t buffer_handle;
1247 VASurfaceAttribExternalBuffers buffer_desc;
1248 VASurfaceAttrib buffer_attrs[2] = {
1250 .type = VASurfaceAttribMemoryType,
1251 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1252 .value.type = VAGenericValueTypeInteger,
1253 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1256 .type = VASurfaceAttribExternalBufferDescriptor,
1257 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1258 .value.type = VAGenericValueTypePointer,
1259 .value.value.p = &buffer_desc,
1263 buffer_handle =
desc->objects[0].fd;
1264 buffer_desc.pixel_format = va_fourcc;
1265 buffer_desc.width = src_fc->width;
1266 buffer_desc.height = src_fc->height;
1267 buffer_desc.data_size =
desc->objects[0].size;
1268 buffer_desc.buffers = &buffer_handle;
1269 buffer_desc.num_buffers = 1;
1270 buffer_desc.flags = 0;
1273 for (
i = 0;
i <
desc->nb_layers;
i++) {
1274 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1275 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1276 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1280 buffer_desc.num_planes = k;
1282 if (format_desc->chroma_planes_swapped &&
1283 buffer_desc.num_planes == 3) {
1284 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1285 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1288 vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1294 buffer_handle =
desc->objects[0].fd;
1295 buffer_desc.pixel_format = va_fourcc;
1296 buffer_desc.width = src_fc->width;
1297 buffer_desc.height = src_fc->height;
1298 buffer_desc.data_size =
desc->objects[0].size;
1299 buffer_desc.buffers = &buffer_handle;
1300 buffer_desc.num_buffers = 1;
1301 buffer_desc.flags = 0;
1304 for (
i = 0;
i <
desc->nb_layers;
i++) {
1305 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1306 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1307 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1311 buffer_desc.num_planes = k;
1313 if (format_desc->chroma_planes_swapped &&
1314 buffer_desc.num_planes == 3) {
1315 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1316 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1319 vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1324 if (vas != VA_STATUS_SUCCESS) {
1326 "object: %d (%s).\n", vas, vaErrorStr(vas));
1332 &vaapi_unmap_from_drm,
1333 (
void*)(uintptr_t)surface_id);
1338 dst->height =
src->height;
1339 dst->data[3] = (uint8_t*)(uintptr_t)surface_id;
1342 "surface %#x.\n",
desc->objects[0].fd, surface_id);
1347#if VA_CHECK_VERSION(1, 1, 0)
1364 VASurfaceID surface_id;
1366 VADRMPRIMESurfaceDescriptor va_desc;
1368 uint32_t export_flags;
1371 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1373 export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1375 export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1377 vas = vaSyncSurface(hwctx->
display, surface_id);
1378 if (vas != VA_STATUS_SUCCESS) {
1380 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
1386 export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1388 vas = vaExportSurfaceHandle(hwctx->
display, surface_id,
1389 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1390 export_flags, &va_desc);
1391 if (vas != VA_STATUS_SUCCESS) {
1392 if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1395 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1407 for (
i = 0;
i < va_desc.num_objects;
i++) {
1411 va_desc.objects[
i].drm_format_modifier;
1413 drm_desc->
nb_layers = va_desc.num_layers;
1414 for (
i = 0;
i < va_desc.num_layers;
i++) {
1417 for (j = 0; j < va_desc.layers[
i].num_planes; j++) {
1419 va_desc.layers[
i].object_index[j];
1421 va_desc.layers[
i].offset[j];
1423 va_desc.layers[
i].pitch[j];
1428 &vaapi_unmap_to_drm_esh, drm_desc);
1433 dst->height =
src->height;
1434 dst->data[0] = (uint8_t*)drm_desc;
1439 for (
i = 0;
i < va_desc.num_objects;
i++)
1440 close(va_desc.objects[
i].fd);
1446#if VA_CHECK_VERSION(0, 36, 0)
1447typedef struct VAAPIDRMImageBufferMapping {
1449 VABufferInfo buffer_info;
1451 AVDRMFrameDescriptor drm_desc;
1452} VAAPIDRMImageBufferMapping;
1458 VAAPIDRMImageBufferMapping *mapping = hwmap->
priv;
1459 VASurfaceID surface_id;
1462 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
1469 vas = vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1470 if (vas != VA_STATUS_SUCCESS) {
1472 "handle of image %#x (derived from surface %#x): "
1473 "%d (%s).\n", mapping->image.buf, surface_id,
1474 vas, vaErrorStr(vas));
1477 vas = vaDestroyImage(hwctx->
display, mapping->image.image_id);
1478 if (vas != VA_STATUS_SUCCESS) {
1480 "derived from surface %#x: %d (%s).\n",
1481 surface_id, vas, vaErrorStr(vas));
1491 VAAPIDRMImageBufferMapping *mapping =
NULL;
1492 VASurfaceID surface_id;
1496 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1504 vas = vaDeriveImage(hwctx->
display, surface_id,
1506 if (vas != VA_STATUS_SUCCESS) {
1508 "surface %#x: %d (%s).\n",
1509 surface_id, vas, vaErrorStr(vas));
1515 if (vaapi_drm_format_map[
i].va_fourcc ==
1516 mapping->image.format.fourcc)
1521 "VAAPI format %#x.\n", mapping->image.format.fourcc);
1526 mapping->buffer_info.mem_type =
1527 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1529 mapping->drm_desc.nb_layers =
1530 vaapi_drm_format_map[
i].nb_layer_formats;
1531 if (mapping->drm_desc.nb_layers > 1) {
1532 if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1534 "expected format: got %d planes, but expected %d.\n",
1535 mapping->image.num_planes, mapping->drm_desc.nb_layers);
1540 for(p = 0;
p < mapping->drm_desc.nb_layers;
p++) {
1542 .format = vaapi_drm_format_map[
i].layer_formats[
p],
1546 .offset = mapping->image.offsets[
p],
1547 .pitch = mapping->image.pitches[
p],
1552 mapping->drm_desc.layers[0].format =
1553 vaapi_drm_format_map[
i].layer_formats[0];
1554 mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1555 for (p = 0;
p < mapping->image.num_planes;
p++) {
1558 .offset = mapping->image.offsets[
p],
1559 .pitch = mapping->image.pitches[
p],
1564 vas = vaAcquireBufferHandle(hwctx->
display, mapping->image.buf,
1565 &mapping->buffer_info);
1566 if (vas != VA_STATUS_SUCCESS) {
1568 "handle from image %#x (derived from surface %#x): "
1569 "%d (%s).\n", mapping->image.buf, surface_id,
1570 vas, vaErrorStr(vas));
1576 mapping->buffer_info.handle);
1578 mapping->drm_desc.nb_objects = 1;
1580 .fd = mapping->buffer_info.handle,
1581 .size = mapping->image.data_size,
1587 dst,
src, &vaapi_unmap_to_drm_abh,
1592 dst->data[0] = (uint8_t*)&mapping->drm_desc;
1594 dst->height =
src->height;
1599 vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1601 vaDestroyImage(hwctx->
display, mapping->image.image_id);
1611#if VA_CHECK_VERSION(1, 1, 0)
1613 err = vaapi_map_to_drm_esh(hwfc,
dst,
src,
flags);
1617#if VA_CHECK_VERSION(0, 36, 0)
1618 return vaapi_map_to_drm_abh(hwfc,
dst,
src,
flags);
1628 switch (
src->format) {
1641 switch (
dst->format) {
1660 if (priv->x11_display)
1661 XCloseDisplay(priv->x11_display);
1673static void vaapi_device_log_error(
void *context,
const char *
message)
1680static void vaapi_device_log_info(
void *context,
const char *
message)
1696 vaSetErrorCallback(display, &vaapi_device_log_error,
ctx);
1697 vaSetInfoCallback (display, &vaapi_device_log_info,
ctx);
1702 vas = vaInitialize(display, &major, &minor);
1703 if (vas != VA_STATUS_SUCCESS) {
1705 "connection: %d (%s).\n", vas, vaErrorStr(vas));
1709 "version %d.%d\n", major, minor);
1718 VADisplay display =
NULL;
1720 int try_drm, try_x11, try_win32, try_all
av_unused;
1728 ctx->user_opaque = priv;
1733 try_all = try_drm = try_x11 = try_win32 = 0;
1734 if (!strcmp(ent->
value,
"drm")) {
1736 }
else if (!strcmp(ent->
value,
"x11")) {
1738 }
else if (!strcmp(ent->
value,
"win32")) {
1747 try_drm = HAVE_VAAPI_DRM;
1748 try_x11 = HAVE_VAAPI_X11;
1749 try_win32 = HAVE_VAAPI_WIN32;
1753 while (!display && try_drm) {
1759 priv->
drm_fd = open(device, O_RDWR);
1761 av_log(
ctx, loglevel,
"Failed to open %s as "
1762 "DRM device node.\n", device);
1767 int n, max_devices = 8;
1775 for (n = 0; n < max_devices; n++) {
1777 "/dev/dri/renderD%d", 128 + n);
1778 priv->
drm_fd = open(path, O_RDWR);
1780 if (errno == ENOENT) {
1781 if (n != max_devices - 1) {
1783 "No render device %s, try next device for "
1784 "DRM render node.\n", path);
1789 "for DRM render node.\n");
1792 "DRM render node for device %d.\n", n);
1796 info = drmGetVersion(priv->
drm_fd);
1799 "Failed to get DRM version for device %d.\n", n);
1804 if (kernel_driver) {
1805 if (strcmp(kernel_driver->
value, info->name)) {
1807 "with non-matching kernel driver (%s).\n",
1809 drmFreeVersion(info);
1815 "DRM render node for device %d, "
1816 "with matching kernel driver (%s).\n",
1818 drmFreeVersion(info);
1821 }
else if (!strcmp(info->name,
"vgem")) {
1823 "Skipping vgem node for device %d.\n", n);
1824 drmFreeVersion(info);
1828 }
else if (vendor_id) {
1829 drmDevicePtr device;
1831 if (drmGetDevice(priv->
drm_fd, &device)) {
1833 "Failed to get DRM device info for device %d.\n", n);
1836 drmFreeVersion(info);
1840 snprintf(drm_vendor,
sizeof(drm_vendor),
"0x%x", device->deviceinfo.pci->vendor_id);
1841 if (strcmp(vendor_id->
value, drm_vendor)) {
1843 "with non-matching vendor id (%s).\n",
1844 n, vendor_id->
value);
1845 drmFreeDevice(&device);
1848 drmFreeVersion(info);
1852 "DRM render node for device %d, "
1853 "with matching vendor id (%s).\n",
1854 n, vendor_id->
value);
1855 drmFreeDevice(&device);
1856 drmFreeVersion(info);
1859 drmFreeVersion(info);
1862 "DRM render node for device %d.\n", n);
1865 if (n >= max_devices)
1869 display = vaGetDisplayDRM(priv->
drm_fd);
1872 "from DRM device %s.\n", device);
1880 if (!display && try_x11) {
1882 priv->x11_display = XOpenDisplay(device);
1883 if (!priv->x11_display) {
1885 "%s.\n", XDisplayName(device));
1887 display = vaGetDisplay(priv->x11_display);
1890 "from X11 display %s.\n", XDisplayName(device));
1895 "X11 display %s.\n", XDisplayName(device));
1901 if (!display && try_win32) {
1904 display = vaGetDisplayWin32(
NULL);
1906 IDXGIFactory2 *pDXGIFactory =
NULL;
1907 IDXGIAdapter *pAdapter =
NULL;
1909 HANDLE dxgi = dlopen(
"dxgi.dll", 0);
1916 if (!pfnCreateDXGIFactory) {
1927 if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2,
1928 (
void **)&pDXGIFactory))) {
1929 int adapter = atoi(device);
1930 if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
1933 DXGI_ADAPTER_DESC
desc;
1934 if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &
desc))) {
1936 "Using device %04x:%04x (%ls) - LUID %lu %ld.\n",
1938 desc.AdapterLuid.LowPart,
1939 desc.AdapterLuid.HighPart);
1940 display = vaGetDisplayWin32(&
desc.AdapterLuid);
1942 IDXGIAdapter_Release(pAdapter);
1944 IDXGIFactory2_Release(pDXGIFactory);
1953 "from Win32 display.\n");
1958 "Win32 display.\n");
1965 "device %s.\n", device);
1968 "any default device.\n");
1974#if VA_CHECK_VERSION(0, 38, 0)
1976 vas = vaSetDriverName(display, ent->
value);
1977 if (vas != VA_STATUS_SUCCESS) {
1979 "%s: %d (%s).\n", ent->
value, vas, vaErrorStr(vas));
1980 vaTerminate(display);
1985 "supported with this VAAPI version.\n");
2003 if (src_hwctx->
fd < 0) {
2005 "device to derive a VA display from.\n");
2011 int node_type = drmGetNodeTypeFromFd(src_hwctx->
fd);
2013 if (node_type < 0) {
2015 "to refer to a DRM device.\n");
2018 if (node_type == DRM_NODE_RENDER) {
2021 render_node = drmGetRenderDeviceNameFromFd(src_hwctx->
fd);
2024 "because the device does not have an "
2025 "associated render node.\n");
2028 fd = open(render_node, O_RDWR);
2031 "because the associated render node "
2032 "could not be opened.\n");
2036 "in place of non-render DRM device.\n",
2049 if (fd != src_hwctx->
fd) {
2056 if (fd == src_hwctx->
fd) {
2064 ctx->user_opaque = priv;
2067 display = vaGetDisplayDRM(fd);
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static AVFormatContext * ctx
static AVDictionary * opts
static av_cold void close(AVCodecParserContext *s)
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
refcounted data buffer API
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
common internal and external API header
static enum AVPixelFormat pix_fmt
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_EXTERNAL
Generic error in an external library.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
@ AV_HWFRAME_MAP_OVERWRITE
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
AVHWFrameTransferDirection
HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory)
API-specific header for AV_HWDEVICE_TYPE_DRM.
@ AV_DRM_MAX_PLANES
The maximum number of layers/planes in a DRM frame.
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
const HWContextType ff_hwcontext_type_vaapi
static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static const VAAPIFormatDescriptor * vaapi_format_from_fourcc(unsigned int fourcc)
static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
static int vaapi_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
static void vaapi_buffer_free(void *opaque, uint8_t *data)
static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vaapi_frames_init(AVHWFramesContext *hwfc)
const char * match_string
static AVBufferRef * vaapi_pool_alloc(void *opaque, size_t size)
static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, const void *hwconfig, AVHWFramesConstraints *constraints)
static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
static void vaapi_device_free(AVHWDeviceContext *ctx)
#define MAP(va, rt, av, swap_uv)
static const struct @005106002122236257040203037051175120226247135247 vaapi_driver_quirks_table[]
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int vaapi_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
static void vaapi_frames_uninit(AVHWFramesContext *hwfc)
static void vaapi_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
static int vaapi_device_connect(AVHWDeviceContext *ctx, VADisplay display)
static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int vaapi_device_init(AVHWDeviceContext *hwdev)
static int vaapi_get_img_desc_and_format(AVHWDeviceContext *hwdev, enum AVPixelFormat pix_fmt, const VAAPIFormatDescriptor **_desc, VAImageFormat **image_format)
static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static void vaapi_device_uninit(AVHWDeviceContext *hwdev)
const char * friendly_name
static int vaapi_get_image_format(AVHWDeviceContext *hwdev, enum AVPixelFormat pix_fmt, VAImageFormat **image_format)
static const VAAPIFormatDescriptor * vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt, const VAAPIFormatDescriptor *prev)
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
@ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
@ AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES
The driver does not support surface attributes at all.
@ AV_VAAPI_DRIVER_QUIRK_USER_SET
The quirks field has been set by the user and should not be detected automatically by av_hwdevice_ctx...
@ AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE
The driver does not support the VASurfaceAttribMemoryType attribute, so the surface allocation code w...
const VDPAUPixFmtMap * map
#define DRM_FORMAT_MOD_INVALID
static enum AVPixelFormat pix_fmts[]
#define FFSWAP(type, a, b)
Memory handling functions.
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
@ AV_PIX_FMT_VAAPI
Hardware acceleration through VA-API, data[3] contains a VASurfaceID.
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
uint8_t * data
The data buffer.
int fd
File descriptor of DRM device.
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
int nb_layers
Number of layers in the frame.
int nb_objects
Number of DRM objects making up this frame.
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
int nb_planes
Number of planes in the layer.
uint32_t format
Format of the layer (DRM_FORMAT_*).
int fd
DRM PRIME fd for the object.
size_t size
Total size of the object.
uint64_t format_modifier
Format modifier applied to the object (DRM_FORMAT_MOD_*).
ptrdiff_t pitch
Pitch (linesize) of this plane.
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor.
ptrdiff_t offset
Offset within that object of this plane.
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
int max_width
The maximum size of frames in this hw_frames_ctx.
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
int min_width
The minimum size of frames in this hw_frames_ctx.
This struct describes a set or pool of "hardware" frames (i.e.
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
int initial_pool_size
Initial size of the frame pool.
int width
The allocated dimensions of the frames in this pool.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
VAAPI connection details.
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
VADisplay display
The VADisplay handle, to be filled by the user.
VAAPI-specific data associated with a frame pool.
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
VASurfaceAttrib * attributes
Set by the user to apply surface attributes to all surfaces in the frame pool.
VAAPI hardware pipeline configuration details.
AVBufferPool * pool_internal
void * priv
Hardware-specific private data associated with the mapping.
AVFrame * source
A reference to the original source of the mapping.
VAAPISurfaceFormat * formats
AVVAAPIDeviceContext p
The public AVVAAPIDeviceContext.
AVVAAPIFramesContext p
The public AVVAAPIFramesContext.
int prime_2_import_unsupported
VASurfaceAttrib * attributes
#define av_malloc_array(a, b)
static int ref[MAX_W *MAX_W]
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pixelformat)
static const struct @375310172260344333305017135226063207373101217274 vaapi_format_map[]