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)
118 } VAAPIFormatDescriptor;
120 #define MAP(va, rt, av, swap_uv) { \
122 VA_RT_FORMAT_ ## rt, \
129 MAP(NV12, YUV420, NV12, 0),
130 #ifdef VA_FOURCC_I420
131 MAP(I420, YUV420, YUV420P, 0),
133 MAP(YV12, YUV420, YUV420P, 1),
134 MAP(IYUV, YUV420, YUV420P, 0),
135 MAP(422
H, YUV422, YUV422P, 0),
136 #ifdef VA_FOURCC_YV16
137 MAP(YV16, YUV422, YUV422P, 1),
139 MAP(UYVY, YUV422, UYVY422, 0),
140 MAP(YUY2, YUV422, YUYV422, 0),
141 #ifdef VA_FOURCC_Y210
142 MAP(Y210, YUV422_10, Y210, 0),
144 #ifdef VA_FOURCC_Y212
145 MAP(Y212, YUV422_12, Y212, 0),
147 MAP(411
P, YUV411, YUV411P, 0),
148 MAP(422
V, YUV422, YUV440P, 0),
149 MAP(444
P, YUV444, YUV444P, 0),
150 #ifdef VA_FOURCC_XYUV
151 MAP(XYUV, YUV444, VUYX, 0),
153 MAP(Y800, YUV400, GRAY8, 0),
154 #ifdef VA_FOURCC_P010
155 MAP(P010, YUV420_10BPP, P010, 0),
157 #ifdef VA_FOURCC_P012
158 MAP(P012, YUV420_12, P012, 0),
160 MAP(BGRA, RGB32, BGRA, 0),
161 MAP(BGRX, RGB32, BGR0, 0),
163 MAP(RGBX, RGB32, RGB0, 0),
164 #ifdef VA_FOURCC_ABGR
165 MAP(ABGR, RGB32, ABGR, 0),
166 MAP(XBGR, RGB32, 0BGR, 0),
168 MAP(ARGB, RGB32, ARGB, 0),
169 MAP(XRGB, RGB32, 0RGB, 0),
170 #ifdef VA_FOURCC_X2R10G10B10
171 MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
173 #ifdef VA_FOURCC_Y410
176 MAP(Y410, YUV444_10, XV30, 0),
178 #ifdef VA_FOURCC_Y412
181 MAP(Y412, YUV444_12, XV36, 0),
186 static const VAAPIFormatDescriptor *
196 static const VAAPIFormatDescriptor *
208 const VAAPIFormatDescriptor *
desc;
211 return desc->pix_fmt;
218 VAImageFormat **image_format)
223 for (
i = 0;
i <
ctx->nb_formats;
i++) {
226 *image_format = &
ctx->formats[
i].image_format;
234 const void *hwconfig,
240 VASurfaceAttrib *attr_list =
NULL;
244 int err,
i, j, attr_count, pix_fmt_count;
249 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
251 if (vas != VA_STATUS_SUCCESS) {
253 "%d (%s).\n", vas, vaErrorStr(vas));
258 attr_list =
av_malloc(attr_count *
sizeof(*attr_list));
264 vas = vaQuerySurfaceAttributes(hwctx->
display,
config->config_id,
265 attr_list, &attr_count);
266 if (vas != VA_STATUS_SUCCESS) {
268 "%d (%s).\n", vas, vaErrorStr(vas));
274 for (
i = 0;
i < attr_count;
i++) {
275 switch (attr_list[
i].
type) {
276 case VASurfaceAttribPixelFormat:
277 fourcc = attr_list[
i].value.value.i;
285 case VASurfaceAttribMinWidth:
286 constraints->
min_width = attr_list[
i].value.value.i;
288 case VASurfaceAttribMinHeight:
289 constraints->
min_height = attr_list[
i].value.value.i;
291 case VASurfaceAttribMaxWidth:
292 constraints->
max_width = attr_list[
i].value.value.i;
294 case VASurfaceAttribMaxHeight:
295 constraints->
max_height = attr_list[
i].value.value.i;
299 if (pix_fmt_count == 0) {
311 for (
i = j = 0;
i < attr_count;
i++) {
314 if (attr_list[
i].
type != VASurfaceAttribPixelFormat)
316 fourcc = attr_list[
i].value.value.i;
322 for (k = 0; k < j; k++) {
341 for (
i = j = 0;
i <
ctx->nb_formats;
i++) {
344 for (k = 0; k < j; k++) {
370 static const struct {
375 #if !VA_CHECK_VERSION(1, 0, 0)
378 "Intel i965 (Quick Sync)",
390 "Splitted-Desktop Systems VDPAU backend for VA-API",
399 VAImageFormat *image_list =
NULL;
401 const char *vendor_string;
402 int err,
i, image_count;
406 image_count = vaMaxNumImageFormats(hwctx->
display);
407 if (image_count <= 0) {
411 image_list =
av_malloc(image_count *
sizeof(*image_list));
416 vas = vaQueryImageFormats(hwctx->
display, image_list, &image_count);
417 if (vas != VA_STATUS_SUCCESS) {
428 for (
i = 0;
i < image_count;
i++) {
438 ctx->formats[
ctx->nb_formats].image_format = image_list[
i];
443 vendor_string = vaQueryVendorString(hwctx->
display);
455 if (strstr(vendor_string,
458 "as known nonstandard driver \"%s\", setting "
469 "nonstandard list, using standard behaviour.\n");
473 "assuming standard behaviour.\n");
496 VASurfaceID surface_id;
499 surface_id = (VASurfaceID)(uintptr_t)
data;
501 vas = vaDestroySurfaces(hwctx->
display, &surface_id, 1);
502 if (vas != VA_STATUS_SUCCESS) {
504 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
514 VASurfaceID surface_id;
522 vas = vaCreateSurfaces(hwctx->
display,
ctx->rt_format,
525 ctx->attributes,
ctx->nb_attributes);
526 if (vas != VA_STATUS_SUCCESS) {
528 "%d (%s).\n", vas, vaErrorStr(vas));
537 vaDestroySurfaces(hwctx->
display, &surface_id, 1);
557 const VAAPIFormatDescriptor *
desc;
558 VAImageFormat *expected_format;
560 VASurfaceID test_surface_id;
575 int need_pixel_format = 1;
577 if (avfc->
attributes[
i].type == VASurfaceAttribMemoryType)
578 need_memory_type = 0;
579 if (avfc->
attributes[
i].type == VASurfaceAttribPixelFormat)
580 need_pixel_format = 0;
586 sizeof(*
ctx->attributes));
587 if (!
ctx->attributes) {
594 if (need_memory_type) {
595 ctx->attributes[
i++] = (VASurfaceAttrib) {
596 .type = VASurfaceAttribMemoryType,
597 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
598 .value.type = VAGenericValueTypeInteger,
599 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
602 if (need_pixel_format) {
603 ctx->attributes[
i++] = (VASurfaceAttrib) {
604 .type = VASurfaceAttribPixelFormat,
605 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
606 .value.type = VAGenericValueTypeInteger,
607 .value.value.i =
desc->fourcc,
613 ctx->nb_attributes = 0;
616 ctx->rt_format =
desc->rt_format;
652 "user-configured buffer pool.\n");
660 "internal buffer pool.\n");
665 test_surface_id = (VASurfaceID)(uintptr_t)test_surface->
data;
667 ctx->derive_works = 0;
672 vas = vaDeriveImage(hwctx->
display, test_surface_id, &test_image);
673 if (vas == VA_STATUS_SUCCESS) {
674 if (expected_format->fourcc == test_image.format.fourcc) {
676 ctx->derive_works = 1;
679 "derived image format %08x does not match "
680 "expected format %08x.\n",
681 expected_format->fourcc, test_image.format.fourcc);
683 vaDestroyImage(hwctx->
display, test_image.image_id);
686 "deriving image does not work: "
687 "%d (%s).\n", vas, vaErrorStr(vas));
691 "image format is not supported.\n");
733 int i, k, sw_format_available;
735 sw_format_available = 0;
736 for (
i = 0;
i <
ctx->nb_formats;
i++) {
738 sw_format_available = 1;
745 if (sw_format_available) {
751 for (
i = 0;
i <
ctx->nb_formats;
i++) {
768 VASurfaceID surface_id;
771 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
774 vas = vaUnmapBuffer(hwctx->
display,
map->image.buf);
775 if (vas != VA_STATUS_SUCCESS) {
777 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
782 vas = vaPutImage(hwctx->
display, surface_id,
map->image.image_id,
785 if (vas != VA_STATUS_SUCCESS) {
787 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
791 vas = vaDestroyImage(hwctx->
display,
map->image.image_id);
792 if (vas != VA_STATUS_SUCCESS) {
794 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
805 VASurfaceID surface_id;
806 const VAAPIFormatDescriptor *
desc;
807 VAImageFormat *image_format;
810 void *address =
NULL;
813 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
837 map->image.image_id = VA_INVALID_ID;
839 vas = vaSyncSurface(hwctx->
display, surface_id);
840 if (vas != VA_STATUS_SUCCESS) {
842 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
856 vas = vaDeriveImage(hwctx->
display, surface_id, &
map->image);
857 if (vas != VA_STATUS_SUCCESS) {
859 "surface %#x: %d (%s).\n",
860 surface_id, vas, vaErrorStr(vas));
864 if (
map->image.format.fourcc != image_format->fourcc) {
866 "is in wrong format: expected %#08x, got %#08x.\n",
867 surface_id, image_format->fourcc,
map->image.format.fourcc);
873 vas = vaCreateImage(hwctx->
display, image_format,
875 if (vas != VA_STATUS_SUCCESS) {
877 "surface %#x: %d (%s).\n",
878 surface_id, vas, vaErrorStr(vas));
883 vas = vaGetImage(hwctx->
display, surface_id, 0, 0,
885 if (vas != VA_STATUS_SUCCESS) {
887 "surface %#x: %d (%s).\n",
888 surface_id, vas, vaErrorStr(vas));
895 vas = vaMapBuffer(hwctx->
display,
map->image.buf, &address);
896 if (vas != VA_STATUS_SUCCESS) {
898 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
911 for (
i = 0;
i <
map->image.num_planes;
i++) {
912 dst->
data[
i] = (uint8_t*)address +
map->image.offsets[
i];
917 if (
desc &&
desc->chroma_planes_swapped) {
927 vaUnmapBuffer(hwctx->
display,
map->image.buf);
928 if (
map->image.image_id != VA_INVALID_ID)
929 vaDestroyImage(hwctx->
display,
map->image.image_id);
978 map->format =
src->format;
985 map->height =
src->height;
1021 #define DRM_MAP(va, layers, ...) { \
1026 static const struct {
1028 int nb_layer_formats;
1030 } vaapi_drm_format_map[] = {
1031 #ifdef DRM_FORMAT_R8
1032 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
1033 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88),
1035 DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
1036 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
1037 DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1039 #if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
1040 DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1042 DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
1043 DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
1044 DRM_MAP(
RGBA, 1, DRM_FORMAT_ABGR8888),
1045 DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
1046 #ifdef VA_FOURCC_ABGR
1047 DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
1048 DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
1050 DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
1051 DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
1052 #if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
1053 DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
1055 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
1056 DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
1058 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
1059 DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
1061 #if defined(VA_FOURCC_X2R10G10B10) && defined(DRM_FORMAT_XRGB2101010)
1062 DRM_MAP(X2R10G10B10, 1, DRM_FORMAT_XRGB2101010),
1072 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->
priv;
1076 vaDestroySurfaces(dst_dev->
display, &surface_id, 1);
1082 #if VA_CHECK_VERSION(1, 1, 0)
1092 const VAAPIFormatDescriptor *format_desc;
1093 VASurfaceID surface_id;
1094 VAStatus vas = VA_STATUS_SUCCESS;
1098 #
if !VA_CHECK_VERSION(1, 1, 0)
1099 unsigned long buffer_handle;
1100 VASurfaceAttribExternalBuffers buffer_desc;
1101 VASurfaceAttrib attrs[2] = {
1103 .type = VASurfaceAttribMemoryType,
1104 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1105 .value.type = VAGenericValueTypeInteger,
1106 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1109 .type = VASurfaceAttribExternalBufferDescriptor,
1110 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1111 .value.type = VAGenericValueTypePointer,
1112 .value.value.p = &buffer_desc,
1119 if (
desc->nb_objects != 1) {
1121 "made from a single DRM object.\n");
1127 if (
desc->nb_layers != vaapi_drm_format_map[
i].nb_layer_formats)
1129 for (j = 0; j <
desc->nb_layers; j++) {
1130 if (
desc->layers[j].format !=
1131 vaapi_drm_format_map[
i].layer_formats[j])
1134 if (j !=
desc->nb_layers)
1136 va_fourcc = vaapi_drm_format_map[
i].va_fourcc;
1146 "%08x.\n",
desc->objects[0].fd, va_fourcc);
1151 #if VA_CHECK_VERSION(1, 1, 0)
1155 VADRMPRIMESurfaceDescriptor prime_desc;
1156 VASurfaceAttrib prime_attrs[2] = {
1158 .type = VASurfaceAttribMemoryType,
1159 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1160 .value.type = VAGenericValueTypeInteger,
1161 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1164 .type = VASurfaceAttribExternalBufferDescriptor,
1165 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1166 .value.type = VAGenericValueTypePointer,
1167 .value.value.p = &prime_desc,
1170 prime_desc.fourcc = va_fourcc;
1171 prime_desc.width = src_fc->
width;
1172 prime_desc.height = src_fc->
height;
1173 prime_desc.num_objects =
desc->nb_objects;
1174 for (
i = 0;
i <
desc->nb_objects; ++
i) {
1175 prime_desc.objects[
i].fd =
desc->objects[
i].fd;
1176 prime_desc.objects[
i].size =
desc->objects[
i].size;
1177 prime_desc.objects[
i].drm_format_modifier =
1178 desc->objects[
i].format_modifier;
1181 prime_desc.num_layers =
desc->nb_layers;
1182 for (
i = 0;
i <
desc->nb_layers; ++
i) {
1183 prime_desc.layers[
i].drm_format =
desc->layers[
i].format;
1184 prime_desc.layers[
i].num_planes =
desc->layers[
i].nb_planes;
1185 for (j = 0; j <
desc->layers[
i].nb_planes; ++j) {
1186 prime_desc.layers[
i].object_index[j] =
1187 desc->layers[
i].planes[j].object_index;
1188 prime_desc.layers[
i].offset[j] =
desc->layers[
i].planes[j].offset;
1189 prime_desc.layers[
i].pitch[j] =
desc->layers[
i].planes[j].pitch;
1192 if (format_desc->chroma_planes_swapped &&
1193 desc->layers[
i].nb_planes == 3) {
1194 FFSWAP(uint32_t, prime_desc.layers[
i].pitch[1],
1195 prime_desc.layers[
i].pitch[2]);
1196 FFSWAP(uint32_t, prime_desc.layers[
i].offset[1],
1197 prime_desc.layers[
i].offset[2]);
1207 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1208 src->width,
src->height, &surface_id, 1,
1210 if (vas != VA_STATUS_SUCCESS)
1214 if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1216 uintptr_t buffer_handle;
1217 VASurfaceAttribExternalBuffers buffer_desc;
1218 VASurfaceAttrib buffer_attrs[2] = {
1220 .type = VASurfaceAttribMemoryType,
1221 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1222 .value.type = VAGenericValueTypeInteger,
1223 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1226 .type = VASurfaceAttribExternalBufferDescriptor,
1227 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1228 .value.type = VAGenericValueTypePointer,
1229 .value.value.p = &buffer_desc,
1233 buffer_handle =
desc->objects[0].fd;
1234 buffer_desc.pixel_format = va_fourcc;
1235 buffer_desc.width = src_fc->
width;
1236 buffer_desc.height = src_fc->
height;
1237 buffer_desc.data_size =
desc->objects[0].size;
1238 buffer_desc.buffers = &buffer_handle;
1239 buffer_desc.num_buffers = 1;
1240 buffer_desc.flags = 0;
1243 for (
i = 0;
i <
desc->nb_layers;
i++) {
1244 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1245 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1246 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1250 buffer_desc.num_planes = k;
1252 if (format_desc->chroma_planes_swapped &&
1253 buffer_desc.num_planes == 3) {
1254 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1255 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1258 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1264 buffer_handle =
desc->objects[0].fd;
1265 buffer_desc.pixel_format = va_fourcc;
1266 buffer_desc.width = src_fc->
width;
1267 buffer_desc.height = src_fc->
height;
1268 buffer_desc.data_size =
desc->objects[0].size;
1269 buffer_desc.buffers = &buffer_handle;
1270 buffer_desc.num_buffers = 1;
1271 buffer_desc.flags = 0;
1274 for (
i = 0;
i <
desc->nb_layers;
i++) {
1275 for (j = 0; j <
desc->layers[
i].nb_planes; j++) {
1276 buffer_desc.pitches[k] =
desc->layers[
i].planes[j].pitch;
1277 buffer_desc.offsets[k] =
desc->layers[
i].planes[j].offset;
1281 buffer_desc.num_planes = k;
1283 if (format_desc->chroma_planes_swapped &&
1284 buffer_desc.num_planes == 3) {
1285 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1286 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1289 vas = vaCreateSurfaces(dst_dev->
display, format_desc->rt_format,
1294 if (vas != VA_STATUS_SUCCESS) {
1296 "object: %d (%s).\n", vas, vaErrorStr(vas));
1302 &vaapi_unmap_from_drm,
1303 (
void*)(uintptr_t)surface_id);
1309 dst->
data[3] = (uint8_t*)(uintptr_t)surface_id;
1312 "surface %#x.\n",
desc->objects[0].fd, surface_id);
1317 #if VA_CHECK_VERSION(1, 1, 0)
1334 VASurfaceID surface_id;
1336 VADRMPRIMESurfaceDescriptor va_desc;
1338 uint32_t export_flags;
1341 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1343 export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1345 export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1347 vas = vaSyncSurface(hwctx->
display, surface_id);
1348 if (vas != VA_STATUS_SUCCESS) {
1350 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
1356 export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1358 vas = vaExportSurfaceHandle(hwctx->
display, surface_id,
1359 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1360 export_flags, &va_desc);
1361 if (vas != VA_STATUS_SUCCESS) {
1362 if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1365 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1377 for (
i = 0;
i < va_desc.num_objects;
i++) {
1381 va_desc.objects[
i].drm_format_modifier;
1383 drm_desc->
nb_layers = va_desc.num_layers;
1384 for (
i = 0;
i < va_desc.num_layers;
i++) {
1387 for (j = 0; j < va_desc.layers[
i].num_planes; j++) {
1389 va_desc.layers[
i].object_index[j];
1391 va_desc.layers[
i].offset[j];
1393 va_desc.layers[
i].pitch[j];
1398 &vaapi_unmap_to_drm_esh, drm_desc);
1404 dst->
data[0] = (uint8_t*)drm_desc;
1409 for (
i = 0;
i < va_desc.num_objects;
i++)
1410 close(va_desc.objects[
i].fd);
1416 #if VA_CHECK_VERSION(0, 36, 0)
1417 typedef struct VAAPIDRMImageBufferMapping {
1419 VABufferInfo buffer_info;
1422 } VAAPIDRMImageBufferMapping;
1428 VAAPIDRMImageBufferMapping *mapping = hwmap->
priv;
1429 VASurfaceID surface_id;
1432 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
1439 vas = vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1440 if (vas != VA_STATUS_SUCCESS) {
1442 "handle of image %#x (derived from surface %#x): "
1443 "%d (%s).\n", mapping->image.buf, surface_id,
1444 vas, vaErrorStr(vas));
1447 vas = vaDestroyImage(hwctx->
display, mapping->image.image_id);
1448 if (vas != VA_STATUS_SUCCESS) {
1450 "derived from surface %#x: %d (%s).\n",
1451 surface_id, vas, vaErrorStr(vas));
1461 VAAPIDRMImageBufferMapping *mapping =
NULL;
1462 VASurfaceID surface_id;
1466 surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
1474 vas = vaDeriveImage(hwctx->
display, surface_id,
1476 if (vas != VA_STATUS_SUCCESS) {
1478 "surface %#x: %d (%s).\n",
1479 surface_id, vas, vaErrorStr(vas));
1485 if (vaapi_drm_format_map[
i].va_fourcc ==
1486 mapping->image.format.fourcc)
1491 "VAAPI format %#x.\n", mapping->image.format.fourcc);
1496 mapping->buffer_info.mem_type =
1497 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1499 mapping->drm_desc.nb_layers =
1500 vaapi_drm_format_map[
i].nb_layer_formats;
1501 if (mapping->drm_desc.nb_layers > 1) {
1502 if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1504 "expected format: got %d planes, but expected %d.\n",
1505 mapping->image.num_planes, mapping->drm_desc.nb_layers);
1510 for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1512 .format = vaapi_drm_format_map[
i].layer_formats[p],
1516 .offset = mapping->image.offsets[p],
1517 .pitch = mapping->image.pitches[p],
1522 mapping->drm_desc.layers[0].format =
1523 vaapi_drm_format_map[
i].layer_formats[0];
1524 mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1525 for (p = 0; p < mapping->image.num_planes; p++) {
1528 .offset = mapping->image.offsets[p],
1529 .pitch = mapping->image.pitches[p],
1534 vas = vaAcquireBufferHandle(hwctx->
display, mapping->image.buf,
1535 &mapping->buffer_info);
1536 if (vas != VA_STATUS_SUCCESS) {
1538 "handle from image %#x (derived from surface %#x): "
1539 "%d (%s).\n", mapping->image.buf, surface_id,
1540 vas, vaErrorStr(vas));
1546 mapping->buffer_info.handle);
1548 mapping->drm_desc.nb_objects = 1;
1550 .fd = mapping->buffer_info.handle,
1551 .size = mapping->image.data_size,
1557 dst,
src, &vaapi_unmap_to_drm_abh,
1562 dst->
data[0] = (uint8_t*)&mapping->drm_desc;
1569 vaReleaseBufferHandle(hwctx->
display, mapping->image.buf);
1571 vaDestroyImage(hwctx->
display, mapping->image.image_id);
1581 #if VA_CHECK_VERSION(1, 1, 0)
1583 err = vaapi_map_to_drm_esh(hwfc, dst,
src,
flags);
1587 #if VA_CHECK_VERSION(0, 36, 0)
1588 return vaapi_map_to_drm_abh(hwfc, dst,
src,
flags);
1598 switch (
src->format) {
1601 return vaapi_map_from_drm(hwfc, dst,
src,
flags);
1614 return vaapi_map_to_drm(hwfc, dst,
src,
flags);
1630 if (priv->x11_display)
1631 XCloseDisplay(priv->x11_display);
1641 static void vaapi_device_log_error(
void *
context,
const char *
message)
1648 static void vaapi_device_log_info(
void *
context,
const char *
message)
1664 vaSetErrorCallback(display, &vaapi_device_log_error,
ctx);
1665 vaSetInfoCallback (display, &vaapi_device_log_info,
ctx);
1670 vas = vaInitialize(display, &major, &minor);
1671 if (vas != VA_STATUS_SUCCESS) {
1673 "connection: %d (%s).\n", vas, vaErrorStr(vas));
1677 "version %d.%d\n", major, minor);
1686 VADisplay display =
NULL;
1688 int try_drm, try_x11, try_win32, try_all;
1696 ctx->user_opaque = priv;
1701 try_all = try_drm = try_x11 = try_win32 = 0;
1702 if (!strcmp(ent->
value,
"drm")) {
1704 }
else if (!strcmp(ent->
value,
"x11")) {
1706 }
else if (!strcmp(ent->
value,
"win32")) {
1715 try_drm = HAVE_VAAPI_DRM;
1716 try_x11 = HAVE_VAAPI_X11;
1717 try_win32 = HAVE_VAAPI_WIN32;
1721 while (!display && try_drm) {
1727 priv->
drm_fd = open(device, O_RDWR);
1729 av_log(
ctx, loglevel,
"Failed to open %s as "
1730 "DRM device node.\n", device);
1735 int n, max_devices = 8;
1741 for (n = 0; n < max_devices; n++) {
1743 "/dev/dri/renderD%d", 128 + n);
1744 priv->
drm_fd = open(path, O_RDWR);
1746 if (errno == ENOENT) {
1747 if (n != max_devices - 1) {
1749 "No render device %s, try next device for "
1750 "DRM render node.\n", path);
1755 "for DRM render node.\n");
1758 "DRM render node for device %d.\n", n);
1765 "Failed to get DRM version for device %d.\n", n);
1770 if (kernel_driver) {
1771 if (strcmp(kernel_driver->
value,
info->name)) {
1773 "with non-matching kernel driver (%s).\n",
1775 drmFreeVersion(
info);
1781 "DRM render node for device %d, "
1782 "with matching kernel driver (%s).\n",
1784 drmFreeVersion(
info);
1787 }
else if (!strcmp(
info->name,
"vgem")) {
1789 "Skipping vgem node for device %d.\n", n);
1790 drmFreeVersion(
info);
1795 drmFreeVersion(
info);
1798 "DRM render node for device %d.\n", n);
1801 if (n >= max_devices)
1805 display = vaGetDisplayDRM(priv->
drm_fd);
1808 "from DRM device %s.\n", device);
1816 if (!display && try_x11) {
1818 priv->x11_display = XOpenDisplay(device);
1819 if (!priv->x11_display) {
1821 "%s.\n", XDisplayName(device));
1823 display = vaGetDisplay(priv->x11_display);
1826 "from X11 display %s.\n", XDisplayName(device));
1831 "X11 display %s.\n", XDisplayName(device));
1836 #if HAVE_VAAPI_WIN32
1837 if (!display && try_win32) {
1840 display = vaGetDisplayWin32(
NULL);
1842 IDXGIFactory2 *pDXGIFactory =
NULL;
1843 IDXGIAdapter *pAdapter =
NULL;
1845 HANDLE dxgi = dlopen(
"dxgi.dll", 0);
1852 if (!pfnCreateDXGIFactory) {
1863 if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2,
1864 (
void **)&pDXGIFactory))) {
1865 int adapter = atoi(device);
1866 if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
1869 DXGI_ADAPTER_DESC
desc;
1870 if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &
desc))) {
1872 "Using device %04x:%04x (%ls) - LUID %lu %ld.\n",
1874 desc.AdapterLuid.LowPart,
1875 desc.AdapterLuid.HighPart);
1876 display = vaGetDisplayWin32(&
desc.AdapterLuid);
1878 IDXGIAdapter_Release(pAdapter);
1880 IDXGIFactory2_Release(pDXGIFactory);
1889 "from Win32 display.\n");
1894 "Win32 display.\n");
1901 "device %s.\n", device);
1904 "any default device.\n");
1910 #if VA_CHECK_VERSION(0, 38, 0)
1912 vas = vaSetDriverName(display, ent->
value);
1913 if (vas != VA_STATUS_SUCCESS) {
1915 "%s: %d (%s).\n", ent->
value, vas, vaErrorStr(vas));
1916 vaTerminate(display);
1921 "supported with this VAAPI version.\n");
1939 if (src_hwctx->
fd < 0) {
1941 "device to derive a VA display from.\n");
1947 int node_type = drmGetNodeTypeFromFd(src_hwctx->
fd);
1949 if (node_type < 0) {
1951 "to refer to a DRM device.\n");
1954 if (node_type == DRM_NODE_RENDER) {
1957 render_node = drmGetRenderDeviceNameFromFd(src_hwctx->
fd);
1960 "because the device does not have an "
1961 "associated render node.\n");
1964 fd = open(render_node, O_RDWR);
1967 "because the associated render node "
1968 "could not be opened.\n");
1972 "in place of non-render DRM device.\n",
1985 if (fd != src_hwctx->
fd) {
1992 if (fd == src_hwctx->
fd) {
2000 ctx->user_opaque = priv;
2003 display = vaGetDisplayDRM(fd);