24 # include <initguid.h>
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)
119 } VAAPIFormatDescriptor;
121 #define MAP(va, rt, av, swap_uv) { \
123 VA_RT_FORMAT_ ## rt, \
130 MAP(NV12, YUV420, NV12, 0),
131 #ifdef VA_FOURCC_I420
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),
137 #ifdef VA_FOURCC_YV16
138 MAP(YV16, YUV422, YUV422P, 1),
140 MAP(UYVY, YUV422, UYVY422, 0),
141 MAP(YUY2, YUV422, YUYV422, 0),
142 #ifdef VA_FOURCC_Y210
143 MAP(Y210, YUV422_10, Y210, 0),
145 #ifdef VA_FOURCC_Y212
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),
151 #ifdef VA_FOURCC_XYUV
152 MAP(XYUV, YUV444, VUYX, 0),
154 MAP(Y800, YUV400, GRAY8, 0),
155 #ifdef VA_FOURCC_P010
156 MAP(P010, YUV420_10BPP, P010, 0),
158 #ifdef VA_FOURCC_P012
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),
165 #ifdef VA_FOURCC_ABGR
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),
174 #ifdef VA_FOURCC_Y410
177 MAP(Y410, YUV444_10, XV30, 0),
179 #ifdef VA_FOURCC_Y412
182 MAP(Y412, YUV444_12, XV36, 0),
187 static const VAAPIFormatDescriptor *
197 static const VAAPIFormatDescriptor *
209 const VAAPIFormatDescriptor *
desc;
212 return desc->pix_fmt;
219 VAImageFormat **image_format)
222 const VAAPIFormatDescriptor *
desc;
226 if (!
desc || !image_format)
229 for (
i = 0;
i <
ctx->nb_formats;
i++) {
230 if (
ctx->formats[
i].fourcc ==
desc->fourcc) {
231 *image_format = &
ctx->formats[
i].image_format;
241 const void *hwconfig,
247 VASurfaceAttrib *attr_list =
NULL;
251 int err,
i, j, attr_count, pix_fmt_count;
256 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
258 if (vas != VA_STATUS_SUCCESS) {
260 "%d (%s).\n", vas, vaErrorStr(vas));
265 attr_list =
av_malloc(attr_count *
sizeof(*attr_list));
271 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
272 attr_list, &attr_count);
273 if (vas != VA_STATUS_SUCCESS) {
275 "%d (%s).\n", vas, vaErrorStr(vas));
281 for (
i = 0;
i < attr_count;
i++) {
282 switch (attr_list[
i].
type) {
283 case VASurfaceAttribPixelFormat:
284 fourcc = attr_list[
i].value.value.i;
292 case VASurfaceAttribMinWidth:
293 constraints->
min_width = attr_list[
i].value.value.i;
295 case VASurfaceAttribMinHeight:
296 constraints->
min_height = attr_list[
i].value.value.i;
298 case VASurfaceAttribMaxWidth:
299 constraints->
max_width = attr_list[
i].value.value.i;
301 case VASurfaceAttribMaxHeight:
302 constraints->
max_height = attr_list[
i].value.value.i;
306 if (pix_fmt_count == 0) {
318 for (
i = j = 0;
i < attr_count;
i++) {
321 if (attr_list[
i].
type != VASurfaceAttribPixelFormat)
323 fourcc = attr_list[
i].value.value.i;
329 for (k = 0; k < j; k++) {
348 for (
i = j = 0;
i <
ctx->nb_formats;
i++) {
351 for (k = 0; k < j; k++) {
377 static const struct {
382 #if !VA_CHECK_VERSION(1, 0, 0)
385 "Intel i965 (Quick Sync)",
397 "Splitted-Desktop Systems VDPAU backend for VA-API",
406 VAImageFormat *image_list =
NULL;
408 const char *vendor_string;
409 int err,
i, image_count;
413 image_count = vaMaxNumImageFormats(hwctx->
display);
414 if (image_count <= 0) {
418 image_list =
av_malloc(image_count *
sizeof(*image_list));
423 vas = vaQueryImageFormats(hwctx->
display, image_list, &image_count);
424 if (vas != VA_STATUS_SUCCESS) {
435 for (
i = 0;
i < image_count;
i++) {
446 ctx->formats[
ctx->nb_formats].image_format = image_list[
i];
451 vendor_string = vaQueryVendorString(hwctx->
display);
463 if (strstr(vendor_string,
466 "as known nonstandard driver \"%s\", setting "
477 "nonstandard list, using standard behaviour.\n");
481 "assuming standard behaviour.\n");
504 VASurfaceID surface_id;
507 surface_id = (VASurfaceID)(uintptr_t)
data;
509 vas = vaDestroySurfaces(hwctx->
display, &surface_id, 1);
510 if (vas != VA_STATUS_SUCCESS) {
512 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
522 VASurfaceID surface_id;
530 vas = vaCreateSurfaces(hwctx->
display,
ctx->rt_format,
533 ctx->attributes,
ctx->nb_attributes);
534 if (vas != VA_STATUS_SUCCESS) {
536 "%d (%s).\n", vas, vaErrorStr(vas));
545 vaDestroySurfaces(hwctx->
display, &surface_id, 1);
565 const VAAPIFormatDescriptor *
desc;
566 VAImageFormat *expected_format;
568 VASurfaceID test_surface_id;
583 int need_pixel_format = 1;
585 if (avfc->
attributes[
i].type == VASurfaceAttribMemoryType)
586 need_memory_type = 0;
587 if (avfc->
attributes[
i].type == VASurfaceAttribPixelFormat)
588 need_pixel_format = 0;
594 sizeof(*
ctx->attributes));
595 if (!
ctx->attributes) {
602 if (need_memory_type) {
603 ctx->attributes[
i++] = (VASurfaceAttrib) {
604 .type = VASurfaceAttribMemoryType,
605 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
606 .value.type = VAGenericValueTypeInteger,
607 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
610 if (need_pixel_format) {
611 ctx->attributes[
i++] = (VASurfaceAttrib) {
612 .type = VASurfaceAttribPixelFormat,
613 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
614 .value.type = VAGenericValueTypeInteger,
615 .value.value.i =
desc->fourcc,
621 ctx->nb_attributes = 0;
624 ctx->rt_format =
desc->rt_format;
660 "user-configured buffer pool.\n");
668 "internal buffer pool.\n");
673 test_surface_id = (VASurfaceID)(uintptr_t)test_surface->
data;
675 ctx->derive_works = 0;
680 vas = vaDeriveImage(hwctx->
display, test_surface_id, &test_image);
681 if (vas == VA_STATUS_SUCCESS) {
682 if (expected_format->fourcc == test_image.format.fourcc) {
684 ctx->derive_works = 1;
687 "derived image format %08x does not match "
688 "expected format %08x.\n",
689 expected_format->fourcc, test_image.format.fourcc);
691 vaDestroyImage(hwctx->
display, test_image.image_id);
694 "deriving image does not work: "
695 "%d (%s).\n", vas, vaErrorStr(vas));
699 "image format is not supported.\n");
741 int i, k, sw_format_available;
743 sw_format_available = 0;
744 for (
i = 0;
i <
ctx->nb_formats;
i++) {
746 sw_format_available = 1;
753 if (sw_format_available) {
759 for (
i = 0;
i <
ctx->nb_formats;
i++) {
776 VASurfaceID surface_id;
779 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
782 vas = vaUnmapBuffer(hwctx->
display,
map->image.buf);
783 if (vas != VA_STATUS_SUCCESS) {
785 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
790 vas = vaPutImage(hwctx->
display, surface_id,
map->image.image_id,
793 if (vas != VA_STATUS_SUCCESS) {
795 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
799 vas = vaDestroyImage(hwctx->
display,
map->image.image_id);
800 if (vas != VA_STATUS_SUCCESS) {
802 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
813 VASurfaceID surface_id;
814 const VAAPIFormatDescriptor *
desc;
815 VAImageFormat *image_format;
818 void *address =
NULL;
820 #if VA_CHECK_VERSION(1, 21, 0)
821 uint32_t vaflags = 0;
824 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
848 map->image.image_id = VA_INVALID_ID;
850 vas = vaSyncSurface(hwctx->
display, surface_id);
851 if (vas != VA_STATUS_SUCCESS) {
853 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
867 vas = vaDeriveImage(hwctx->
display, surface_id, &
map->image);
868 if (vas != VA_STATUS_SUCCESS) {
870 "surface %#x: %d (%s).\n",
871 surface_id, vas, vaErrorStr(vas));
875 if (
map->image.format.fourcc != image_format->fourcc) {
877 "is in wrong format: expected %#08x, got %#08x.\n",
878 surface_id, image_format->fourcc,
map->image.format.fourcc);
884 vas = vaCreateImage(hwctx->
display, image_format,
886 if (vas != VA_STATUS_SUCCESS) {
888 "surface %#x: %d (%s).\n",
889 surface_id, vas, vaErrorStr(vas));
894 vas = vaGetImage(hwctx->
display, surface_id, 0, 0,
896 if (vas != VA_STATUS_SUCCESS) {
898 "surface %#x: %d (%s).\n",
899 surface_id, vas, vaErrorStr(vas));
906 #if VA_CHECK_VERSION(1, 21, 0)
908 vaflags |= VA_MAPBUFFER_FLAG_READ;
910 vaflags |= VA_MAPBUFFER_FLAG_WRITE;
912 vas = vaMapBuffer2(hwctx->
display,
map->image.buf, &address, vaflags);
914 vas = vaMapBuffer(hwctx->
display,
map->image.buf, &address);
916 if (vas != VA_STATUS_SUCCESS) {
918 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
929 dst->height =
src->height;
931 for (
i = 0;
i <
map->image.num_planes;
i++) {
932 dst->data[
i] = (uint8_t*)address +
map->image.offsets[
i];
933 dst->linesize[
i] =
map->image.pitches[
i];
937 if (
desc &&
desc->chroma_planes_swapped) {
947 vaUnmapBuffer(hwctx->
display,
map->image.buf);
948 if (
map->image.image_id != VA_INVALID_ID)
949 vaDestroyImage(hwctx->
display,
map->image.image_id);
967 map->format =
dst->format;
974 map->height =
dst->height;
998 map->format =
src->format;
1005 map->height =
src->height;
1035 #define DRM_MAP(va, layers, ...) { \
1040 static const struct {
1042 int nb_layer_formats;
1044 } vaapi_drm_format_map[] = {
1045 #ifdef DRM_FORMAT_R8
1046 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
1047 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88),
1049 DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
1050 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
1051 DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1053 #if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
1054 DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1056 DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
1057 DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
1058 DRM_MAP(
RGBA, 1, DRM_FORMAT_ABGR8888),
1059 DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
1060 #ifdef VA_FOURCC_ABGR
1061 DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
1062 DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
1064 DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
1065 DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
1066 #if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
1067 DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
1069 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
1070 DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
1072 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
1073 DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
1075 #if defined(VA_FOURCC_X2R10G10B10) && defined(DRM_FORMAT_XRGB2101010)
1076 DRM_MAP(X2R10G10B10, 1, DRM_FORMAT_XRGB2101010),
1086 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->
priv;
1090 vaDestroySurfaces(dst_dev->
display, &surface_id, 1);
1096 #if VA_CHECK_VERSION(1, 1, 0)
1106 const VAAPIFormatDescriptor *format_desc;
1107 VASurfaceID surface_id;
1108 VAStatus vas = VA_STATUS_SUCCESS;
1112 #
if !VA_CHECK_VERSION(1, 1, 0)
1113 unsigned long buffer_handle;
1114 VASurfaceAttribExternalBuffers buffer_desc;
1115 VASurfaceAttrib attrs[2] = {
1117 .type = VASurfaceAttribMemoryType,
1118 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1119 .value.type = VAGenericValueTypeInteger,
1120 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1123 .type = VASurfaceAttribExternalBufferDescriptor,
1124 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1125 .value.type = VAGenericValueTypePointer,
1126 .value.value.p = &buffer_desc,
1133 if (
desc->nb_objects != 1) {
1135 "made from a single DRM object.\n");
1141 if (
desc->nb_layers != vaapi_drm_format_map[
i].nb_layer_formats)
1143 for (j = 0; j <
desc->nb_layers; j++) {
1144 if (
desc->layers[j].format !=
1145 vaapi_drm_format_map[
i].layer_formats[j])
1148 if (j !=
desc->nb_layers)
1150 va_fourcc = vaapi_drm_format_map[
i].va_fourcc;
1160 "%08x.\n",
desc->objects[0].fd, va_fourcc);
1165 #if VA_CHECK_VERSION(1, 1, 0)
1169 VADRMPRIMESurfaceDescriptor prime_desc;
1170 VASurfaceAttrib prime_attrs[2] = {
1172 .type = VASurfaceAttribMemoryType,
1173 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1174 .value.type = VAGenericValueTypeInteger,
1175 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1178 .type = VASurfaceAttribExternalBufferDescriptor,
1179 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1180 .value.type = VAGenericValueTypePointer,
1181 .value.value.p = &prime_desc,
1184 prime_desc.fourcc = va_fourcc;
1185 prime_desc.width = src_fc->
width;
1186 prime_desc.height = src_fc->
height;
1187 prime_desc.num_objects =
desc->nb_objects;
1188 for (
i = 0;
i <
desc->nb_objects; ++
i) {
1189 prime_desc.objects[
i].fd =
desc->objects[
i].fd;
1190 prime_desc.objects[
i].size =
desc->objects[
i].size;
1191 prime_desc.objects[
i].drm_format_modifier =
1192 desc->objects[
i].format_modifier;
1195 prime_desc.num_layers =
desc->nb_layers;
1196 for (
i = 0;
i <
desc->nb_layers; ++
i) {
1197 prime_desc.layers[
i].drm_format =
desc->layers[
i].format;
1198 prime_desc.layers[
i].num_planes =
desc->layers[
i].nb_planes;
1199 for (j = 0; j <
desc->layers[
i].nb_planes; ++j) {
1200 prime_desc.layers[
i].object_index[j] =
1201 desc->layers[
i].planes[j].object_index;
1202 prime_desc.layers[
i].offset[j] =
desc->layers[
i].planes[j].offset;
1203 prime_desc.layers[
i].pitch[j] =
desc->layers[
i].planes[j].pitch;
1206 if (format_desc->chroma_planes_swapped &&
1207 desc->layers[
i].nb_planes == 3) {
1208 FFSWAP(uint32_t, prime_desc.layers[
i].pitch[1],
1209 prime_desc.layers[
i].pitch[2]);
1210 FFSWAP(uint32_t, prime_desc.layers[
i].offset[1],
1211 prime_desc.layers[
i].offset[2]);
1221 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1222 src->width,
src->height, &surface_id, 1,
1224 if (vas != VA_STATUS_SUCCESS)
1228 if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1230 uintptr_t buffer_handle;
1231 VASurfaceAttribExternalBuffers buffer_desc;
1232 VASurfaceAttrib buffer_attrs[2] = {
1234 .type = VASurfaceAttribMemoryType,
1235 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1236 .value.type = VAGenericValueTypeInteger,
1237 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1240 .type = VASurfaceAttribExternalBufferDescriptor,
1241 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1242 .value.type = VAGenericValueTypePointer,
1243 .value.value.p = &buffer_desc,
1247 buffer_handle =
desc->objects[0].fd;
1248 buffer_desc.pixel_format = va_fourcc;
1249 buffer_desc.width = src_fc->
width;
1250 buffer_desc.height = src_fc->
height;
1251 buffer_desc.data_size =
desc->objects[0].size;
1252 buffer_desc.buffers = &buffer_handle;
1253 buffer_desc.num_buffers = 1;
1254 buffer_desc.flags = 0;
1257 for (
i = 0;
i <
desc->nb_layers;
i++) {
1258 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1259 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1260 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1264 buffer_desc.num_planes = k;
1266 if (format_desc->chroma_planes_swapped &&
1267 buffer_desc.num_planes == 3) {
1268 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1269 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1272 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1278 buffer_handle =
desc->objects[0].fd;
1279 buffer_desc.pixel_format = va_fourcc;
1280 buffer_desc.width = src_fc->
width;
1281 buffer_desc.height = src_fc->
height;
1282 buffer_desc.data_size =
desc->objects[0].size;
1283 buffer_desc.buffers = &buffer_handle;
1284 buffer_desc.num_buffers = 1;
1285 buffer_desc.flags = 0;
1288 for (
i = 0;
i <
desc->nb_layers;
i++) {
1289 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1290 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1291 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1295 buffer_desc.num_planes = k;
1297 if (format_desc->chroma_planes_swapped &&
1298 buffer_desc.num_planes == 3) {
1299 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1300 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1303 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1308 if (vas != VA_STATUS_SUCCESS) {
1310 "object: %d (%s).\n", vas, vaErrorStr(vas));
1316 &vaapi_unmap_from_drm,
1317 (
void*)(uintptr_t)surface_id);
1322 dst->height =
src->height;
1323 dst->data[3] = (uint8_t*)(uintptr_t)surface_id;
1326 "surface %#x.\n",
desc->objects[0].fd, surface_id);
1331 #if VA_CHECK_VERSION(1, 1, 0)
1348 VASurfaceID surface_id;
1350 VADRMPRIMESurfaceDescriptor va_desc;
1352 uint32_t export_flags;
1355 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1357 export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1359 export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1361 vas = vaSyncSurface(hwctx->
display, surface_id);
1362 if (vas != VA_STATUS_SUCCESS) {
1364 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
1370 export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1372 vas = vaExportSurfaceHandle(hwctx->
display, surface_id,
1373 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1374 export_flags, &va_desc);
1375 if (vas != VA_STATUS_SUCCESS) {
1376 if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1379 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1391 for (
i = 0;
i < va_desc.num_objects;
i++) {
1395 va_desc.objects[
i].drm_format_modifier;
1397 drm_desc->
nb_layers = va_desc.num_layers;
1398 for (
i = 0;
i < va_desc.num_layers;
i++) {
1401 for (j = 0; j < va_desc.layers[
i].num_planes; j++) {
1403 va_desc.layers[
i].object_index[j];
1405 va_desc.layers[
i].offset[j];
1407 va_desc.layers[
i].pitch[j];
1412 &vaapi_unmap_to_drm_esh, drm_desc);
1417 dst->height =
src->height;
1418 dst->data[0] = (uint8_t*)drm_desc;
1423 for (
i = 0;
i < va_desc.num_objects;
i++)
1424 close(va_desc.objects[
i].fd);
1430 #if VA_CHECK_VERSION(0, 36, 0)
1431 typedef struct VAAPIDRMImageBufferMapping {
1433 VABufferInfo buffer_info;
1436 } VAAPIDRMImageBufferMapping;
1442 VAAPIDRMImageBufferMapping *mapping = hwmap->
priv;
1443 VASurfaceID surface_id;
1446 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
1453 vas = vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1454 if (vas != VA_STATUS_SUCCESS) {
1456 "handle of image %#x (derived from surface %#x): "
1457 "%d (%s).\n", mapping->image.buf, surface_id,
1458 vas, vaErrorStr(vas));
1461 vas = vaDestroyImage(hwctx->
display, mapping->image.image_id);
1462 if (vas != VA_STATUS_SUCCESS) {
1464 "derived from surface %#x: %d (%s).\n",
1465 surface_id, vas, vaErrorStr(vas));
1475 VAAPIDRMImageBufferMapping *mapping =
NULL;
1476 VASurfaceID surface_id;
1480 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1488 vas = vaDeriveImage(hwctx->
display, surface_id,
1490 if (vas != VA_STATUS_SUCCESS) {
1492 "surface %#x: %d (%s).\n",
1493 surface_id, vas, vaErrorStr(vas));
1499 if (vaapi_drm_format_map[
i].va_fourcc ==
1500 mapping->image.format.fourcc)
1505 "VAAPI format %#x.\n", mapping->image.format.fourcc);
1510 mapping->buffer_info.mem_type =
1511 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1513 mapping->drm_desc.nb_layers =
1514 vaapi_drm_format_map[
i].nb_layer_formats;
1515 if (mapping->drm_desc.nb_layers > 1) {
1516 if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1518 "expected format: got %d planes, but expected %d.\n",
1519 mapping->image.num_planes, mapping->drm_desc.nb_layers);
1524 for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1526 .format = vaapi_drm_format_map[
i].layer_formats[p],
1530 .offset = mapping->image.offsets[p],
1531 .pitch = mapping->image.pitches[p],
1536 mapping->drm_desc.layers[0].format =
1537 vaapi_drm_format_map[
i].layer_formats[0];
1538 mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1539 for (p = 0; p < mapping->image.num_planes; p++) {
1542 .offset = mapping->image.offsets[p],
1543 .pitch = mapping->image.pitches[p],
1548 vas = vaAcquireBufferHandle(hwctx->
display, mapping->image.buf,
1549 &mapping->buffer_info);
1550 if (vas != VA_STATUS_SUCCESS) {
1552 "handle from image %#x (derived from surface %#x): "
1553 "%d (%s).\n", mapping->image.buf, surface_id,
1554 vas, vaErrorStr(vas));
1560 mapping->buffer_info.handle);
1562 mapping->drm_desc.nb_objects = 1;
1564 .fd = mapping->buffer_info.handle,
1565 .size = mapping->image.data_size,
1571 dst,
src, &vaapi_unmap_to_drm_abh,
1576 dst->data[0] = (uint8_t*)&mapping->drm_desc;
1578 dst->height =
src->height;
1583 vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1585 vaDestroyImage(hwctx->
display, mapping->image.image_id);
1595 #if VA_CHECK_VERSION(1, 1, 0)
1597 err = vaapi_map_to_drm_esh(hwfc,
dst,
src,
flags);
1601 #if VA_CHECK_VERSION(0, 36, 0)
1602 return vaapi_map_to_drm_abh(hwfc,
dst,
src,
flags);
1612 switch (
src->format) {
1625 switch (
dst->format) {
1644 if (priv->x11_display)
1645 XCloseDisplay(priv->x11_display);
1655 static void vaapi_device_log_error(
void *
context,
const char *
message)
1662 static void vaapi_device_log_info(
void *
context,
const char *
message)
1678 vaSetErrorCallback(display, &vaapi_device_log_error,
ctx);
1679 vaSetInfoCallback (display, &vaapi_device_log_info,
ctx);
1684 vas = vaInitialize(display, &major, &minor);
1685 if (vas != VA_STATUS_SUCCESS) {
1687 "connection: %d (%s).\n", vas, vaErrorStr(vas));
1691 "version %d.%d\n", major, minor);
1700 VADisplay display =
NULL;
1702 int try_drm, try_x11, try_win32, try_all;
1710 ctx->user_opaque = priv;
1715 try_all = try_drm = try_x11 = try_win32 = 0;
1716 if (!strcmp(ent->
value,
"drm")) {
1718 }
else if (!strcmp(ent->
value,
"x11")) {
1720 }
else if (!strcmp(ent->
value,
"win32")) {
1729 try_drm = HAVE_VAAPI_DRM;
1730 try_x11 = HAVE_VAAPI_X11;
1731 try_win32 = HAVE_VAAPI_WIN32;
1735 while (!display && try_drm) {
1741 priv->
drm_fd = open(device, O_RDWR);
1743 av_log(
ctx, loglevel,
"Failed to open %s as "
1744 "DRM device node.\n", device);
1749 int n, max_devices = 8;
1757 for (n = 0; n < max_devices; n++) {
1759 "/dev/dri/renderD%d", 128 + n);
1760 priv->
drm_fd = open(path, O_RDWR);
1762 if (errno == ENOENT) {
1763 if (n != max_devices - 1) {
1765 "No render device %s, try next device for "
1766 "DRM render node.\n", path);
1771 "for DRM render node.\n");
1774 "DRM render node for device %d.\n", n);
1781 "Failed to get DRM version for device %d.\n", n);
1786 if (kernel_driver) {
1787 if (strcmp(kernel_driver->
value,
info->name)) {
1789 "with non-matching kernel driver (%s).\n",
1791 drmFreeVersion(
info);
1797 "DRM render node for device %d, "
1798 "with matching kernel driver (%s).\n",
1800 drmFreeVersion(
info);
1803 }
else if (!strcmp(
info->name,
"vgem")) {
1805 "Skipping vgem node for device %d.\n", n);
1806 drmFreeVersion(
info);
1810 }
else if (vendor_id) {
1811 drmDevicePtr device;
1813 if (drmGetDevice(priv->
drm_fd, &device)) {
1815 "Failed to get DRM device info for device %d.\n", n);
1821 snprintf(drm_vendor,
sizeof(drm_vendor),
"0x%x", device->deviceinfo.pci->vendor_id);
1822 if (strcmp(vendor_id->
value, drm_vendor)) {
1824 "with non-matching vendor id (%s).\n",
1825 n, vendor_id->
value);
1826 drmFreeDevice(&device);
1832 "DRM render node for device %d, "
1833 "with matching vendor id (%s).\n",
1834 n, vendor_id->
value);
1835 drmFreeDevice(&device);
1838 drmFreeVersion(
info);
1841 "DRM render node for device %d.\n", n);
1844 if (n >= max_devices)
1848 display = vaGetDisplayDRM(priv->
drm_fd);
1851 "from DRM device %s.\n", device);
1859 if (!display && try_x11) {
1861 priv->x11_display = XOpenDisplay(device);
1862 if (!priv->x11_display) {
1864 "%s.\n", XDisplayName(device));
1866 display = vaGetDisplay(priv->x11_display);
1869 "from X11 display %s.\n", XDisplayName(device));
1874 "X11 display %s.\n", XDisplayName(device));
1879 #if HAVE_VAAPI_WIN32
1880 if (!display && try_win32) {
1883 display = vaGetDisplayWin32(
NULL);
1885 IDXGIFactory2 *pDXGIFactory =
NULL;
1886 IDXGIAdapter *pAdapter =
NULL;
1888 HANDLE dxgi = dlopen(
"dxgi.dll", 0);
1895 if (!pfnCreateDXGIFactory) {
1906 if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2,
1907 (
void **)&pDXGIFactory))) {
1908 int adapter = atoi(device);
1909 if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
1912 DXGI_ADAPTER_DESC
desc;
1913 if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &
desc))) {
1915 "Using device %04x:%04x (%ls) - LUID %lu %ld.\n",
1917 desc.AdapterLuid.LowPart,
1918 desc.AdapterLuid.HighPart);
1919 display = vaGetDisplayWin32(&
desc.AdapterLuid);
1921 IDXGIAdapter_Release(pAdapter);
1923 IDXGIFactory2_Release(pDXGIFactory);
1932 "from Win32 display.\n");
1937 "Win32 display.\n");
1944 "device %s.\n", device);
1947 "any default device.\n");
1953 #if VA_CHECK_VERSION(0, 38, 0)
1955 vas = vaSetDriverName(display, ent->
value);
1956 if (vas != VA_STATUS_SUCCESS) {
1958 "%s: %d (%s).\n", ent->
value, vas, vaErrorStr(vas));
1959 vaTerminate(display);
1964 "supported with this VAAPI version.\n");
1982 if (src_hwctx->
fd < 0) {
1984 "device to derive a VA display from.\n");
1990 int node_type = drmGetNodeTypeFromFd(src_hwctx->
fd);
1992 if (node_type < 0) {
1994 "to refer to a DRM device.\n");
1997 if (node_type == DRM_NODE_RENDER) {
2000 render_node = drmGetRenderDeviceNameFromFd(src_hwctx->
fd);
2003 "because the device does not have an "
2004 "associated render node.\n");
2007 fd = open(render_node, O_RDWR);
2010 "because the associated render node "
2011 "could not be opened.\n");
2015 "in place of non-render DRM device.\n",
2028 if (fd != src_hwctx->
fd) {
2035 if (fd == src_hwctx->
fd) {
2043 ctx->user_opaque = priv;
2046 display = vaGetDisplayDRM(fd);