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)
108 } VAAPIFormatDescriptor;
110 #define MAP(va, rt, av, swap_uv) { \
112 VA_RT_FORMAT_ ## rt, \
119 MAP(NV12, YUV420, NV12, 0),
120 #ifdef VA_FOURCC_I420
121 MAP(I420, YUV420, YUV420P, 0),
123 MAP(YV12, YUV420, YUV420P, 1),
124 MAP(IYUV, YUV420, YUV420P, 0),
125 MAP(422
H, YUV422, YUV422P, 0),
126 #ifdef VA_FOURCC_YV16
127 MAP(YV16, YUV422, YUV422P, 1),
129 MAP(UYVY, YUV422, UYVY422, 0),
130 MAP(YUY2, YUV422, YUYV422, 0),
131 #ifdef VA_FOURCC_Y210
132 MAP(Y210, YUV422_10, Y210, 0),
134 #ifdef VA_FOURCC_Y212
135 MAP(Y212, YUV422_12, Y212, 0),
137 MAP(411
P, YUV411, YUV411P, 0),
138 MAP(422
V, YUV422, YUV440P, 0),
139 MAP(444
P, YUV444, YUV444P, 0),
140 #ifdef VA_FOURCC_XYUV
141 MAP(XYUV, YUV444, VUYX, 0),
143 MAP(Y800, YUV400, GRAY8, 0),
144 #ifdef VA_FOURCC_P010
145 MAP(P010, YUV420_10BPP, P010, 0),
147 #ifdef VA_FOURCC_P012
148 MAP(P012, YUV420_12, P012, 0),
150 MAP(BGRA, RGB32, BGRA, 0),
151 MAP(BGRX, RGB32, BGR0, 0),
153 MAP(RGBX, RGB32, RGB0, 0),
154 #ifdef VA_FOURCC_ABGR
155 MAP(ABGR, RGB32, ABGR, 0),
156 MAP(XBGR, RGB32, 0BGR, 0),
158 MAP(ARGB, RGB32, ARGB, 0),
159 MAP(XRGB, RGB32, 0RGB, 0),
160 #ifdef VA_FOURCC_X2R10G10B10
161 MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
163 #ifdef VA_FOURCC_Y410
166 MAP(Y410, YUV444_10, XV30, 0),
168 #ifdef VA_FOURCC_Y412
171 MAP(Y412, YUV444_12, XV36, 0),
176 static const VAAPIFormatDescriptor *
186 static const VAAPIFormatDescriptor *
198 const VAAPIFormatDescriptor *
desc;
201 return desc->pix_fmt;
208 VAImageFormat **image_format)
213 for (
i = 0;
i <
ctx->nb_formats;
i++) {
216 *image_format = &
ctx->formats[
i].image_format;
224 const void *hwconfig,
230 VASurfaceAttrib *attr_list =
NULL;
234 int err,
i, j, attr_count, pix_fmt_count;
239 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
241 if (vas != VA_STATUS_SUCCESS) {
243 "%d (%s).\n", vas, vaErrorStr(vas));
248 attr_list =
av_malloc(attr_count *
sizeof(*attr_list));
254 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
255 attr_list, &attr_count);
256 if (vas != VA_STATUS_SUCCESS) {
258 "%d (%s).\n", vas, vaErrorStr(vas));
264 for (
i = 0;
i < attr_count;
i++) {
265 switch (attr_list[
i].
type) {
266 case VASurfaceAttribPixelFormat:
267 fourcc = attr_list[
i].value.value.i;
275 case VASurfaceAttribMinWidth:
276 constraints->
min_width = attr_list[
i].value.value.i;
278 case VASurfaceAttribMinHeight:
279 constraints->
min_height = attr_list[
i].value.value.i;
281 case VASurfaceAttribMaxWidth:
282 constraints->
max_width = attr_list[
i].value.value.i;
284 case VASurfaceAttribMaxHeight:
285 constraints->
max_height = attr_list[
i].value.value.i;
289 if (pix_fmt_count == 0) {
301 for (
i = j = 0;
i < attr_count;
i++) {
304 if (attr_list[
i].
type != VASurfaceAttribPixelFormat)
306 fourcc = attr_list[
i].value.value.i;
312 for (k = 0; k < j; k++) {
331 for (
i = j = 0;
i <
ctx->nb_formats;
i++) {
334 for (k = 0; k < j; k++) {
360 static const struct {
365 #if !VA_CHECK_VERSION(1, 0, 0)
368 "Intel i965 (Quick Sync)",
380 "Splitted-Desktop Systems VDPAU backend for VA-API",
389 VAImageFormat *image_list =
NULL;
391 const char *vendor_string;
392 int err,
i, image_count;
396 image_count = vaMaxNumImageFormats(hwctx->
display);
397 if (image_count <= 0) {
401 image_list =
av_malloc(image_count *
sizeof(*image_list));
406 vas = vaQueryImageFormats(hwctx->
display, image_list, &image_count);
407 if (vas != VA_STATUS_SUCCESS) {
418 for (
i = 0;
i < image_count;
i++) {
428 ctx->formats[
ctx->nb_formats].image_format = image_list[
i];
433 vendor_string = vaQueryVendorString(hwctx->
display);
445 if (strstr(vendor_string,
448 "as known nonstandard driver \"%s\", setting "
459 "nonstandard list, using standard behaviour.\n");
463 "assuming standard behaviour.\n");
486 VASurfaceID surface_id;
489 surface_id = (VASurfaceID)(uintptr_t)
data;
491 vas = vaDestroySurfaces(hwctx->
display, &surface_id, 1);
492 if (vas != VA_STATUS_SUCCESS) {
494 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
504 VASurfaceID surface_id;
512 vas = vaCreateSurfaces(hwctx->
display,
ctx->rt_format,
515 ctx->attributes,
ctx->nb_attributes);
516 if (vas != VA_STATUS_SUCCESS) {
518 "%d (%s).\n", vas, vaErrorStr(vas));
527 vaDestroySurfaces(hwctx->
display, &surface_id, 1);
547 const VAAPIFormatDescriptor *
desc;
548 VAImageFormat *expected_format;
550 VASurfaceID test_surface_id;
565 int need_pixel_format = 1;
567 if (avfc->
attributes[
i].type == VASurfaceAttribMemoryType)
568 need_memory_type = 0;
569 if (avfc->
attributes[
i].type == VASurfaceAttribPixelFormat)
570 need_pixel_format = 0;
576 sizeof(*
ctx->attributes));
577 if (!
ctx->attributes) {
584 if (need_memory_type) {
585 ctx->attributes[
i++] = (VASurfaceAttrib) {
586 .type = VASurfaceAttribMemoryType,
587 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
588 .value.type = VAGenericValueTypeInteger,
589 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
592 if (need_pixel_format) {
593 ctx->attributes[
i++] = (VASurfaceAttrib) {
594 .type = VASurfaceAttribPixelFormat,
595 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
596 .value.type = VAGenericValueTypeInteger,
597 .value.value.i =
desc->fourcc,
603 ctx->nb_attributes = 0;
606 ctx->rt_format =
desc->rt_format;
642 "user-configured buffer pool.\n");
650 "internal buffer pool.\n");
655 test_surface_id = (VASurfaceID)(uintptr_t)test_surface->
data;
657 ctx->derive_works = 0;
662 vas = vaDeriveImage(hwctx->
display, test_surface_id, &test_image);
663 if (vas == VA_STATUS_SUCCESS) {
664 if (expected_format->fourcc == test_image.format.fourcc) {
666 ctx->derive_works = 1;
669 "derived image format %08x does not match "
670 "expected format %08x.\n",
671 expected_format->fourcc, test_image.format.fourcc);
673 vaDestroyImage(hwctx->
display, test_image.image_id);
676 "deriving image does not work: "
677 "%d (%s).\n", vas, vaErrorStr(vas));
681 "image format is not supported.\n");
723 int i, k, sw_format_available;
725 sw_format_available = 0;
726 for (
i = 0;
i <
ctx->nb_formats;
i++) {
728 sw_format_available = 1;
735 if (sw_format_available) {
741 for (
i = 0;
i <
ctx->nb_formats;
i++) {
758 VASurfaceID surface_id;
761 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
764 vas = vaUnmapBuffer(hwctx->
display,
map->image.buf);
765 if (vas != VA_STATUS_SUCCESS) {
767 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
772 vas = vaPutImage(hwctx->
display, surface_id,
map->image.image_id,
775 if (vas != VA_STATUS_SUCCESS) {
777 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
781 vas = vaDestroyImage(hwctx->
display,
map->image.image_id);
782 if (vas != VA_STATUS_SUCCESS) {
784 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
795 VASurfaceID surface_id;
796 const VAAPIFormatDescriptor *
desc;
797 VAImageFormat *image_format;
800 void *address =
NULL;
803 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
827 map->image.image_id = VA_INVALID_ID;
829 vas = vaSyncSurface(hwctx->
display, surface_id);
830 if (vas != VA_STATUS_SUCCESS) {
832 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
846 vas = vaDeriveImage(hwctx->
display, surface_id, &
map->image);
847 if (vas != VA_STATUS_SUCCESS) {
849 "surface %#x: %d (%s).\n",
850 surface_id, vas, vaErrorStr(vas));
854 if (
map->image.format.fourcc != image_format->fourcc) {
856 "is in wrong format: expected %#08x, got %#08x.\n",
857 surface_id, image_format->fourcc,
map->image.format.fourcc);
863 vas = vaCreateImage(hwctx->
display, image_format,
865 if (vas != VA_STATUS_SUCCESS) {
867 "surface %#x: %d (%s).\n",
868 surface_id, vas, vaErrorStr(vas));
873 vas = vaGetImage(hwctx->
display, surface_id, 0, 0,
875 if (vas != VA_STATUS_SUCCESS) {
877 "surface %#x: %d (%s).\n",
878 surface_id, vas, vaErrorStr(vas));
885 vas = vaMapBuffer(hwctx->
display,
map->image.buf, &address);
886 if (vas != VA_STATUS_SUCCESS) {
888 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
901 for (
i = 0;
i <
map->image.num_planes;
i++) {
902 dst->
data[
i] = (uint8_t*)address +
map->image.offsets[
i];
907 if (
desc &&
desc->chroma_planes_swapped) {
917 vaUnmapBuffer(hwctx->
display,
map->image.buf);
918 if (
map->image.image_id != VA_INVALID_ID)
919 vaDestroyImage(hwctx->
display,
map->image.image_id);
968 map->format =
src->format;
975 map->height =
src->height;
1011 #define DRM_MAP(va, layers, ...) { \
1016 static const struct {
1018 int nb_layer_formats;
1020 } vaapi_drm_format_map[] = {
1021 #ifdef DRM_FORMAT_R8
1022 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
1023 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88),
1025 DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
1026 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
1027 DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1029 #if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
1030 DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1032 DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
1033 DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
1034 DRM_MAP(
RGBA, 1, DRM_FORMAT_ABGR8888),
1035 DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
1036 #ifdef VA_FOURCC_ABGR
1037 DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
1038 DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
1040 DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
1041 DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
1042 #if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
1043 DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
1045 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
1046 DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
1048 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
1049 DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
1051 #if defined(VA_FOURCC_X2R10G10B10) && defined(DRM_FORMAT_XRGB2101010)
1052 DRM_MAP(X2R10G10B10, 1, DRM_FORMAT_XRGB2101010),
1062 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->
priv;
1066 vaDestroySurfaces(dst_dev->
display, &surface_id, 1);
1072 #if VA_CHECK_VERSION(1, 1, 0)
1082 const VAAPIFormatDescriptor *format_desc;
1083 VASurfaceID surface_id;
1084 VAStatus vas = VA_STATUS_SUCCESS;
1088 #
if !VA_CHECK_VERSION(1, 1, 0)
1089 unsigned long buffer_handle;
1090 VASurfaceAttribExternalBuffers buffer_desc;
1091 VASurfaceAttrib attrs[2] = {
1093 .type = VASurfaceAttribMemoryType,
1094 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1095 .value.type = VAGenericValueTypeInteger,
1096 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1099 .type = VASurfaceAttribExternalBufferDescriptor,
1100 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1101 .value.type = VAGenericValueTypePointer,
1102 .value.value.p = &buffer_desc,
1109 if (
desc->nb_objects != 1) {
1111 "made from a single DRM object.\n");
1117 if (
desc->nb_layers != vaapi_drm_format_map[
i].nb_layer_formats)
1119 for (j = 0; j <
desc->nb_layers; j++) {
1120 if (
desc->layers[j].format !=
1121 vaapi_drm_format_map[
i].layer_formats[j])
1124 if (j !=
desc->nb_layers)
1126 va_fourcc = vaapi_drm_format_map[
i].va_fourcc;
1136 "%08x.\n",
desc->objects[0].fd, va_fourcc);
1141 #if VA_CHECK_VERSION(1, 1, 0)
1145 VADRMPRIMESurfaceDescriptor prime_desc;
1146 VASurfaceAttrib prime_attrs[2] = {
1148 .type = VASurfaceAttribMemoryType,
1149 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1150 .value.type = VAGenericValueTypeInteger,
1151 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1154 .type = VASurfaceAttribExternalBufferDescriptor,
1155 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1156 .value.type = VAGenericValueTypePointer,
1157 .value.value.p = &prime_desc,
1160 prime_desc.fourcc = va_fourcc;
1161 prime_desc.width = src_fc->
width;
1162 prime_desc.height = src_fc->
height;
1163 prime_desc.num_objects =
desc->nb_objects;
1164 for (
i = 0;
i <
desc->nb_objects; ++
i) {
1165 prime_desc.objects[
i].fd =
desc->objects[
i].fd;
1166 prime_desc.objects[
i].size =
desc->objects[
i].size;
1167 prime_desc.objects[
i].drm_format_modifier =
1168 desc->objects[
i].format_modifier;
1171 prime_desc.num_layers =
desc->nb_layers;
1172 for (
i = 0;
i <
desc->nb_layers; ++
i) {
1173 prime_desc.layers[
i].drm_format =
desc->layers[
i].format;
1174 prime_desc.layers[
i].num_planes =
desc->layers[
i].nb_planes;
1175 for (j = 0; j <
desc->layers[
i].nb_planes; ++j) {
1176 prime_desc.layers[
i].object_index[j] =
1177 desc->layers[
i].planes[j].object_index;
1178 prime_desc.layers[
i].offset[j] =
desc->layers[
i].planes[j].offset;
1179 prime_desc.layers[
i].pitch[j] =
desc->layers[
i].planes[j].pitch;
1182 if (format_desc->chroma_planes_swapped &&
1183 desc->layers[
i].nb_planes == 3) {
1184 FFSWAP(uint32_t, prime_desc.layers[
i].pitch[1],
1185 prime_desc.layers[
i].pitch[2]);
1186 FFSWAP(uint32_t, prime_desc.layers[
i].offset[1],
1187 prime_desc.layers[
i].offset[2]);
1197 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1198 src->width,
src->height, &surface_id, 1,
1200 if (vas != VA_STATUS_SUCCESS)
1204 if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1206 unsigned long buffer_handle;
1207 VASurfaceAttribExternalBuffers buffer_desc;
1208 VASurfaceAttrib buffer_attrs[2] = {
1210 .type = VASurfaceAttribMemoryType,
1211 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1212 .value.type = VAGenericValueTypeInteger,
1213 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1216 .type = VASurfaceAttribExternalBufferDescriptor,
1217 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1218 .value.type = VAGenericValueTypePointer,
1219 .value.value.p = &buffer_desc,
1223 buffer_handle =
desc->objects[0].fd;
1224 buffer_desc.pixel_format = va_fourcc;
1225 buffer_desc.width = src_fc->
width;
1226 buffer_desc.height = src_fc->
height;
1227 buffer_desc.data_size =
desc->objects[0].size;
1228 buffer_desc.buffers = &buffer_handle;
1229 buffer_desc.num_buffers = 1;
1230 buffer_desc.flags = 0;
1233 for (
i = 0;
i <
desc->nb_layers;
i++) {
1234 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1235 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1236 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1240 buffer_desc.num_planes = k;
1242 if (format_desc->chroma_planes_swapped &&
1243 buffer_desc.num_planes == 3) {
1244 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1245 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1248 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1254 buffer_handle =
desc->objects[0].fd;
1255 buffer_desc.pixel_format = va_fourcc;
1256 buffer_desc.width = src_fc->
width;
1257 buffer_desc.height = src_fc->
height;
1258 buffer_desc.data_size =
desc->objects[0].size;
1259 buffer_desc.buffers = &buffer_handle;
1260 buffer_desc.num_buffers = 1;
1261 buffer_desc.flags = 0;
1264 for (
i = 0;
i <
desc->nb_layers;
i++) {
1265 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1266 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1267 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1271 buffer_desc.num_planes = k;
1273 if (format_desc->chroma_planes_swapped &&
1274 buffer_desc.num_planes == 3) {
1275 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1276 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1279 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1284 if (vas != VA_STATUS_SUCCESS) {
1286 "object: %d (%s).\n", vas, vaErrorStr(vas));
1292 &vaapi_unmap_from_drm,
1293 (
void*)(uintptr_t)surface_id);
1299 dst->
data[3] = (uint8_t*)(uintptr_t)surface_id;
1302 "surface %#x.\n",
desc->objects[0].fd, surface_id);
1307 #if VA_CHECK_VERSION(1, 1, 0)
1324 VASurfaceID surface_id;
1326 VADRMPRIMESurfaceDescriptor va_desc;
1328 uint32_t export_flags;
1331 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1333 export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1335 export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1337 vas = vaSyncSurface(hwctx->
display, surface_id);
1338 if (vas != VA_STATUS_SUCCESS) {
1340 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
1346 export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1348 vas = vaExportSurfaceHandle(hwctx->
display, surface_id,
1349 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1350 export_flags, &va_desc);
1351 if (vas != VA_STATUS_SUCCESS) {
1352 if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1355 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1367 for (
i = 0;
i < va_desc.num_objects;
i++) {
1371 va_desc.objects[
i].drm_format_modifier;
1373 drm_desc->
nb_layers = va_desc.num_layers;
1374 for (
i = 0;
i < va_desc.num_layers;
i++) {
1377 for (j = 0; j < va_desc.layers[
i].num_planes; j++) {
1379 va_desc.layers[
i].object_index[j];
1381 va_desc.layers[
i].offset[j];
1383 va_desc.layers[
i].pitch[j];
1388 &vaapi_unmap_to_drm_esh, drm_desc);
1394 dst->
data[0] = (uint8_t*)drm_desc;
1399 for (
i = 0;
i < va_desc.num_objects;
i++)
1400 close(va_desc.objects[
i].fd);
1406 #if VA_CHECK_VERSION(0, 36, 0)
1407 typedef struct VAAPIDRMImageBufferMapping {
1409 VABufferInfo buffer_info;
1412 } VAAPIDRMImageBufferMapping;
1418 VAAPIDRMImageBufferMapping *mapping = hwmap->
priv;
1419 VASurfaceID surface_id;
1422 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
1429 vas = vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1430 if (vas != VA_STATUS_SUCCESS) {
1432 "handle of image %#x (derived from surface %#x): "
1433 "%d (%s).\n", mapping->image.buf, surface_id,
1434 vas, vaErrorStr(vas));
1437 vas = vaDestroyImage(hwctx->
display, mapping->image.image_id);
1438 if (vas != VA_STATUS_SUCCESS) {
1440 "derived from surface %#x: %d (%s).\n",
1441 surface_id, vas, vaErrorStr(vas));
1451 VAAPIDRMImageBufferMapping *mapping =
NULL;
1452 VASurfaceID surface_id;
1456 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1464 vas = vaDeriveImage(hwctx->
display, surface_id,
1466 if (vas != VA_STATUS_SUCCESS) {
1468 "surface %#x: %d (%s).\n",
1469 surface_id, vas, vaErrorStr(vas));
1475 if (vaapi_drm_format_map[
i].va_fourcc ==
1476 mapping->image.format.fourcc)
1481 "VAAPI format %#x.\n", mapping->image.format.fourcc);
1486 mapping->buffer_info.mem_type =
1487 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1489 mapping->drm_desc.nb_layers =
1490 vaapi_drm_format_map[
i].nb_layer_formats;
1491 if (mapping->drm_desc.nb_layers > 1) {
1492 if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1494 "expected format: got %d planes, but expected %d.\n",
1495 mapping->image.num_planes, mapping->drm_desc.nb_layers);
1500 for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1502 .format = vaapi_drm_format_map[
i].layer_formats[p],
1506 .offset = mapping->image.offsets[p],
1507 .pitch = mapping->image.pitches[p],
1512 mapping->drm_desc.layers[0].format =
1513 vaapi_drm_format_map[
i].layer_formats[0];
1514 mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1515 for (p = 0; p < mapping->image.num_planes; p++) {
1518 .offset = mapping->image.offsets[p],
1519 .pitch = mapping->image.pitches[p],
1524 vas = vaAcquireBufferHandle(hwctx->
display, mapping->image.buf,
1525 &mapping->buffer_info);
1526 if (vas != VA_STATUS_SUCCESS) {
1528 "handle from image %#x (derived from surface %#x): "
1529 "%d (%s).\n", mapping->image.buf, surface_id,
1530 vas, vaErrorStr(vas));
1536 mapping->buffer_info.handle);
1538 mapping->drm_desc.nb_objects = 1;
1540 .fd = mapping->buffer_info.handle,
1541 .size = mapping->image.data_size,
1547 dst,
src, &vaapi_unmap_to_drm_abh,
1552 dst->
data[0] = (uint8_t*)&mapping->drm_desc;
1559 vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1561 vaDestroyImage(hwctx->
display, mapping->image.image_id);
1571 #if VA_CHECK_VERSION(1, 1, 0)
1573 err = vaapi_map_to_drm_esh(hwfc, dst,
src,
flags);
1577 #if VA_CHECK_VERSION(0, 36, 0)
1578 return vaapi_map_to_drm_abh(hwfc, dst,
src,
flags);
1588 switch (
src->format) {
1591 return vaapi_map_from_drm(hwfc, dst,
src,
flags);
1604 return vaapi_map_to_drm(hwfc, dst,
src,
flags);
1620 if (priv->x11_display)
1621 XCloseDisplay(priv->x11_display);
1631 static void vaapi_device_log_error(
void *
context,
const char *
message)
1638 static void vaapi_device_log_info(
void *
context,
const char *
message)
1654 vaSetErrorCallback(display, &vaapi_device_log_error,
ctx);
1655 vaSetInfoCallback (display, &vaapi_device_log_info,
ctx);
1660 vas = vaInitialize(display, &major, &minor);
1661 if (vas != VA_STATUS_SUCCESS) {
1663 "connection: %d (%s).\n", vas, vaErrorStr(vas));
1667 "version %d.%d\n", major, minor);
1676 VADisplay display =
NULL;
1678 int try_drm, try_x11, try_win32, try_all;
1686 ctx->user_opaque = priv;
1691 try_all = try_drm = try_x11 = try_win32 = 0;
1692 if (!strcmp(ent->
value,
"drm")) {
1694 }
else if (!strcmp(ent->
value,
"x11")) {
1696 }
else if (!strcmp(ent->
value,
"win32")) {
1705 try_drm = HAVE_VAAPI_DRM;
1706 try_x11 = HAVE_VAAPI_X11;
1707 try_win32 = HAVE_VAAPI_WIN32;
1711 while (!display && try_drm) {
1717 priv->
drm_fd = open(device, O_RDWR);
1719 av_log(
ctx, loglevel,
"Failed to open %s as "
1720 "DRM device node.\n", device);
1725 int n, max_devices = 8;
1731 for (n = 0; n < max_devices; n++) {
1733 "/dev/dri/renderD%d", 128 + n);
1734 priv->
drm_fd = open(path, O_RDWR);
1737 "DRM render node for device %d.\n", n);
1744 "Failed to get DRM version for device %d.\n", n);
1749 if (kernel_driver) {
1750 if (strcmp(kernel_driver->
value,
info->name)) {
1752 "with non-matching kernel driver (%s).\n",
1754 drmFreeVersion(
info);
1760 "DRM render node for device %d, "
1761 "with matching kernel driver (%s).\n",
1763 drmFreeVersion(
info);
1766 }
else if (!strcmp(
info->name,
"vgem")) {
1768 "Skipping vgem node for device %d.\n", n);
1769 drmFreeVersion(
info);
1774 drmFreeVersion(
info);
1777 "DRM render node for device %d.\n", n);
1780 if (n >= max_devices)
1784 display = vaGetDisplayDRM(priv->
drm_fd);
1787 "from DRM device %s.\n", device);
1795 if (!display && try_x11) {
1797 priv->x11_display = XOpenDisplay(device);
1798 if (!priv->x11_display) {
1800 "%s.\n", XDisplayName(device));
1802 display = vaGetDisplay(priv->x11_display);
1805 "from X11 display %s.\n", XDisplayName(device));
1810 "X11 display %s.\n", XDisplayName(device));
1815 #if HAVE_VAAPI_WIN32
1816 if (!display && try_win32) {
1819 display = vaGetDisplayWin32(
NULL);
1821 IDXGIFactory2 *pDXGIFactory =
NULL;
1822 IDXGIAdapter *pAdapter =
NULL;
1824 HANDLE dxgi = dlopen(
"dxgi.dll", 0);
1831 if (!pfnCreateDXGIFactory) {
1842 if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2,
1843 (
void **)&pDXGIFactory))) {
1844 int adapter = atoi(device);
1845 if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
1848 DXGI_ADAPTER_DESC
desc;
1849 if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &
desc))) {
1851 "Using device %04x:%04x (%ls) - LUID %lu %ld.\n",
1853 desc.AdapterLuid.LowPart,
1854 desc.AdapterLuid.HighPart);
1855 display = vaGetDisplayWin32(&
desc.AdapterLuid);
1857 IDXGIAdapter_Release(pAdapter);
1859 IDXGIFactory2_Release(pDXGIFactory);
1868 "from Win32 display.\n");
1873 "Win32 display.\n");
1880 "device %s.\n", device);
1883 "any default device.\n");
1889 #if VA_CHECK_VERSION(0, 38, 0)
1891 vas = vaSetDriverName(display, ent->
value);
1892 if (vas != VA_STATUS_SUCCESS) {
1894 "%s: %d (%s).\n", ent->
value, vas, vaErrorStr(vas));
1895 vaTerminate(display);
1900 "supported with this VAAPI version.\n");
1918 if (src_hwctx->
fd < 0) {
1920 "device to derive a VA display from.\n");
1926 int node_type = drmGetNodeTypeFromFd(src_hwctx->
fd);
1928 if (node_type < 0) {
1930 "to refer to a DRM device.\n");
1933 if (node_type == DRM_NODE_RENDER) {
1936 render_node = drmGetRenderDeviceNameFromFd(src_hwctx->
fd);
1939 "because the device does not have an "
1940 "associated render node.\n");
1943 fd = open(render_node, O_RDWR);
1946 "because the associated render node "
1947 "could not be opened.\n");
1951 "in place of non-render DRM device.\n",
1964 if (fd != src_hwctx->
fd) {
1971 if (fd == src_hwctx->
fd) {
1979 ctx->user_opaque = priv;
1982 display = vaGetDisplayDRM(fd);