22 # include <va/va_x11.h>
25 # include <va/va_drm.h>
29 # include <va/va_drmcommon.h>
31 # include <drm_fourcc.h>
32 # ifndef DRM_FORMAT_MOD_INVALID
33 # define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
99 } VAAPIFormatDescriptor;
101 #define MAP(va, rt, av, swap_uv) { \
103 VA_RT_FORMAT_ ## rt, \
110 MAP(NV12, YUV420, NV12, 0),
111 #ifdef VA_FOURCC_I420
112 MAP(I420, YUV420, YUV420P, 0),
114 MAP(YV12, YUV420, YUV420P, 1),
115 MAP(IYUV, YUV420, YUV420P, 0),
116 MAP(422
H, YUV422, YUV422P, 0),
117 #ifdef VA_FOURCC_YV16
118 MAP(YV16, YUV422, YUV422P, 1),
120 MAP(UYVY, YUV422, UYVY422, 0),
121 MAP(YUY2, YUV422, YUYV422, 0),
122 #ifdef VA_FOURCC_Y210
123 MAP(Y210, YUV422_10, Y210, 0),
125 #ifdef VA_FOURCC_Y212
126 MAP(Y212, YUV422_12, Y212, 0),
128 MAP(411
P, YUV411, YUV411P, 0),
129 MAP(422
V, YUV422, YUV440P, 0),
130 MAP(444
P, YUV444, YUV444P, 0),
131 #ifdef VA_FOURCC_XYUV
132 MAP(XYUV, YUV444, VUYX, 0),
134 MAP(Y800, YUV400, GRAY8, 0),
135 #ifdef VA_FOURCC_P010
136 MAP(P010, YUV420_10BPP, P010, 0),
138 #ifdef VA_FOURCC_P012
139 MAP(P012, YUV420_12, P012, 0),
141 MAP(BGRA, RGB32, BGRA, 0),
142 MAP(BGRX, RGB32, BGR0, 0),
144 MAP(RGBX, RGB32, RGB0, 0),
145 #ifdef VA_FOURCC_ABGR
146 MAP(ABGR, RGB32, ABGR, 0),
147 MAP(XBGR, RGB32, 0BGR, 0),
149 MAP(ARGB, RGB32, ARGB, 0),
150 MAP(XRGB, RGB32, 0RGB, 0),
151 #ifdef VA_FOURCC_X2R10G10B10
152 MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
154 #ifdef VA_FOURCC_Y410
157 MAP(Y410, YUV444_10, XV30, 0),
159 #ifdef VA_FOURCC_Y412
162 MAP(Y412, YUV444_12, XV36, 0),
167 static const VAAPIFormatDescriptor *
177 static const VAAPIFormatDescriptor *
189 const VAAPIFormatDescriptor *
desc;
192 return desc->pix_fmt;
199 VAImageFormat **image_format)
204 for (
i = 0;
i <
ctx->nb_formats;
i++) {
207 *image_format = &
ctx->formats[
i].image_format;
215 const void *hwconfig,
221 VASurfaceAttrib *attr_list =
NULL;
225 int err,
i, j, attr_count, pix_fmt_count;
230 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
232 if (vas != VA_STATUS_SUCCESS) {
234 "%d (%s).\n", vas, vaErrorStr(vas));
239 attr_list =
av_malloc(attr_count *
sizeof(*attr_list));
245 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
246 attr_list, &attr_count);
247 if (vas != VA_STATUS_SUCCESS) {
249 "%d (%s).\n", vas, vaErrorStr(vas));
255 for (
i = 0;
i < attr_count;
i++) {
256 switch (attr_list[
i].
type) {
257 case VASurfaceAttribPixelFormat:
258 fourcc = attr_list[
i].value.value.i;
266 case VASurfaceAttribMinWidth:
267 constraints->
min_width = attr_list[
i].value.value.i;
269 case VASurfaceAttribMinHeight:
270 constraints->
min_height = attr_list[
i].value.value.i;
272 case VASurfaceAttribMaxWidth:
273 constraints->
max_width = attr_list[
i].value.value.i;
275 case VASurfaceAttribMaxHeight:
276 constraints->
max_height = attr_list[
i].value.value.i;
280 if (pix_fmt_count == 0) {
292 for (
i = j = 0;
i < attr_count;
i++) {
295 if (attr_list[
i].
type != VASurfaceAttribPixelFormat)
297 fourcc = attr_list[
i].value.value.i;
303 for (k = 0; k < j; k++) {
322 for (
i = j = 0;
i <
ctx->nb_formats;
i++) {
325 for (k = 0; k < j; k++) {
351 static const struct {
356 #if !VA_CHECK_VERSION(1, 0, 0)
359 "Intel i965 (Quick Sync)",
371 "Splitted-Desktop Systems VDPAU backend for VA-API",
380 VAImageFormat *image_list =
NULL;
382 const char *vendor_string;
383 int err,
i, image_count;
387 image_count = vaMaxNumImageFormats(hwctx->
display);
388 if (image_count <= 0) {
392 image_list =
av_malloc(image_count *
sizeof(*image_list));
397 vas = vaQueryImageFormats(hwctx->
display, image_list, &image_count);
398 if (vas != VA_STATUS_SUCCESS) {
409 for (
i = 0;
i < image_count;
i++) {
419 ctx->formats[
ctx->nb_formats].image_format = image_list[
i];
424 vendor_string = vaQueryVendorString(hwctx->
display);
436 if (strstr(vendor_string,
439 "as known nonstandard driver \"%s\", setting "
450 "nonstandard list, using standard behaviour.\n");
454 "assuming standard behaviour.\n");
477 VASurfaceID surface_id;
480 surface_id = (VASurfaceID)(uintptr_t)
data;
482 vas = vaDestroySurfaces(hwctx->
display, &surface_id, 1);
483 if (vas != VA_STATUS_SUCCESS) {
485 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
495 VASurfaceID surface_id;
503 vas = vaCreateSurfaces(hwctx->
display,
ctx->rt_format,
506 ctx->attributes,
ctx->nb_attributes);
507 if (vas != VA_STATUS_SUCCESS) {
509 "%d (%s).\n", vas, vaErrorStr(vas));
518 vaDestroySurfaces(hwctx->
display, &surface_id, 1);
538 const VAAPIFormatDescriptor *
desc;
539 VAImageFormat *expected_format;
541 VASurfaceID test_surface_id;
556 int need_pixel_format = 1;
558 if (avfc->
attributes[
i].type == VASurfaceAttribMemoryType)
559 need_memory_type = 0;
560 if (avfc->
attributes[
i].type == VASurfaceAttribPixelFormat)
561 need_pixel_format = 0;
567 sizeof(*
ctx->attributes));
568 if (!
ctx->attributes) {
575 if (need_memory_type) {
576 ctx->attributes[
i++] = (VASurfaceAttrib) {
577 .type = VASurfaceAttribMemoryType,
578 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
579 .value.type = VAGenericValueTypeInteger,
580 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
583 if (need_pixel_format) {
584 ctx->attributes[
i++] = (VASurfaceAttrib) {
585 .type = VASurfaceAttribPixelFormat,
586 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
587 .value.type = VAGenericValueTypeInteger,
588 .value.value.i =
desc->fourcc,
594 ctx->nb_attributes = 0;
597 ctx->rt_format =
desc->rt_format;
633 "user-configured buffer pool.\n");
641 "internal buffer pool.\n");
646 test_surface_id = (VASurfaceID)(uintptr_t)test_surface->
data;
648 ctx->derive_works = 0;
653 vas = vaDeriveImage(hwctx->
display, test_surface_id, &test_image);
654 if (vas == VA_STATUS_SUCCESS) {
655 if (expected_format->fourcc == test_image.format.fourcc) {
657 ctx->derive_works = 1;
660 "derived image format %08x does not match "
661 "expected format %08x.\n",
662 expected_format->fourcc, test_image.format.fourcc);
664 vaDestroyImage(hwctx->
display, test_image.image_id);
667 "deriving image does not work: "
668 "%d (%s).\n", vas, vaErrorStr(vas));
672 "image format is not supported.\n");
714 int i, k, sw_format_available;
716 sw_format_available = 0;
717 for (
i = 0;
i <
ctx->nb_formats;
i++) {
719 sw_format_available = 1;
726 if (sw_format_available) {
732 for (
i = 0;
i <
ctx->nb_formats;
i++) {
749 VASurfaceID surface_id;
752 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
755 vas = vaUnmapBuffer(hwctx->
display,
map->image.buf);
756 if (vas != VA_STATUS_SUCCESS) {
758 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
763 vas = vaPutImage(hwctx->
display, surface_id,
map->image.image_id,
766 if (vas != VA_STATUS_SUCCESS) {
768 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
772 vas = vaDestroyImage(hwctx->
display,
map->image.image_id);
773 if (vas != VA_STATUS_SUCCESS) {
775 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
786 VASurfaceID surface_id;
787 const VAAPIFormatDescriptor *
desc;
788 VAImageFormat *image_format;
791 void *address =
NULL;
794 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
818 map->image.image_id = VA_INVALID_ID;
820 vas = vaSyncSurface(hwctx->
display, surface_id);
821 if (vas != VA_STATUS_SUCCESS) {
823 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
837 vas = vaDeriveImage(hwctx->
display, surface_id, &
map->image);
838 if (vas != VA_STATUS_SUCCESS) {
840 "surface %#x: %d (%s).\n",
841 surface_id, vas, vaErrorStr(vas));
845 if (
map->image.format.fourcc != image_format->fourcc) {
847 "is in wrong format: expected %#08x, got %#08x.\n",
848 surface_id, image_format->fourcc,
map->image.format.fourcc);
854 vas = vaCreateImage(hwctx->
display, image_format,
856 if (vas != VA_STATUS_SUCCESS) {
858 "surface %#x: %d (%s).\n",
859 surface_id, vas, vaErrorStr(vas));
864 vas = vaGetImage(hwctx->
display, surface_id, 0, 0,
866 if (vas != VA_STATUS_SUCCESS) {
868 "surface %#x: %d (%s).\n",
869 surface_id, vas, vaErrorStr(vas));
876 vas = vaMapBuffer(hwctx->
display,
map->image.buf, &address);
877 if (vas != VA_STATUS_SUCCESS) {
879 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
892 for (
i = 0;
i <
map->image.num_planes;
i++) {
893 dst->
data[
i] = (uint8_t*)address +
map->image.offsets[
i];
898 if (
desc &&
desc->chroma_planes_swapped) {
908 vaUnmapBuffer(hwctx->
display,
map->image.buf);
909 if (
map->image.image_id != VA_INVALID_ID)
910 vaDestroyImage(hwctx->
display,
map->image.image_id);
959 map->format =
src->format;
966 map->height =
src->height;
1002 #define DRM_MAP(va, layers, ...) { \
1007 static const struct {
1009 int nb_layer_formats;
1011 } vaapi_drm_format_map[] = {
1012 #ifdef DRM_FORMAT_R8
1013 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
1014 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88),
1016 DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
1017 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
1018 DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1020 #if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
1021 DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1023 DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
1024 DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
1025 DRM_MAP(
RGBA, 1, DRM_FORMAT_ABGR8888),
1026 DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
1027 #ifdef VA_FOURCC_ABGR
1028 DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
1029 DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
1031 DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
1032 DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
1033 #if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
1034 DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
1036 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
1037 DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
1039 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
1040 DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
1050 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->
priv;
1054 vaDestroySurfaces(dst_dev->
display, &surface_id, 1);
1060 #if VA_CHECK_VERSION(1, 1, 0)
1070 const VAAPIFormatDescriptor *format_desc;
1071 VASurfaceID surface_id;
1072 VAStatus vas = VA_STATUS_SUCCESS;
1076 #
if !VA_CHECK_VERSION(1, 1, 0)
1077 unsigned long buffer_handle;
1078 VASurfaceAttribExternalBuffers buffer_desc;
1079 VASurfaceAttrib attrs[2] = {
1081 .type = VASurfaceAttribMemoryType,
1082 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1083 .value.type = VAGenericValueTypeInteger,
1084 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1087 .type = VASurfaceAttribExternalBufferDescriptor,
1088 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1089 .value.type = VAGenericValueTypePointer,
1090 .value.value.p = &buffer_desc,
1097 if (
desc->nb_objects != 1) {
1099 "made from a single DRM object.\n");
1105 if (
desc->nb_layers != vaapi_drm_format_map[
i].nb_layer_formats)
1107 for (j = 0; j <
desc->nb_layers; j++) {
1108 if (
desc->layers[j].format !=
1109 vaapi_drm_format_map[
i].layer_formats[j])
1112 if (j !=
desc->nb_layers)
1114 va_fourcc = vaapi_drm_format_map[
i].va_fourcc;
1124 "%08x.\n",
desc->objects[0].fd, va_fourcc);
1129 #if VA_CHECK_VERSION(1, 1, 0)
1133 VADRMPRIMESurfaceDescriptor prime_desc;
1134 VASurfaceAttrib prime_attrs[2] = {
1136 .type = VASurfaceAttribMemoryType,
1137 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1138 .value.type = VAGenericValueTypeInteger,
1139 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1142 .type = VASurfaceAttribExternalBufferDescriptor,
1143 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1144 .value.type = VAGenericValueTypePointer,
1145 .value.value.p = &prime_desc,
1148 prime_desc.fourcc = va_fourcc;
1149 prime_desc.width = src_fc->
width;
1150 prime_desc.height = src_fc->
height;
1151 prime_desc.num_objects =
desc->nb_objects;
1152 for (
i = 0;
i <
desc->nb_objects; ++
i) {
1153 prime_desc.objects[
i].fd =
desc->objects[
i].fd;
1154 prime_desc.objects[
i].size =
desc->objects[
i].size;
1155 prime_desc.objects[
i].drm_format_modifier =
1156 desc->objects[
i].format_modifier;
1159 prime_desc.num_layers =
desc->nb_layers;
1160 for (
i = 0;
i <
desc->nb_layers; ++
i) {
1161 prime_desc.layers[
i].drm_format =
desc->layers[
i].format;
1162 prime_desc.layers[
i].num_planes =
desc->layers[
i].nb_planes;
1163 for (j = 0; j <
desc->layers[
i].nb_planes; ++j) {
1164 prime_desc.layers[
i].object_index[j] =
1165 desc->layers[
i].planes[j].object_index;
1166 prime_desc.layers[
i].offset[j] =
desc->layers[
i].planes[j].offset;
1167 prime_desc.layers[
i].pitch[j] =
desc->layers[
i].planes[j].pitch;
1170 if (format_desc->chroma_planes_swapped &&
1171 desc->layers[
i].nb_planes == 3) {
1172 FFSWAP(uint32_t, prime_desc.layers[
i].pitch[1],
1173 prime_desc.layers[
i].pitch[2]);
1174 FFSWAP(uint32_t, prime_desc.layers[
i].offset[1],
1175 prime_desc.layers[
i].offset[2]);
1185 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1186 src->width,
src->height, &surface_id, 1,
1188 if (vas != VA_STATUS_SUCCESS)
1192 if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1194 unsigned long buffer_handle;
1195 VASurfaceAttribExternalBuffers buffer_desc;
1196 VASurfaceAttrib buffer_attrs[2] = {
1198 .type = VASurfaceAttribMemoryType,
1199 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1200 .value.type = VAGenericValueTypeInteger,
1201 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1204 .type = VASurfaceAttribExternalBufferDescriptor,
1205 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1206 .value.type = VAGenericValueTypePointer,
1207 .value.value.p = &buffer_desc,
1211 buffer_handle =
desc->objects[0].fd;
1212 buffer_desc.pixel_format = va_fourcc;
1213 buffer_desc.width = src_fc->
width;
1214 buffer_desc.height = src_fc->
height;
1215 buffer_desc.data_size =
desc->objects[0].size;
1216 buffer_desc.buffers = &buffer_handle;
1217 buffer_desc.num_buffers = 1;
1218 buffer_desc.flags = 0;
1221 for (
i = 0;
i <
desc->nb_layers;
i++) {
1222 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1223 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1224 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1228 buffer_desc.num_planes = k;
1230 if (format_desc->chroma_planes_swapped &&
1231 buffer_desc.num_planes == 3) {
1232 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1233 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1236 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1242 buffer_handle =
desc->objects[0].fd;
1243 buffer_desc.pixel_format = va_fourcc;
1244 buffer_desc.width = src_fc->
width;
1245 buffer_desc.height = src_fc->
height;
1246 buffer_desc.data_size =
desc->objects[0].size;
1247 buffer_desc.buffers = &buffer_handle;
1248 buffer_desc.num_buffers = 1;
1249 buffer_desc.flags = 0;
1252 for (
i = 0;
i <
desc->nb_layers;
i++) {
1253 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1254 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1255 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1259 buffer_desc.num_planes = k;
1261 if (format_desc->chroma_planes_swapped &&
1262 buffer_desc.num_planes == 3) {
1263 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1264 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1267 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1272 if (vas != VA_STATUS_SUCCESS) {
1274 "object: %d (%s).\n", vas, vaErrorStr(vas));
1280 &vaapi_unmap_from_drm,
1281 (
void*)(uintptr_t)surface_id);
1287 dst->
data[3] = (uint8_t*)(uintptr_t)surface_id;
1290 "surface %#x.\n",
desc->objects[0].fd, surface_id);
1295 #if VA_CHECK_VERSION(1, 1, 0)
1312 VASurfaceID surface_id;
1314 VADRMPRIMESurfaceDescriptor va_desc;
1316 uint32_t export_flags;
1319 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1321 export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1323 export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1325 export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1327 vas = vaExportSurfaceHandle(hwctx->
display, surface_id,
1328 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1329 export_flags, &va_desc);
1330 if (vas != VA_STATUS_SUCCESS) {
1331 if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1334 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1346 for (
i = 0;
i < va_desc.num_objects;
i++) {
1350 va_desc.objects[
i].drm_format_modifier;
1352 drm_desc->
nb_layers = va_desc.num_layers;
1353 for (
i = 0;
i < va_desc.num_layers;
i++) {
1356 for (j = 0; j < va_desc.layers[
i].num_planes; j++) {
1358 va_desc.layers[
i].object_index[j];
1360 va_desc.layers[
i].offset[j];
1362 va_desc.layers[
i].pitch[j];
1367 &vaapi_unmap_to_drm_esh, drm_desc);
1373 dst->
data[0] = (uint8_t*)drm_desc;
1378 for (
i = 0;
i < va_desc.num_objects;
i++)
1379 close(va_desc.objects[
i].fd);
1385 #if VA_CHECK_VERSION(0, 36, 0)
1386 typedef struct VAAPIDRMImageBufferMapping {
1388 VABufferInfo buffer_info;
1391 } VAAPIDRMImageBufferMapping;
1397 VAAPIDRMImageBufferMapping *mapping = hwmap->
priv;
1398 VASurfaceID surface_id;
1401 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
1408 vas = vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1409 if (vas != VA_STATUS_SUCCESS) {
1411 "handle of image %#x (derived from surface %#x): "
1412 "%d (%s).\n", mapping->image.buf, surface_id,
1413 vas, vaErrorStr(vas));
1416 vas = vaDestroyImage(hwctx->
display, mapping->image.image_id);
1417 if (vas != VA_STATUS_SUCCESS) {
1419 "derived from surface %#x: %d (%s).\n",
1420 surface_id, vas, vaErrorStr(vas));
1430 VAAPIDRMImageBufferMapping *mapping =
NULL;
1431 VASurfaceID surface_id;
1435 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1443 vas = vaDeriveImage(hwctx->
display, surface_id,
1445 if (vas != VA_STATUS_SUCCESS) {
1447 "surface %#x: %d (%s).\n",
1448 surface_id, vas, vaErrorStr(vas));
1454 if (vaapi_drm_format_map[
i].va_fourcc ==
1455 mapping->image.format.fourcc)
1460 "VAAPI format %#x.\n", mapping->image.format.fourcc);
1465 mapping->buffer_info.mem_type =
1466 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1468 mapping->drm_desc.nb_layers =
1469 vaapi_drm_format_map[
i].nb_layer_formats;
1470 if (mapping->drm_desc.nb_layers > 1) {
1471 if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1473 "expected format: got %d planes, but expected %d.\n",
1474 mapping->image.num_planes, mapping->drm_desc.nb_layers);
1479 for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1481 .format = vaapi_drm_format_map[
i].layer_formats[p],
1485 .offset = mapping->image.offsets[p],
1486 .pitch = mapping->image.pitches[p],
1491 mapping->drm_desc.layers[0].format =
1492 vaapi_drm_format_map[
i].layer_formats[0];
1493 mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1494 for (p = 0; p < mapping->image.num_planes; p++) {
1497 .offset = mapping->image.offsets[p],
1498 .pitch = mapping->image.pitches[p],
1503 vas = vaAcquireBufferHandle(hwctx->
display, mapping->image.buf,
1504 &mapping->buffer_info);
1505 if (vas != VA_STATUS_SUCCESS) {
1507 "handle from image %#x (derived from surface %#x): "
1508 "%d (%s).\n", mapping->image.buf, surface_id,
1509 vas, vaErrorStr(vas));
1515 mapping->buffer_info.handle);
1517 mapping->drm_desc.nb_objects = 1;
1519 .fd = mapping->buffer_info.handle,
1520 .size = mapping->image.data_size,
1526 dst,
src, &vaapi_unmap_to_drm_abh,
1531 dst->
data[0] = (uint8_t*)&mapping->drm_desc;
1538 vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1540 vaDestroyImage(hwctx->
display, mapping->image.image_id);
1550 #if VA_CHECK_VERSION(1, 1, 0)
1552 err = vaapi_map_to_drm_esh(hwfc, dst,
src,
flags);
1556 #if VA_CHECK_VERSION(0, 36, 0)
1557 return vaapi_map_to_drm_abh(hwfc, dst,
src,
flags);
1567 switch (
src->format) {
1570 return vaapi_map_from_drm(hwfc, dst,
src,
flags);
1583 return vaapi_map_to_drm(hwfc, dst,
src,
flags);
1599 if (priv->x11_display)
1600 XCloseDisplay(priv->x11_display);
1610 static void vaapi_device_log_error(
void *
context,
const char *
message)
1617 static void vaapi_device_log_info(
void *
context,
const char *
message)
1633 vaSetErrorCallback(display, &vaapi_device_log_error,
ctx);
1634 vaSetInfoCallback (display, &vaapi_device_log_info,
ctx);
1640 if (vas != VA_STATUS_SUCCESS) {
1642 "connection: %d (%s).\n", vas, vaErrorStr(vas));
1655 VADisplay display =
NULL;
1657 int try_drm, try_x11, try_all;
1665 ctx->user_opaque = priv;
1670 try_all = try_drm = try_x11 = 0;
1671 if (!strcmp(ent->
value,
"drm")) {
1673 }
else if (!strcmp(ent->
value,
"x11")) {
1682 try_drm = HAVE_VAAPI_DRM;
1683 try_x11 = HAVE_VAAPI_X11;
1687 while (!display && try_drm) {
1693 priv->
drm_fd = open(device, O_RDWR);
1695 av_log(
ctx, loglevel,
"Failed to open %s as "
1696 "DRM device node.\n", device);
1701 int n, max_devices = 8;
1707 for (n = 0; n < max_devices; n++) {
1709 "/dev/dri/renderD%d", 128 + n);
1710 priv->
drm_fd = open(path, O_RDWR);
1713 "DRM render node for device %d.\n", n);
1720 "Failed to get DRM version for device %d.\n", n);
1725 if (kernel_driver) {
1726 if (strcmp(kernel_driver->
value,
info->name)) {
1728 "with non-matching kernel driver (%s).\n",
1730 drmFreeVersion(
info);
1736 "DRM render node for device %d, "
1737 "with matching kernel driver (%s).\n",
1739 drmFreeVersion(
info);
1742 }
else if (!strcmp(
info->name,
"vgem")) {
1744 "Skipping vgem node for device %d.\n", n);
1745 drmFreeVersion(
info);
1750 drmFreeVersion(
info);
1753 "DRM render node for device %d.\n", n);
1756 if (n >= max_devices)
1760 display = vaGetDisplayDRM(priv->
drm_fd);
1763 "from DRM device %s.\n", device);
1771 if (!display && try_x11) {
1773 priv->x11_display = XOpenDisplay(device);
1774 if (!priv->x11_display) {
1776 "%s.\n", XDisplayName(device));
1778 display = vaGetDisplay(priv->x11_display);
1781 "from X11 display %s.\n", XDisplayName(device));
1786 "X11 display %s.\n", XDisplayName(device));
1794 "device %s.\n", device);
1797 "any default device.\n");
1803 #if VA_CHECK_VERSION(0, 38, 0)
1805 vas = vaSetDriverName(display, ent->
value);
1806 if (vas != VA_STATUS_SUCCESS) {
1808 "%s: %d (%s).\n", ent->
value, vas, vaErrorStr(vas));
1809 vaTerminate(display);
1814 "supported with this VAAPI version.\n");
1832 if (src_hwctx->
fd < 0) {
1834 "device to derive a VA display from.\n");
1840 int node_type = drmGetNodeTypeFromFd(src_hwctx->
fd);
1842 if (node_type < 0) {
1844 "to refer to a DRM device.\n");
1847 if (node_type == DRM_NODE_RENDER) {
1850 render_node = drmGetRenderDeviceNameFromFd(src_hwctx->
fd);
1853 "because the device does not have an "
1854 "associated render node.\n");
1857 fd = open(render_node, O_RDWR);
1860 "because the associated render node "
1861 "could not be opened.\n");
1865 "in place of non-render DRM device.\n",
1878 if (fd != src_hwctx->
fd) {
1885 if (fd == src_hwctx->
fd) {
1893 ctx->user_opaque = priv;
1896 display = vaGetDisplayDRM(fd);