FFmpeg
hwcontext_vaapi.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "config.h"
20 
21 #if HAVE_VAAPI_WIN32
22 # include <windows.h>
23 #define COBJMACROS
24 # include <initguid.h>
25 # include <dxgi1_2.h>
26 # include "compat/w32dlfcn.h"
27 # include <va/va_win32.h>
28 typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
29 #endif
30 #if HAVE_VAAPI_X11
31 # include <va/va_x11.h>
32 #endif
33 #if HAVE_VAAPI_DRM
34 # include <va/va_drm.h>
35 #endif
36 
37 #if CONFIG_LIBDRM
38 # include <va/va_drmcommon.h>
39 # include <xf86drm.h>
40 # include <drm_fourcc.h>
41 # ifndef DRM_FORMAT_MOD_INVALID
42 # define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
43 # endif
44 #endif
45 
46 #include <fcntl.h>
47 #if HAVE_UNISTD_H
48 # include <unistd.h>
49 #endif
50 
51 
52 #include "avassert.h"
53 #include "buffer.h"
54 #include "common.h"
55 #include "hwcontext.h"
56 #include "hwcontext_drm.h"
57 #include "hwcontext_internal.h"
58 #include "hwcontext_vaapi.h"
59 #include "mem.h"
60 #include "pixdesc.h"
61 #include "pixfmt.h"
62 
63 
64 typedef struct VAAPIDevicePriv {
65 #if HAVE_VAAPI_X11
66  Display *x11_display;
67 #endif
68 
69  int drm_fd;
71 
72 typedef struct VAAPISurfaceFormat {
74  VAImageFormat image_format;
76 
77 typedef struct VAAPIDeviceContext {
78  /**
79  * The public AVVAAPIDeviceContext. See hwcontext_vaapi.h for it.
80  */
82 
83  // Surface formats which can be used with this device.
87 
88 typedef struct VAAPIFramesContext {
89  /**
90  * The public AVVAAPIFramesContext. See hwcontext_vaapi.h for it.
91  */
93 
94  // Surface attributes set at create time.
95  VASurfaceAttrib *attributes;
97  // RT format of the underlying surface (Intel driver ignores this anyway).
98  unsigned int rt_format;
99  // Whether vaDeriveImage works.
101  // Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for
102  // surface imports.
105 
106 typedef struct VAAPIMapping {
107  // Handle to the derived or copied image which is mapped.
108  VAImage image;
109  // The mapping flags actually used.
110  int flags;
111 } VAAPIMapping;
112 
113 typedef struct VAAPIFormat {
114  unsigned int fourcc;
115  unsigned int rt_format;
118 } VAAPIFormatDescriptor;
119 
120 #define MAP(va, rt, av, swap_uv) { \
121  VA_FOURCC_ ## va, \
122  VA_RT_FORMAT_ ## rt, \
123  AV_PIX_FMT_ ## av, \
124  swap_uv, \
125  }
126 // The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V
127 // plane swap cases. The frame handling below tries to hide these.
128 static const VAAPIFormatDescriptor vaapi_format_map[] = {
129  MAP(NV12, YUV420, NV12, 0),
130 #ifdef VA_FOURCC_I420
131  MAP(I420, YUV420, YUV420P, 0),
132 #endif
133  MAP(YV12, YUV420, YUV420P, 1),
134  MAP(IYUV, YUV420, YUV420P, 0),
135  MAP(422H, YUV422, YUV422P, 0),
136 #ifdef VA_FOURCC_YV16
137  MAP(YV16, YUV422, YUV422P, 1),
138 #endif
139  MAP(UYVY, YUV422, UYVY422, 0),
140  MAP(YUY2, YUV422, YUYV422, 0),
141 #ifdef VA_FOURCC_Y210
142  MAP(Y210, YUV422_10, Y210, 0),
143 #endif
144 #ifdef VA_FOURCC_Y212
145  MAP(Y212, YUV422_12, Y212, 0),
146 #endif
147  MAP(411P, YUV411, YUV411P, 0),
148  MAP(422V, YUV422, YUV440P, 0),
149  MAP(444P, YUV444, YUV444P, 0),
150 #ifdef VA_FOURCC_XYUV
151  MAP(XYUV, YUV444, VUYX, 0),
152 #endif
153  MAP(Y800, YUV400, GRAY8, 0),
154 #ifdef VA_FOURCC_P010
155  MAP(P010, YUV420_10BPP, P010, 0),
156 #endif
157 #ifdef VA_FOURCC_P012
158  MAP(P012, YUV420_12, P012, 0),
159 #endif
160  MAP(BGRA, RGB32, BGRA, 0),
161  MAP(BGRX, RGB32, BGR0, 0),
162  MAP(RGBA, RGB32, RGBA, 0),
163  MAP(RGBX, RGB32, RGB0, 0),
164 #ifdef VA_FOURCC_ABGR
165  MAP(ABGR, RGB32, ABGR, 0),
166  MAP(XBGR, RGB32, 0BGR, 0),
167 #endif
168  MAP(ARGB, RGB32, ARGB, 0),
169  MAP(XRGB, RGB32, 0RGB, 0),
170 #ifdef VA_FOURCC_X2R10G10B10
171  MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
172 #endif
173 #ifdef VA_FOURCC_Y410
174  // libva doesn't include a fourcc for XV30 and the driver only declares
175  // support for Y410, so we must fudge the mapping here.
176  MAP(Y410, YUV444_10, XV30, 0),
177 #endif
178 #ifdef VA_FOURCC_Y412
179  // libva doesn't include a fourcc for XV36 and the driver only declares
180  // support for Y412, so we must fudge the mapping here.
181  MAP(Y412, YUV444_12, XV36, 0),
182 #endif
183 };
184 #undef MAP
185 
186 static const VAAPIFormatDescriptor *
188 {
189  int i;
190  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
192  return &vaapi_format_map[i];
193  return NULL;
194 }
195 
196 static const VAAPIFormatDescriptor *
198 {
199  int i;
200  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
202  return &vaapi_format_map[i];
203  return NULL;
204 }
205 
207 {
208  const VAAPIFormatDescriptor *desc;
210  if (desc)
211  return desc->pix_fmt;
212  else
213  return AV_PIX_FMT_NONE;
214 }
215 
217  enum AVPixelFormat pix_fmt,
218  VAImageFormat **image_format)
219 {
220  VAAPIDeviceContext *ctx = hwdev->hwctx;
221  int i;
222 
223  for (i = 0; i < ctx->nb_formats; i++) {
224  if (ctx->formats[i].pix_fmt == pix_fmt) {
225  if (image_format)
226  *image_format = &ctx->formats[i].image_format;
227  return 0;
228  }
229  }
230  return AVERROR(ENOSYS);
231 }
232 
234  const void *hwconfig,
235  AVHWFramesConstraints *constraints)
236 {
237  VAAPIDeviceContext *ctx = hwdev->hwctx;
238  AVVAAPIDeviceContext *hwctx = &ctx->p;
239  const AVVAAPIHWConfig *config = hwconfig;
240  VASurfaceAttrib *attr_list = NULL;
241  VAStatus vas;
242  enum AVPixelFormat pix_fmt;
243  unsigned int fourcc;
244  int err, i, j, attr_count, pix_fmt_count;
245 
246  if (config &&
248  attr_count = 0;
249  vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
250  0, &attr_count);
251  if (vas != VA_STATUS_SUCCESS) {
252  av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
253  "%d (%s).\n", vas, vaErrorStr(vas));
254  err = AVERROR(ENOSYS);
255  goto fail;
256  }
257 
258  attr_list = av_malloc(attr_count * sizeof(*attr_list));
259  if (!attr_list) {
260  err = AVERROR(ENOMEM);
261  goto fail;
262  }
263 
264  vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
265  attr_list, &attr_count);
266  if (vas != VA_STATUS_SUCCESS) {
267  av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
268  "%d (%s).\n", vas, vaErrorStr(vas));
269  err = AVERROR(ENOSYS);
270  goto fail;
271  }
272 
273  pix_fmt_count = 0;
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;
279  if (pix_fmt != AV_PIX_FMT_NONE) {
280  ++pix_fmt_count;
281  } else {
282  // Something unsupported - ignore.
283  }
284  break;
285  case VASurfaceAttribMinWidth:
286  constraints->min_width = attr_list[i].value.value.i;
287  break;
288  case VASurfaceAttribMinHeight:
289  constraints->min_height = attr_list[i].value.value.i;
290  break;
291  case VASurfaceAttribMaxWidth:
292  constraints->max_width = attr_list[i].value.value.i;
293  break;
294  case VASurfaceAttribMaxHeight:
295  constraints->max_height = attr_list[i].value.value.i;
296  break;
297  }
298  }
299  if (pix_fmt_count == 0) {
300  // Nothing usable found. Presumably there exists something which
301  // works, so leave the set null to indicate unknown.
302  constraints->valid_sw_formats = NULL;
303  } else {
304  constraints->valid_sw_formats = av_malloc_array(pix_fmt_count + 1,
305  sizeof(pix_fmt));
306  if (!constraints->valid_sw_formats) {
307  err = AVERROR(ENOMEM);
308  goto fail;
309  }
310 
311  for (i = j = 0; i < attr_count; i++) {
312  int k;
313 
314  if (attr_list[i].type != VASurfaceAttribPixelFormat)
315  continue;
316  fourcc = attr_list[i].value.value.i;
318 
319  if (pix_fmt == AV_PIX_FMT_NONE)
320  continue;
321 
322  for (k = 0; k < j; k++) {
323  if (constraints->valid_sw_formats[k] == pix_fmt)
324  break;
325  }
326 
327  if (k == j)
328  constraints->valid_sw_formats[j++] = pix_fmt;
329  }
330  constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
331  }
332  } else {
333  // No configuration supplied.
334  // Return the full set of image formats known by the implementation.
335  constraints->valid_sw_formats = av_malloc_array(ctx->nb_formats + 1,
336  sizeof(pix_fmt));
337  if (!constraints->valid_sw_formats) {
338  err = AVERROR(ENOMEM);
339  goto fail;
340  }
341  for (i = j = 0; i < ctx->nb_formats; i++) {
342  int k;
343 
344  for (k = 0; k < j; k++) {
345  if (constraints->valid_sw_formats[k] == ctx->formats[i].pix_fmt)
346  break;
347  }
348 
349  if (k == j)
350  constraints->valid_sw_formats[j++] = ctx->formats[i].pix_fmt;
351  }
352 
353  constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
354  }
355 
356  constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt));
357  if (!constraints->valid_hw_formats) {
358  err = AVERROR(ENOMEM);
359  goto fail;
360  }
361  constraints->valid_hw_formats[0] = AV_PIX_FMT_VAAPI;
362  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
363 
364  err = 0;
365 fail:
366  av_freep(&attr_list);
367  return err;
368 }
369 
370 static const struct {
371  const char *friendly_name;
372  const char *match_string;
373  unsigned int quirks;
375 #if !VA_CHECK_VERSION(1, 0, 0)
376  // The i965 driver did not conform before version 2.0.
377  {
378  "Intel i965 (Quick Sync)",
379  "i965",
381  },
382 #endif
383  {
384  "Intel iHD",
385  "ubit",
387  },
388  {
389  "VDPAU wrapper",
390  "Splitted-Desktop Systems VDPAU backend for VA-API",
392  },
393 };
394 
396 {
397  VAAPIDeviceContext *ctx = hwdev->hwctx;
398  AVVAAPIDeviceContext *hwctx = &ctx->p;
399  VAImageFormat *image_list = NULL;
400  VAStatus vas;
401  const char *vendor_string;
402  int err, i, image_count;
403  enum AVPixelFormat pix_fmt;
404  unsigned int fourcc;
405 
406  image_count = vaMaxNumImageFormats(hwctx->display);
407  if (image_count <= 0) {
408  err = AVERROR(EIO);
409  goto fail;
410  }
411  image_list = av_malloc(image_count * sizeof(*image_list));
412  if (!image_list) {
413  err = AVERROR(ENOMEM);
414  goto fail;
415  }
416  vas = vaQueryImageFormats(hwctx->display, image_list, &image_count);
417  if (vas != VA_STATUS_SUCCESS) {
418  err = AVERROR(EIO);
419  goto fail;
420  }
421 
422  ctx->formats = av_malloc(image_count * sizeof(*ctx->formats));
423  if (!ctx->formats) {
424  err = AVERROR(ENOMEM);
425  goto fail;
426  }
427  ctx->nb_formats = 0;
428  for (i = 0; i < image_count; i++) {
429  fourcc = image_list[i].fourcc;
431  if (pix_fmt == AV_PIX_FMT_NONE) {
432  av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> unknown.\n",
433  fourcc);
434  } else {
435  av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n",
437  ctx->formats[ctx->nb_formats].pix_fmt = pix_fmt;
438  ctx->formats[ctx->nb_formats].image_format = image_list[i];
439  ++ctx->nb_formats;
440  }
441  }
442 
443  vendor_string = vaQueryVendorString(hwctx->display);
444  if (vendor_string)
445  av_log(hwdev, AV_LOG_VERBOSE, "VAAPI driver: %s.\n", vendor_string);
446 
448  av_log(hwdev, AV_LOG_VERBOSE, "Using quirks set by user (%#x).\n",
449  hwctx->driver_quirks);
450  } else {
451  // Detect the driver in use and set quirk flags if necessary.
452  hwctx->driver_quirks = 0;
453  if (vendor_string) {
454  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) {
455  if (strstr(vendor_string,
457  av_log(hwdev, AV_LOG_VERBOSE, "Matched driver string "
458  "as known nonstandard driver \"%s\", setting "
459  "quirks (%#x).\n",
462  hwctx->driver_quirks |=
464  break;
465  }
466  }
468  av_log(hwdev, AV_LOG_VERBOSE, "Driver not found in known "
469  "nonstandard list, using standard behaviour.\n");
470  }
471  } else {
472  av_log(hwdev, AV_LOG_VERBOSE, "Driver has no vendor string, "
473  "assuming standard behaviour.\n");
474  }
475  }
476 
477  av_free(image_list);
478  return 0;
479 fail:
480  av_freep(&ctx->formats);
481  av_free(image_list);
482  return err;
483 }
484 
486 {
487  VAAPIDeviceContext *ctx = hwdev->hwctx;
488 
489  av_freep(&ctx->formats);
490 }
491 
492 static void vaapi_buffer_free(void *opaque, uint8_t *data)
493 {
494  AVHWFramesContext *hwfc = opaque;
495  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
496  VASurfaceID surface_id;
497  VAStatus vas;
498 
499  surface_id = (VASurfaceID)(uintptr_t)data;
500 
501  vas = vaDestroySurfaces(hwctx->display, &surface_id, 1);
502  if (vas != VA_STATUS_SUCCESS) {
503  av_log(hwfc, AV_LOG_ERROR, "Failed to destroy surface %#x: "
504  "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
505  }
506 }
507 
508 static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size)
509 {
510  AVHWFramesContext *hwfc = opaque;
511  VAAPIFramesContext *ctx = hwfc->hwctx;
512  AVVAAPIFramesContext *avfc = &ctx->p;
513  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
514  VASurfaceID surface_id;
515  VAStatus vas;
516  AVBufferRef *ref;
517 
518  if (hwfc->initial_pool_size > 0 &&
519  avfc->nb_surfaces >= hwfc->initial_pool_size)
520  return NULL;
521 
522  vas = vaCreateSurfaces(hwctx->display, ctx->rt_format,
523  hwfc->width, hwfc->height,
524  &surface_id, 1,
525  ctx->attributes, ctx->nb_attributes);
526  if (vas != VA_STATUS_SUCCESS) {
527  av_log(hwfc, AV_LOG_ERROR, "Failed to create surface: "
528  "%d (%s).\n", vas, vaErrorStr(vas));
529  return NULL;
530  }
531  av_log(hwfc, AV_LOG_DEBUG, "Created surface %#x.\n", surface_id);
532 
533  ref = av_buffer_create((uint8_t*)(uintptr_t)surface_id,
534  sizeof(surface_id), &vaapi_buffer_free,
536  if (!ref) {
537  vaDestroySurfaces(hwctx->display, &surface_id, 1);
538  return NULL;
539  }
540 
541  if (hwfc->initial_pool_size > 0) {
542  // This is a fixed-size pool, so we must still be in the initial
543  // allocation sequence.
545  avfc->surface_ids[avfc->nb_surfaces] = surface_id;
546  ++avfc->nb_surfaces;
547  }
548 
549  return ref;
550 }
551 
553 {
554  VAAPIFramesContext *ctx = hwfc->hwctx;
555  AVVAAPIFramesContext *avfc = &ctx->p;
556  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
557  const VAAPIFormatDescriptor *desc;
558  VAImageFormat *expected_format;
559  AVBufferRef *test_surface = NULL;
560  VASurfaceID test_surface_id;
561  VAImage test_image;
562  VAStatus vas;
563  int err, i;
564 
566  if (!desc) {
567  av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
569  return AVERROR(EINVAL);
570  }
571 
572  if (!hwfc->pool) {
574  int need_memory_type = !(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE);
575  int need_pixel_format = 1;
576  for (i = 0; i < avfc->nb_attributes; i++) {
577  if (avfc->attributes[i].type == VASurfaceAttribMemoryType)
578  need_memory_type = 0;
579  if (avfc->attributes[i].type == VASurfaceAttribPixelFormat)
580  need_pixel_format = 0;
581  }
582  ctx->nb_attributes =
583  avfc->nb_attributes + need_memory_type + need_pixel_format;
584 
585  ctx->attributes = av_malloc(ctx->nb_attributes *
586  sizeof(*ctx->attributes));
587  if (!ctx->attributes) {
588  err = AVERROR(ENOMEM);
589  goto fail;
590  }
591 
592  for (i = 0; i < avfc->nb_attributes; i++)
593  ctx->attributes[i] = avfc->attributes[i];
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,
600  };
601  }
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,
608  };
609  }
610  av_assert0(i == ctx->nb_attributes);
611  } else {
612  ctx->attributes = NULL;
613  ctx->nb_attributes = 0;
614  }
615 
616  ctx->rt_format = desc->rt_format;
617 
618  if (hwfc->initial_pool_size > 0) {
619  // This pool will be usable as a render target, so we need to store
620  // all of the surface IDs somewhere that vaCreateContext() calls
621  // will be able to access them.
622  avfc->nb_surfaces = 0;
623  avfc->surface_ids = av_malloc(hwfc->initial_pool_size *
624  sizeof(*avfc->surface_ids));
625  if (!avfc->surface_ids) {
626  err = AVERROR(ENOMEM);
627  goto fail;
628  }
629  } else {
630  // This pool allows dynamic sizing, and will not be usable as a
631  // render target.
632  avfc->nb_surfaces = 0;
633  avfc->surface_ids = NULL;
634  }
635 
637  av_buffer_pool_init2(sizeof(VASurfaceID), hwfc,
639  if (!ffhwframesctx(hwfc)->pool_internal) {
640  av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n");
641  err = AVERROR(ENOMEM);
642  goto fail;
643  }
644  }
645 
646  // Allocate a single surface to test whether vaDeriveImage() is going
647  // to work for the specific configuration.
648  if (hwfc->pool) {
649  test_surface = av_buffer_pool_get(hwfc->pool);
650  if (!test_surface) {
651  av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
652  "user-configured buffer pool.\n");
653  err = AVERROR(ENOMEM);
654  goto fail;
655  }
656  } else {
657  test_surface = av_buffer_pool_get(ffhwframesctx(hwfc)->pool_internal);
658  if (!test_surface) {
659  av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
660  "internal buffer pool.\n");
661  err = AVERROR(ENOMEM);
662  goto fail;
663  }
664  }
665  test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data;
666 
667  ctx->derive_works = 0;
668 
670  hwfc->sw_format, &expected_format);
671  if (err == 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) {
675  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n");
676  ctx->derive_works = 1;
677  } else {
678  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
679  "derived image format %08x does not match "
680  "expected format %08x.\n",
681  expected_format->fourcc, test_image.format.fourcc);
682  }
683  vaDestroyImage(hwctx->display, test_image.image_id);
684  } else {
685  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
686  "deriving image does not work: "
687  "%d (%s).\n", vas, vaErrorStr(vas));
688  }
689  } else {
690  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
691  "image format is not supported.\n");
692  }
693 
694  av_buffer_unref(&test_surface);
695  return 0;
696 
697 fail:
698  av_buffer_unref(&test_surface);
699  av_freep(&avfc->surface_ids);
700  av_freep(&ctx->attributes);
701  return err;
702 }
703 
705 {
706  VAAPIFramesContext *ctx = hwfc->hwctx;
707  AVVAAPIFramesContext *avfc = &ctx->p;
708 
709  av_freep(&avfc->surface_ids);
710  av_freep(&ctx->attributes);
711 }
712 
714 {
715  frame->buf[0] = av_buffer_pool_get(hwfc->pool);
716  if (!frame->buf[0])
717  return AVERROR(ENOMEM);
718 
719  frame->data[3] = frame->buf[0]->data;
720  frame->format = AV_PIX_FMT_VAAPI;
721  frame->width = hwfc->width;
722  frame->height = hwfc->height;
723 
724  return 0;
725 }
726 
729  enum AVPixelFormat **formats)
730 {
732  enum AVPixelFormat *pix_fmts;
733  int i, k, sw_format_available;
734 
735  sw_format_available = 0;
736  for (i = 0; i < ctx->nb_formats; i++) {
737  if (ctx->formats[i].pix_fmt == hwfc->sw_format)
738  sw_format_available = 1;
739  }
740 
741  pix_fmts = av_malloc((ctx->nb_formats + 1) * sizeof(*pix_fmts));
742  if (!pix_fmts)
743  return AVERROR(ENOMEM);
744 
745  if (sw_format_available) {
746  pix_fmts[0] = hwfc->sw_format;
747  k = 1;
748  } else {
749  k = 0;
750  }
751  for (i = 0; i < ctx->nb_formats; i++) {
752  if (ctx->formats[i].pix_fmt == hwfc->sw_format)
753  continue;
754  av_assert0(k < ctx->nb_formats);
755  pix_fmts[k++] = ctx->formats[i].pix_fmt;
756  }
758 
759  *formats = pix_fmts;
760  return 0;
761 }
762 
764  HWMapDescriptor *hwmap)
765 {
766  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
767  VAAPIMapping *map = hwmap->priv;
768  VASurfaceID surface_id;
769  VAStatus vas;
770 
771  surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
772  av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id);
773 
774  vas = vaUnmapBuffer(hwctx->display, map->image.buf);
775  if (vas != VA_STATUS_SUCCESS) {
776  av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface "
777  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
778  }
779 
780  if ((map->flags & AV_HWFRAME_MAP_WRITE) &&
781  !(map->flags & AV_HWFRAME_MAP_DIRECT)) {
782  vas = vaPutImage(hwctx->display, surface_id, map->image.image_id,
783  0, 0, hwfc->width, hwfc->height,
784  0, 0, hwfc->width, hwfc->height);
785  if (vas != VA_STATUS_SUCCESS) {
786  av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface "
787  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
788  }
789  }
790 
791  vas = vaDestroyImage(hwctx->display, map->image.image_id);
792  if (vas != VA_STATUS_SUCCESS) {
793  av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface "
794  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
795  }
796 
797  av_free(map);
798 }
799 
801  AVFrame *dst, const AVFrame *src, int flags)
802 {
803  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
804  VAAPIFramesContext *ctx = hwfc->hwctx;
805  VASurfaceID surface_id;
806  const VAAPIFormatDescriptor *desc;
807  VAImageFormat *image_format;
808  VAAPIMapping *map;
809  VAStatus vas;
810  void *address = NULL;
811  int err, i;
812 #if VA_CHECK_VERSION(1, 21, 0)
813  uint32_t vaflags = 0;
814 #endif
815 
816  surface_id = (VASurfaceID)(uintptr_t)src->data[3];
817  av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id);
818 
819  if (!ctx->derive_works && (flags & AV_HWFRAME_MAP_DIRECT)) {
820  // Requested direct mapping but it is not possible.
821  return AVERROR(EINVAL);
822  }
823  if (dst->format == AV_PIX_FMT_NONE)
824  dst->format = hwfc->sw_format;
825  if (dst->format != hwfc->sw_format && (flags & AV_HWFRAME_MAP_DIRECT)) {
826  // Requested direct mapping but the formats do not match.
827  return AVERROR(EINVAL);
828  }
829 
830  err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format);
831  if (err < 0) {
832  // Requested format is not a valid output format.
833  return err;
834  }
835 
836  map = av_malloc(sizeof(*map));
837  if (!map)
838  return AVERROR(ENOMEM);
839  map->flags = flags;
840  map->image.image_id = VA_INVALID_ID;
841 
842  vas = vaSyncSurface(hwctx->display, surface_id);
843  if (vas != VA_STATUS_SUCCESS) {
844  av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
845  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
846  err = AVERROR(EIO);
847  goto fail;
848  }
849 
850  // The memory which we map using derive need not be connected to the CPU
851  // in a way conducive to fast access. On Gen7-Gen9 Intel graphics, the
852  // memory is mappable but not cached, so normal memcpy()-like access is
853  // very slow to read it (but writing is ok). It is possible to read much
854  // faster with a copy routine which is aware of the limitation, but we
855  // assume for now that the user is not aware of that and would therefore
856  // prefer not to be given direct-mapped memory if they request read access.
857  if (ctx->derive_works && dst->format == hwfc->sw_format &&
859  vas = vaDeriveImage(hwctx->display, surface_id, &map->image);
860  if (vas != VA_STATUS_SUCCESS) {
861  av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
862  "surface %#x: %d (%s).\n",
863  surface_id, vas, vaErrorStr(vas));
864  err = AVERROR(EIO);
865  goto fail;
866  }
867  if (map->image.format.fourcc != image_format->fourcc) {
868  av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x "
869  "is in wrong format: expected %#08x, got %#08x.\n",
870  surface_id, image_format->fourcc, map->image.format.fourcc);
871  err = AVERROR(EIO);
872  goto fail;
873  }
874  map->flags |= AV_HWFRAME_MAP_DIRECT;
875  } else {
876  vas = vaCreateImage(hwctx->display, image_format,
877  hwfc->width, hwfc->height, &map->image);
878  if (vas != VA_STATUS_SUCCESS) {
879  av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
880  "surface %#x: %d (%s).\n",
881  surface_id, vas, vaErrorStr(vas));
882  err = AVERROR(EIO);
883  goto fail;
884  }
885  if (!(flags & AV_HWFRAME_MAP_OVERWRITE)) {
886  vas = vaGetImage(hwctx->display, surface_id, 0, 0,
887  hwfc->width, hwfc->height, map->image.image_id);
888  if (vas != VA_STATUS_SUCCESS) {
889  av_log(hwfc, AV_LOG_ERROR, "Failed to read image from "
890  "surface %#x: %d (%s).\n",
891  surface_id, vas, vaErrorStr(vas));
892  err = AVERROR(EIO);
893  goto fail;
894  }
895  }
896  }
897 
898 #if VA_CHECK_VERSION(1, 21, 0)
900  vaflags |= VA_MAPBUFFER_FLAG_READ;
902  vaflags |= VA_MAPBUFFER_FLAG_WRITE;
903  // On drivers not implementing vaMapBuffer2 libva calls vaMapBuffer instead.
904  vas = vaMapBuffer2(hwctx->display, map->image.buf, &address, vaflags);
905 #else
906  vas = vaMapBuffer(hwctx->display, map->image.buf, &address);
907 #endif
908  if (vas != VA_STATUS_SUCCESS) {
909  av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface "
910  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
911  err = AVERROR(EIO);
912  goto fail;
913  }
914 
915  err = ff_hwframe_map_create(src->hw_frames_ctx,
916  dst, src, &vaapi_unmap_frame, map);
917  if (err < 0)
918  goto fail;
919 
920  dst->width = src->width;
921  dst->height = src->height;
922 
923  for (i = 0; i < map->image.num_planes; i++) {
924  dst->data[i] = (uint8_t*)address + map->image.offsets[i];
925  dst->linesize[i] = map->image.pitches[i];
926  }
927 
928  desc = vaapi_format_from_fourcc(map->image.format.fourcc);
929  if (desc && desc->chroma_planes_swapped) {
930  // Chroma planes are YVU rather than YUV, so swap them.
931  FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
932  }
933 
934  return 0;
935 
936 fail:
937  if (map) {
938  if (address)
939  vaUnmapBuffer(hwctx->display, map->image.buf);
940  if (map->image.image_id != VA_INVALID_ID)
941  vaDestroyImage(hwctx->display, map->image.image_id);
942  av_free(map);
943  }
944  return err;
945 }
946 
948  AVFrame *dst, const AVFrame *src)
949 {
950  AVFrame *map;
951  int err;
952 
953  if (dst->width > hwfc->width || dst->height > hwfc->height)
954  return AVERROR(EINVAL);
955 
956  map = av_frame_alloc();
957  if (!map)
958  return AVERROR(ENOMEM);
959  map->format = dst->format;
960 
962  if (err)
963  goto fail;
964 
965  map->width = dst->width;
966  map->height = dst->height;
967 
968  err = av_frame_copy(dst, map);
969  if (err)
970  goto fail;
971 
972  err = 0;
973 fail:
974  av_frame_free(&map);
975  return err;
976 }
977 
979  AVFrame *dst, const AVFrame *src)
980 {
981  AVFrame *map;
982  int err;
983 
984  if (src->width > hwfc->width || src->height > hwfc->height)
985  return AVERROR(EINVAL);
986 
987  map = av_frame_alloc();
988  if (!map)
989  return AVERROR(ENOMEM);
990  map->format = src->format;
991 
993  if (err)
994  goto fail;
995 
996  map->width = src->width;
997  map->height = src->height;
998 
999  err = av_frame_copy(map, src);
1000  if (err)
1001  goto fail;
1002 
1003  err = 0;
1004 fail:
1005  av_frame_free(&map);
1006  return err;
1007 }
1008 
1010  const AVFrame *src, int flags)
1011 {
1012  int err;
1013 
1014  if (dst->format != AV_PIX_FMT_NONE) {
1015  err = vaapi_get_image_format(hwfc->device_ctx, dst->format, NULL);
1016  if (err < 0)
1017  return err;
1018  }
1019 
1020  err = vaapi_map_frame(hwfc, dst, src, flags);
1021  if (err)
1022  return err;
1023 
1024  err = av_frame_copy_props(dst, src);
1025  if (err)
1026  return err;
1027 
1028  return 0;
1029 }
1030 
1031 #if CONFIG_LIBDRM
1032 
1033 #define DRM_MAP(va, layers, ...) { \
1034  VA_FOURCC_ ## va, \
1035  layers, \
1036  { __VA_ARGS__ } \
1037  }
1038 static const struct {
1039  uint32_t va_fourcc;
1040  int nb_layer_formats;
1041  uint32_t layer_formats[AV_DRM_MAX_PLANES];
1042 } vaapi_drm_format_map[] = {
1043 #ifdef DRM_FORMAT_R8
1044  DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
1045  DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88),
1046 #endif
1047  DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
1048 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
1049  DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1050 #endif
1051 #if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
1052  DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1053 #endif
1054  DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
1055  DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
1056  DRM_MAP(RGBA, 1, DRM_FORMAT_ABGR8888),
1057  DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
1058 #ifdef VA_FOURCC_ABGR
1059  DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
1060  DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
1061 #endif
1062  DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
1063  DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
1064 #if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
1065  DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
1066 #endif
1067 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
1068  DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
1069 #endif
1070 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
1071  DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
1072 #endif
1073 #if defined(VA_FOURCC_X2R10G10B10) && defined(DRM_FORMAT_XRGB2101010)
1074  DRM_MAP(X2R10G10B10, 1, DRM_FORMAT_XRGB2101010),
1075 #endif
1076 };
1077 #undef DRM_MAP
1078 
1079 static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc,
1080  HWMapDescriptor *hwmap)
1081 {
1082  AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
1083 
1084  VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->priv;
1085 
1086  av_log(dst_fc, AV_LOG_DEBUG, "Destroy surface %#x.\n", surface_id);
1087 
1088  vaDestroySurfaces(dst_dev->display, &surface_id, 1);
1089 }
1090 
1091 static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
1092  const AVFrame *src, int flags)
1093 {
1094 #if VA_CHECK_VERSION(1, 1, 0)
1095  VAAPIFramesContext *src_vafc = src_fc->hwctx;
1096  int use_prime2;
1097 #else
1098  int k;
1099 #endif
1100  AVHWFramesContext *dst_fc =
1102  AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
1103  const AVDRMFrameDescriptor *desc;
1104  const VAAPIFormatDescriptor *format_desc;
1105  VASurfaceID surface_id;
1106  VAStatus vas = VA_STATUS_SUCCESS;
1107  uint32_t va_fourcc;
1108  int err, i, j;
1109 
1110 #if !VA_CHECK_VERSION(1, 1, 0)
1111  unsigned long buffer_handle;
1112  VASurfaceAttribExternalBuffers buffer_desc;
1113  VASurfaceAttrib attrs[2] = {
1114  {
1115  .type = VASurfaceAttribMemoryType,
1116  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1117  .value.type = VAGenericValueTypeInteger,
1118  .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1119  },
1120  {
1121  .type = VASurfaceAttribExternalBufferDescriptor,
1122  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1123  .value.type = VAGenericValueTypePointer,
1124  .value.value.p = &buffer_desc,
1125  }
1126  };
1127 #endif
1128 
1129  desc = (AVDRMFrameDescriptor*)src->data[0];
1130 
1131  if (desc->nb_objects != 1) {
1132  av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames "
1133  "made from a single DRM object.\n");
1134  return AVERROR(EINVAL);
1135  }
1136 
1137  va_fourcc = 0;
1138  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
1139  if (desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats)
1140  continue;
1141  for (j = 0; j < desc->nb_layers; j++) {
1142  if (desc->layers[j].format !=
1143  vaapi_drm_format_map[i].layer_formats[j])
1144  break;
1145  }
1146  if (j != desc->nb_layers)
1147  continue;
1148  va_fourcc = vaapi_drm_format_map[i].va_fourcc;
1149  break;
1150  }
1151  if (!va_fourcc) {
1152  av_log(dst_fc, AV_LOG_ERROR, "DRM format not supported "
1153  "by VAAPI.\n");
1154  return AVERROR(EINVAL);
1155  }
1156 
1157  av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as "
1158  "%08x.\n", desc->objects[0].fd, va_fourcc);
1159 
1160  format_desc = vaapi_format_from_fourcc(va_fourcc);
1161  av_assert0(format_desc);
1162 
1163 #if VA_CHECK_VERSION(1, 1, 0)
1164  use_prime2 = !src_vafc->prime_2_import_unsupported &&
1165  desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID;
1166  if (use_prime2) {
1167  VADRMPRIMESurfaceDescriptor prime_desc;
1168  VASurfaceAttrib prime_attrs[2] = {
1169  {
1170  .type = VASurfaceAttribMemoryType,
1171  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1172  .value.type = VAGenericValueTypeInteger,
1173  .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1174  },
1175  {
1176  .type = VASurfaceAttribExternalBufferDescriptor,
1177  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1178  .value.type = VAGenericValueTypePointer,
1179  .value.value.p = &prime_desc,
1180  }
1181  };
1182  prime_desc.fourcc = va_fourcc;
1183  prime_desc.width = src_fc->width;
1184  prime_desc.height = src_fc->height;
1185  prime_desc.num_objects = desc->nb_objects;
1186  for (i = 0; i < desc->nb_objects; ++i) {
1187  prime_desc.objects[i].fd = desc->objects[i].fd;
1188  prime_desc.objects[i].size = desc->objects[i].size;
1189  prime_desc.objects[i].drm_format_modifier =
1190  desc->objects[i].format_modifier;
1191  }
1192 
1193  prime_desc.num_layers = desc->nb_layers;
1194  for (i = 0; i < desc->nb_layers; ++i) {
1195  prime_desc.layers[i].drm_format = desc->layers[i].format;
1196  prime_desc.layers[i].num_planes = desc->layers[i].nb_planes;
1197  for (j = 0; j < desc->layers[i].nb_planes; ++j) {
1198  prime_desc.layers[i].object_index[j] =
1199  desc->layers[i].planes[j].object_index;
1200  prime_desc.layers[i].offset[j] = desc->layers[i].planes[j].offset;
1201  prime_desc.layers[i].pitch[j] = desc->layers[i].planes[j].pitch;
1202  }
1203 
1204  if (format_desc->chroma_planes_swapped &&
1205  desc->layers[i].nb_planes == 3) {
1206  FFSWAP(uint32_t, prime_desc.layers[i].pitch[1],
1207  prime_desc.layers[i].pitch[2]);
1208  FFSWAP(uint32_t, prime_desc.layers[i].offset[1],
1209  prime_desc.layers[i].offset[2]);
1210  }
1211  }
1212 
1213  /*
1214  * We can query for PRIME_2 support with vaQuerySurfaceAttributes, but that
1215  * that needs the config_id which we don't have here . Both Intel and
1216  * Gallium seem to do the correct error checks, so lets just try the
1217  * PRIME_2 import first.
1218  */
1219  vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1220  src->width, src->height, &surface_id, 1,
1221  prime_attrs, FF_ARRAY_ELEMS(prime_attrs));
1222  if (vas != VA_STATUS_SUCCESS)
1223  src_vafc->prime_2_import_unsupported = 1;
1224  }
1225 
1226  if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1227  int k;
1228  unsigned long buffer_handle;
1229  VASurfaceAttribExternalBuffers buffer_desc;
1230  VASurfaceAttrib buffer_attrs[2] = {
1231  {
1232  .type = VASurfaceAttribMemoryType,
1233  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1234  .value.type = VAGenericValueTypeInteger,
1235  .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1236  },
1237  {
1238  .type = VASurfaceAttribExternalBufferDescriptor,
1239  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1240  .value.type = VAGenericValueTypePointer,
1241  .value.value.p = &buffer_desc,
1242  }
1243  };
1244 
1245  buffer_handle = desc->objects[0].fd;
1246  buffer_desc.pixel_format = va_fourcc;
1247  buffer_desc.width = src_fc->width;
1248  buffer_desc.height = src_fc->height;
1249  buffer_desc.data_size = desc->objects[0].size;
1250  buffer_desc.buffers = &buffer_handle;
1251  buffer_desc.num_buffers = 1;
1252  buffer_desc.flags = 0;
1253 
1254  k = 0;
1255  for (i = 0; i < desc->nb_layers; i++) {
1256  for (j = 0; j < desc->layers[i].nb_planes; j++) {
1257  buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch;
1258  buffer_desc.offsets[k] = desc->layers[i].planes[j].offset;
1259  ++k;
1260  }
1261  }
1262  buffer_desc.num_planes = k;
1263 
1264  if (format_desc->chroma_planes_swapped &&
1265  buffer_desc.num_planes == 3) {
1266  FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1267  FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1268  }
1269 
1270  vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1271  src->width, src->height,
1272  &surface_id, 1,
1273  buffer_attrs, FF_ARRAY_ELEMS(buffer_attrs));
1274  }
1275 #else
1276  buffer_handle = desc->objects[0].fd;
1277  buffer_desc.pixel_format = va_fourcc;
1278  buffer_desc.width = src_fc->width;
1279  buffer_desc.height = src_fc->height;
1280  buffer_desc.data_size = desc->objects[0].size;
1281  buffer_desc.buffers = &buffer_handle;
1282  buffer_desc.num_buffers = 1;
1283  buffer_desc.flags = 0;
1284 
1285  k = 0;
1286  for (i = 0; i < desc->nb_layers; i++) {
1287  for (j = 0; j < desc->layers[i].nb_planes; j++) {
1288  buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch;
1289  buffer_desc.offsets[k] = desc->layers[i].planes[j].offset;
1290  ++k;
1291  }
1292  }
1293  buffer_desc.num_planes = k;
1294 
1295  if (format_desc->chroma_planes_swapped &&
1296  buffer_desc.num_planes == 3) {
1297  FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1298  FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1299  }
1300 
1301  vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1302  src->width, src->height,
1303  &surface_id, 1,
1304  attrs, FF_ARRAY_ELEMS(attrs));
1305 #endif
1306  if (vas != VA_STATUS_SUCCESS) {
1307  av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM "
1308  "object: %d (%s).\n", vas, vaErrorStr(vas));
1309  return AVERROR(EIO);
1310  }
1311  av_log(dst_fc, AV_LOG_DEBUG, "Create surface %#x.\n", surface_id);
1312 
1313  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
1314  &vaapi_unmap_from_drm,
1315  (void*)(uintptr_t)surface_id);
1316  if (err < 0)
1317  return err;
1318 
1319  dst->width = src->width;
1320  dst->height = src->height;
1321  dst->data[3] = (uint8_t*)(uintptr_t)surface_id;
1322 
1323  av_log(dst_fc, AV_LOG_DEBUG, "Mapped DRM object %d to "
1324  "surface %#x.\n", desc->objects[0].fd, surface_id);
1325 
1326  return 0;
1327 }
1328 
1329 #if VA_CHECK_VERSION(1, 1, 0)
1330 static void vaapi_unmap_to_drm_esh(AVHWFramesContext *hwfc,
1331  HWMapDescriptor *hwmap)
1332 {
1333  AVDRMFrameDescriptor *drm_desc = hwmap->priv;
1334  int i;
1335 
1336  for (i = 0; i < drm_desc->nb_objects; i++)
1337  close(drm_desc->objects[i].fd);
1338 
1339  av_freep(&drm_desc);
1340 }
1341 
1342 static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
1343  const AVFrame *src, int flags)
1344 {
1345  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1346  VASurfaceID surface_id;
1347  VAStatus vas;
1348  VADRMPRIMESurfaceDescriptor va_desc;
1349  AVDRMFrameDescriptor *drm_desc = NULL;
1350  uint32_t export_flags;
1351  int err, i, j;
1352 
1353  surface_id = (VASurfaceID)(uintptr_t)src->data[3];
1354 
1355  export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1356  if (flags & AV_HWFRAME_MAP_READ) {
1357  export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1358 
1359  vas = vaSyncSurface(hwctx->display, surface_id);
1360  if (vas != VA_STATUS_SUCCESS) {
1361  av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
1362  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
1363  return AVERROR(EIO);
1364  }
1365  }
1366 
1368  export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1369 
1370  vas = vaExportSurfaceHandle(hwctx->display, surface_id,
1371  VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1372  export_flags, &va_desc);
1373  if (vas != VA_STATUS_SUCCESS) {
1374  if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1375  return AVERROR(ENOSYS);
1376  av_log(hwfc, AV_LOG_ERROR, "Failed to export surface %#x: "
1377  "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1378  return AVERROR(EIO);
1379  }
1380 
1381  drm_desc = av_mallocz(sizeof(*drm_desc));
1382  if (!drm_desc) {
1383  err = AVERROR(ENOMEM);
1384  goto fail;
1385  }
1386 
1387  // By some bizarre coincidence, these structures are very similar...
1388  drm_desc->nb_objects = va_desc.num_objects;
1389  for (i = 0; i < va_desc.num_objects; i++) {
1390  drm_desc->objects[i].fd = va_desc.objects[i].fd;
1391  drm_desc->objects[i].size = va_desc.objects[i].size;
1392  drm_desc->objects[i].format_modifier =
1393  va_desc.objects[i].drm_format_modifier;
1394  }
1395  drm_desc->nb_layers = va_desc.num_layers;
1396  for (i = 0; i < va_desc.num_layers; i++) {
1397  drm_desc->layers[i].format = va_desc.layers[i].drm_format;
1398  drm_desc->layers[i].nb_planes = va_desc.layers[i].num_planes;
1399  for (j = 0; j < va_desc.layers[i].num_planes; j++) {
1400  drm_desc->layers[i].planes[j].object_index =
1401  va_desc.layers[i].object_index[j];
1402  drm_desc->layers[i].planes[j].offset =
1403  va_desc.layers[i].offset[j];
1404  drm_desc->layers[i].planes[j].pitch =
1405  va_desc.layers[i].pitch[j];
1406  }
1407  }
1408 
1409  err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
1410  &vaapi_unmap_to_drm_esh, drm_desc);
1411  if (err < 0)
1412  goto fail;
1413 
1414  dst->width = src->width;
1415  dst->height = src->height;
1416  dst->data[0] = (uint8_t*)drm_desc;
1417 
1418  return 0;
1419 
1420 fail:
1421  for (i = 0; i < va_desc.num_objects; i++)
1422  close(va_desc.objects[i].fd);
1423  av_freep(&drm_desc);
1424  return err;
1425 }
1426 #endif
1427 
1428 #if VA_CHECK_VERSION(0, 36, 0)
1429 typedef struct VAAPIDRMImageBufferMapping {
1430  VAImage image;
1431  VABufferInfo buffer_info;
1432 
1433  AVDRMFrameDescriptor drm_desc;
1434 } VAAPIDRMImageBufferMapping;
1435 
1436 static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc,
1437  HWMapDescriptor *hwmap)
1438 {
1439  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1440  VAAPIDRMImageBufferMapping *mapping = hwmap->priv;
1441  VASurfaceID surface_id;
1442  VAStatus vas;
1443 
1444  surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
1445  av_log(hwfc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from DRM.\n",
1446  surface_id);
1447 
1448  // DRM PRIME file descriptors are closed by vaReleaseBufferHandle(),
1449  // so we shouldn't close them separately.
1450 
1451  vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1452  if (vas != VA_STATUS_SUCCESS) {
1453  av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer "
1454  "handle of image %#x (derived from surface %#x): "
1455  "%d (%s).\n", mapping->image.buf, surface_id,
1456  vas, vaErrorStr(vas));
1457  }
1458 
1459  vas = vaDestroyImage(hwctx->display, mapping->image.image_id);
1460  if (vas != VA_STATUS_SUCCESS) {
1461  av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image "
1462  "derived from surface %#x: %d (%s).\n",
1463  surface_id, vas, vaErrorStr(vas));
1464  }
1465 
1466  av_free(mapping);
1467 }
1468 
1469 static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
1470  const AVFrame *src, int flags)
1471 {
1472  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1473  VAAPIDRMImageBufferMapping *mapping = NULL;
1474  VASurfaceID surface_id;
1475  VAStatus vas;
1476  int err, i, p;
1477 
1478  surface_id = (VASurfaceID)(uintptr_t)src->data[3];
1479  av_log(hwfc, AV_LOG_DEBUG, "Map VAAPI surface %#x to DRM.\n",
1480  surface_id);
1481 
1482  mapping = av_mallocz(sizeof(*mapping));
1483  if (!mapping)
1484  return AVERROR(ENOMEM);
1485 
1486  vas = vaDeriveImage(hwctx->display, surface_id,
1487  &mapping->image);
1488  if (vas != VA_STATUS_SUCCESS) {
1489  av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
1490  "surface %#x: %d (%s).\n",
1491  surface_id, vas, vaErrorStr(vas));
1492  err = AVERROR(EIO);
1493  goto fail;
1494  }
1495 
1496  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
1497  if (vaapi_drm_format_map[i].va_fourcc ==
1498  mapping->image.format.fourcc)
1499  break;
1500  }
1501  if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) {
1502  av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for "
1503  "VAAPI format %#x.\n", mapping->image.format.fourcc);
1504  err = AVERROR(EINVAL);
1505  goto fail_derived;
1506  }
1507 
1508  mapping->buffer_info.mem_type =
1509  VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1510 
1511  mapping->drm_desc.nb_layers =
1512  vaapi_drm_format_map[i].nb_layer_formats;
1513  if (mapping->drm_desc.nb_layers > 1) {
1514  if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1515  av_log(hwfc, AV_LOG_ERROR, "Image properties do not match "
1516  "expected format: got %d planes, but expected %d.\n",
1517  mapping->image.num_planes, mapping->drm_desc.nb_layers);
1518  err = AVERROR(EINVAL);
1519  goto fail_derived;
1520  }
1521 
1522  for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1523  mapping->drm_desc.layers[p] = (AVDRMLayerDescriptor) {
1524  .format = vaapi_drm_format_map[i].layer_formats[p],
1525  .nb_planes = 1,
1526  .planes[0] = {
1527  .object_index = 0,
1528  .offset = mapping->image.offsets[p],
1529  .pitch = mapping->image.pitches[p],
1530  },
1531  };
1532  }
1533  } else {
1534  mapping->drm_desc.layers[0].format =
1535  vaapi_drm_format_map[i].layer_formats[0];
1536  mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1537  for (p = 0; p < mapping->image.num_planes; p++) {
1538  mapping->drm_desc.layers[0].planes[p] = (AVDRMPlaneDescriptor) {
1539  .object_index = 0,
1540  .offset = mapping->image.offsets[p],
1541  .pitch = mapping->image.pitches[p],
1542  };
1543  }
1544  }
1545 
1546  vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf,
1547  &mapping->buffer_info);
1548  if (vas != VA_STATUS_SUCCESS) {
1549  av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer "
1550  "handle from image %#x (derived from surface %#x): "
1551  "%d (%s).\n", mapping->image.buf, surface_id,
1552  vas, vaErrorStr(vas));
1553  err = AVERROR(EIO);
1554  goto fail_derived;
1555  }
1556 
1557  av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %"PRIdPTR".\n",
1558  mapping->buffer_info.handle);
1559 
1560  mapping->drm_desc.nb_objects = 1;
1561  mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) {
1562  .fd = mapping->buffer_info.handle,
1563  .size = mapping->image.data_size,
1564  // There is no way to get the format modifier with this API.
1565  .format_modifier = DRM_FORMAT_MOD_INVALID,
1566  };
1567 
1568  err = ff_hwframe_map_create(src->hw_frames_ctx,
1569  dst, src, &vaapi_unmap_to_drm_abh,
1570  mapping);
1571  if (err < 0)
1572  goto fail_mapped;
1573 
1574  dst->data[0] = (uint8_t*)&mapping->drm_desc;
1575  dst->width = src->width;
1576  dst->height = src->height;
1577 
1578  return 0;
1579 
1580 fail_mapped:
1581  vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1582 fail_derived:
1583  vaDestroyImage(hwctx->display, mapping->image.image_id);
1584 fail:
1585  av_freep(&mapping);
1586  return err;
1587 }
1588 #endif
1589 
1590 static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
1591  const AVFrame *src, int flags)
1592 {
1593 #if VA_CHECK_VERSION(1, 1, 0)
1594  int err;
1595  err = vaapi_map_to_drm_esh(hwfc, dst, src, flags);
1596  if (err != AVERROR(ENOSYS))
1597  return err;
1598 #endif
1599 #if VA_CHECK_VERSION(0, 36, 0)
1600  return vaapi_map_to_drm_abh(hwfc, dst, src, flags);
1601 #endif
1602  return AVERROR(ENOSYS);
1603 }
1604 
1605 #endif /* CONFIG_LIBDRM */
1606 
1607 static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
1608  const AVFrame *src, int flags)
1609 {
1610  switch (src->format) {
1611 #if CONFIG_LIBDRM
1612  case AV_PIX_FMT_DRM_PRIME:
1613  return vaapi_map_from_drm(hwfc, dst, src, flags);
1614 #endif
1615  default:
1616  return AVERROR(ENOSYS);
1617  }
1618 }
1619 
1621  const AVFrame *src, int flags)
1622 {
1623  switch (dst->format) {
1624 #if CONFIG_LIBDRM
1625  case AV_PIX_FMT_DRM_PRIME:
1626  return vaapi_map_to_drm(hwfc, dst, src, flags);
1627 #endif
1628  default:
1629  return vaapi_map_to_memory(hwfc, dst, src, flags);
1630  }
1631 }
1632 
1634 {
1635  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1636  VAAPIDevicePriv *priv = ctx->user_opaque;
1637 
1638  if (hwctx->display)
1639  vaTerminate(hwctx->display);
1640 
1641 #if HAVE_VAAPI_X11
1642  if (priv->x11_display)
1643  XCloseDisplay(priv->x11_display);
1644 #endif
1645 
1646  if (priv->drm_fd >= 0)
1647  close(priv->drm_fd);
1648 
1649  av_freep(&priv);
1650 }
1651 
1652 #if CONFIG_VAAPI_1
1653 static void vaapi_device_log_error(void *context, const char *message)
1654 {
1656 
1657  av_log(ctx, AV_LOG_ERROR, "libva: %s", message);
1658 }
1659 
1660 static void vaapi_device_log_info(void *context, const char *message)
1661 {
1663 
1664  av_log(ctx, AV_LOG_VERBOSE, "libva: %s", message);
1665 }
1666 #endif
1667 
1669  VADisplay display)
1670 {
1671  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1672  int major, minor;
1673  VAStatus vas;
1674 
1675 #if CONFIG_VAAPI_1
1676  vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
1677  vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
1678 #endif
1679 
1680  hwctx->display = display;
1681 
1682  vas = vaInitialize(display, &major, &minor);
1683  if (vas != VA_STATUS_SUCCESS) {
1684  av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
1685  "connection: %d (%s).\n", vas, vaErrorStr(vas));
1686  return AVERROR(EIO);
1687  }
1688  av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
1689  "version %d.%d\n", major, minor);
1690 
1691  return 0;
1692 }
1693 
1694 static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
1695  AVDictionary *opts, int flags)
1696 {
1697  VAAPIDevicePriv *priv;
1698  VADisplay display = NULL;
1699  const AVDictionaryEntry *ent;
1700  int try_drm, try_x11, try_win32, try_all;
1701 
1702  priv = av_mallocz(sizeof(*priv));
1703  if (!priv)
1704  return AVERROR(ENOMEM);
1705 
1706  priv->drm_fd = -1;
1707 
1708  ctx->user_opaque = priv;
1709  ctx->free = vaapi_device_free;
1710 
1711  ent = av_dict_get(opts, "connection_type", NULL, 0);
1712  if (ent) {
1713  try_all = try_drm = try_x11 = try_win32 = 0;
1714  if (!strcmp(ent->value, "drm")) {
1715  try_drm = 1;
1716  } else if (!strcmp(ent->value, "x11")) {
1717  try_x11 = 1;
1718  } else if (!strcmp(ent->value, "win32")) {
1719  try_win32 = 1;
1720  } else {
1721  av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n",
1722  ent->value);
1723  return AVERROR(EINVAL);
1724  }
1725  } else {
1726  try_all = 1;
1727  try_drm = HAVE_VAAPI_DRM;
1728  try_x11 = HAVE_VAAPI_X11;
1729  try_win32 = HAVE_VAAPI_WIN32;
1730  }
1731 
1732 #if HAVE_VAAPI_DRM
1733  while (!display && try_drm) {
1734  // If the device is specified, try to open it as a DRM device node.
1735  // If not, look for a usable render node, possibly restricted to those
1736  // using a specified kernel driver.
1737  int loglevel = try_all ? AV_LOG_VERBOSE : AV_LOG_ERROR;
1738  if (device) {
1739  priv->drm_fd = open(device, O_RDWR);
1740  if (priv->drm_fd < 0) {
1741  av_log(ctx, loglevel, "Failed to open %s as "
1742  "DRM device node.\n", device);
1743  break;
1744  }
1745  } else {
1746  char path[64];
1747  int n, max_devices = 8;
1748 #if CONFIG_LIBDRM
1749  drmVersion *info;
1750  const AVDictionaryEntry *kernel_driver;
1751  kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0);
1752 #endif
1753  for (n = 0; n < max_devices; n++) {
1754  snprintf(path, sizeof(path),
1755  "/dev/dri/renderD%d", 128 + n);
1756  priv->drm_fd = open(path, O_RDWR);
1757  if (priv->drm_fd < 0) {
1758  if (errno == ENOENT) {
1759  if (n != max_devices - 1) {
1761  "No render device %s, try next device for "
1762  "DRM render node.\n", path);
1763  continue;
1764  }
1765 
1766  av_log(ctx, AV_LOG_VERBOSE, "No available render device "
1767  "for DRM render node.\n");
1768  } else
1769  av_log(ctx, AV_LOG_VERBOSE, "Cannot open "
1770  "DRM render node for device %d.\n", n);
1771  break;
1772  }
1773 #if CONFIG_LIBDRM
1774  info = drmGetVersion(priv->drm_fd);
1775  if (!info) {
1777  "Failed to get DRM version for device %d.\n", n);
1778  close(priv->drm_fd);
1779  priv->drm_fd = -1;
1780  continue;
1781  }
1782  if (kernel_driver) {
1783  if (strcmp(kernel_driver->value, info->name)) {
1784  av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d "
1785  "with non-matching kernel driver (%s).\n",
1786  n, info->name);
1787  drmFreeVersion(info);
1788  close(priv->drm_fd);
1789  priv->drm_fd = -1;
1790  continue;
1791  }
1792  av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1793  "DRM render node for device %d, "
1794  "with matching kernel driver (%s).\n",
1795  n, info->name);
1796  drmFreeVersion(info);
1797  break;
1798  // drmGetVersion() ensures |info->name| is 0-terminated.
1799  } else if (!strcmp(info->name, "vgem")) {
1801  "Skipping vgem node for device %d.\n", n);
1802  drmFreeVersion(info);
1803  close(priv->drm_fd);
1804  priv->drm_fd = -1;
1805  continue;
1806  }
1807  drmFreeVersion(info);
1808 #endif
1809  av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1810  "DRM render node for device %d.\n", n);
1811  break;
1812  }
1813  if (n >= max_devices)
1814  break;
1815  }
1816 
1817  display = vaGetDisplayDRM(priv->drm_fd);
1818  if (!display) {
1819  av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display "
1820  "from DRM device %s.\n", device);
1821  return AVERROR_EXTERNAL;
1822  }
1823  break;
1824  }
1825 #endif
1826 
1827 #if HAVE_VAAPI_X11
1828  if (!display && try_x11) {
1829  // Try to open the device as an X11 display.
1830  priv->x11_display = XOpenDisplay(device);
1831  if (!priv->x11_display) {
1832  av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
1833  "%s.\n", XDisplayName(device));
1834  } else {
1835  display = vaGetDisplay(priv->x11_display);
1836  if (!display) {
1837  av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1838  "from X11 display %s.\n", XDisplayName(device));
1839  return AVERROR_UNKNOWN;
1840  }
1841 
1842  av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1843  "X11 display %s.\n", XDisplayName(device));
1844  }
1845  }
1846 #endif
1847 
1848 #if HAVE_VAAPI_WIN32
1849  if (!display && try_win32) {
1850  // Try to create a display from the specified device, if any.
1851  if (!device) {
1852  display = vaGetDisplayWin32(NULL);
1853  } else {
1854  IDXGIFactory2 *pDXGIFactory = NULL;
1855  IDXGIAdapter *pAdapter = NULL;
1856 #if !HAVE_UWP
1857  HANDLE dxgi = dlopen("dxgi.dll", 0);
1858  if (!dxgi) {
1859  av_log(ctx, AV_LOG_ERROR, "Failed to load dxgi.dll\n");
1860  return AVERROR_UNKNOWN;
1861  }
1862  PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory =
1863  (PFN_CREATE_DXGI_FACTORY)dlsym(dxgi, "CreateDXGIFactory");
1864  if (!pfnCreateDXGIFactory) {
1865  av_log(ctx, AV_LOG_ERROR, "CreateDXGIFactory load failed\n");
1866  dlclose(dxgi);
1867  return AVERROR_UNKNOWN;
1868  }
1869 #else
1870  // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't
1871  // available, only CreateDXGIFactory1
1872  PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory =
1873  (PFN_CREATE_DXGI_FACTORY)CreateDXGIFactory1;
1874 #endif
1875  if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2,
1876  (void **)&pDXGIFactory))) {
1877  int adapter = atoi(device);
1878  if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
1879  adapter,
1880  &pAdapter))) {
1881  DXGI_ADAPTER_DESC desc;
1882  if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &desc))) {
1884  "Using device %04x:%04x (%ls) - LUID %lu %ld.\n",
1885  desc.VendorId, desc.DeviceId, desc.Description,
1886  desc.AdapterLuid.LowPart,
1887  desc.AdapterLuid.HighPart);
1888  display = vaGetDisplayWin32(&desc.AdapterLuid);
1889  }
1890  IDXGIAdapter_Release(pAdapter);
1891  }
1892  IDXGIFactory2_Release(pDXGIFactory);
1893  }
1894 #if !HAVE_UWP
1895  dlclose(dxgi);
1896 #endif
1897  }
1898 
1899  if (!display) {
1900  av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1901  "from Win32 display.\n");
1902  return AVERROR_UNKNOWN;
1903  }
1904 
1905  av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1906  "Win32 display.\n");
1907  }
1908 #endif
1909 
1910  if (!display) {
1911  if (device)
1912  av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1913  "device %s.\n", device);
1914  else
1915  av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1916  "any default device.\n");
1917  return AVERROR(EINVAL);
1918  }
1919 
1920  ent = av_dict_get(opts, "driver", NULL, 0);
1921  if (ent) {
1922 #if VA_CHECK_VERSION(0, 38, 0)
1923  VAStatus vas;
1924  vas = vaSetDriverName(display, ent->value);
1925  if (vas != VA_STATUS_SUCCESS) {
1926  av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to "
1927  "%s: %d (%s).\n", ent->value, vas, vaErrorStr(vas));
1928  vaTerminate(display);
1929  return AVERROR_EXTERNAL;
1930  }
1931 #else
1932  av_log(ctx, AV_LOG_WARNING, "Driver name setting is not "
1933  "supported with this VAAPI version.\n");
1934 #endif
1935  }
1936 
1937  return vaapi_device_connect(ctx, display);
1938 }
1939 
1941  AVHWDeviceContext *src_ctx,
1942  AVDictionary *opts, int flags)
1943 {
1944 #if HAVE_VAAPI_DRM
1945  if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
1946  AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
1947  VADisplay *display;
1948  VAAPIDevicePriv *priv;
1949  int fd;
1950 
1951  if (src_hwctx->fd < 0) {
1952  av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated "
1953  "device to derive a VA display from.\n");
1954  return AVERROR(EINVAL);
1955  }
1956 
1957 #if CONFIG_LIBDRM
1958  {
1959  int node_type = drmGetNodeTypeFromFd(src_hwctx->fd);
1960  char *render_node;
1961  if (node_type < 0) {
1962  av_log(ctx, AV_LOG_ERROR, "DRM instance fd does not appear "
1963  "to refer to a DRM device.\n");
1964  return AVERROR(EINVAL);
1965  }
1966  if (node_type == DRM_NODE_RENDER) {
1967  fd = src_hwctx->fd;
1968  } else {
1969  render_node = drmGetRenderDeviceNameFromFd(src_hwctx->fd);
1970  if (!render_node) {
1971  av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
1972  "because the device does not have an "
1973  "associated render node.\n");
1974  fd = src_hwctx->fd;
1975  } else {
1976  fd = open(render_node, O_RDWR);
1977  if (fd < 0) {
1978  av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
1979  "because the associated render node "
1980  "could not be opened.\n");
1981  fd = src_hwctx->fd;
1982  } else {
1983  av_log(ctx, AV_LOG_VERBOSE, "Using render node %s "
1984  "in place of non-render DRM device.\n",
1985  render_node);
1986  }
1987  free(render_node);
1988  }
1989  }
1990  }
1991 #else
1992  fd = src_hwctx->fd;
1993 #endif
1994 
1995  priv = av_mallocz(sizeof(*priv));
1996  if (!priv) {
1997  if (fd != src_hwctx->fd) {
1998  // The fd was opened in this function.
1999  close(fd);
2000  }
2001  return AVERROR(ENOMEM);
2002  }
2003 
2004  if (fd == src_hwctx->fd) {
2005  // The fd is inherited from the source context and we are holding
2006  // a reference to that, we don't want to close it from here.
2007  priv->drm_fd = -1;
2008  } else {
2009  priv->drm_fd = fd;
2010  }
2011 
2012  ctx->user_opaque = priv;
2013  ctx->free = &vaapi_device_free;
2014 
2015  display = vaGetDisplayDRM(fd);
2016  if (!display) {
2017  av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
2018  "DRM device.\n");
2019  return AVERROR(EIO);
2020  }
2021 
2022  return vaapi_device_connect(ctx, display);
2023  }
2024 #endif
2025  return AVERROR(ENOSYS);
2026 }
2027 
2030  .name = "VAAPI",
2031 
2032  .device_hwctx_size = sizeof(VAAPIDeviceContext),
2033  .device_hwconfig_size = sizeof(AVVAAPIHWConfig),
2034  .frames_hwctx_size = sizeof(VAAPIFramesContext),
2035 
2036  .device_create = &vaapi_device_create,
2037  .device_derive = &vaapi_device_derive,
2039  .device_uninit = &vaapi_device_uninit,
2040  .frames_get_constraints = &vaapi_frames_get_constraints,
2041  .frames_init = &vaapi_frames_init,
2042  .frames_uninit = &vaapi_frames_uninit,
2043  .frames_get_buffer = &vaapi_get_buffer,
2044  .transfer_get_formats = &vaapi_transfer_get_formats,
2045  .transfer_data_to = &vaapi_transfer_data_to,
2046  .transfer_data_from = &vaapi_transfer_data_from,
2047  .map_to = &vaapi_map_to,
2048  .map_from = &vaapi_map_from,
2049 
2050  .pix_fmts = (const enum AVPixelFormat[]) {
2053  },
2054 };
VAAPIFormat
Definition: hwcontext_vaapi.c:113
formats
formats
Definition: signature.h:48
vaapi_device_derive
static int vaapi_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
Definition: hwcontext_vaapi.c:1940
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:85
FFHWFramesContext::pool_internal
AVBufferPool * pool_internal
Definition: hwcontext_internal.h:101
AVVAAPIFramesContext::attributes
VASurfaceAttrib * attributes
Set by the user to apply surface attributes to all surfaces in the frame pool.
Definition: hwcontext_vaapi.h:93
VAAPIDeviceContext
Definition: hwcontext_vaapi.c:77
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
VAAPIDeviceContext::nb_formats
int nb_formats
Definition: hwcontext_vaapi.c:85
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
VAAPIFramesContext::prime_2_import_unsupported
int prime_2_import_unsupported
Definition: hwcontext_vaapi.c:103
AVVAAPIHWConfig
VAAPI hardware pipeline configuration details.
Definition: hwcontext_vaapi.h:110
HWMapDescriptor::source
AVFrame * source
A reference to the original source of the mapping.
Definition: hwcontext_internal.h:124
message
Definition: api-threadmessage-test.c:47
VAAPIDeviceContext::p
AVVAAPIDeviceContext p
The public AVVAAPIDeviceContext.
Definition: hwcontext_vaapi.c:81
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AV_DRM_MAX_PLANES
@ AV_DRM_MAX_PLANES
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
AVDRMPlaneDescriptor
DRM plane descriptor.
Definition: hwcontext_drm.h:74
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:160
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
pixdesc.h
vaapi_format_from_fourcc
static const VAAPIFormatDescriptor * vaapi_format_from_fourcc(unsigned int fourcc)
Definition: hwcontext_vaapi.c:187
AVFrame::width
int width
Definition: frame.h:446
vaapi_map_to
static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:1607
AVDRMFrameDescriptor::nb_layers
int nb_layers
Number of layers in the frame.
Definition: hwcontext_drm.h:145
AV_PIX_FMT_DRM_PRIME
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:351
data
const char data[16]
Definition: mxf.c:148
AVVAAPIDeviceContext::driver_quirks
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
Definition: hwcontext_vaapi.h:80
vaapi_format_from_pix_fmt
static const VAAPIFormatDescriptor * vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt)
Definition: hwcontext_vaapi.c:197
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AVVAAPIDeviceContext::display
VADisplay display
The VADisplay handle, to be filled by the user.
Definition: hwcontext_vaapi.h:72
AV_HWFRAME_MAP_OVERWRITE
@ AV_HWFRAME_MAP_OVERWRITE
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:522
AVDictionary
Definition: dict.c:34
ff_hwframe_map_create
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition: hwcontext.c:726
AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS
@ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
Definition: hwcontext_vaapi.h:47
HWMapDescriptor::priv
void * priv
Hardware-specific private data associated with the mapping.
Definition: hwcontext_internal.h:139
AVDRMFrameDescriptor
DRM frame descriptor.
Definition: hwcontext_drm.h:133
AVHWFramesConstraints::valid_hw_formats
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:446
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:217
VAAPIMapping::image
VAImage image
Definition: hwcontext_vaapi.c:108
tf_sess_config.config
config
Definition: tf_sess_config.py:33
VAAPIMapping::flags
int flags
Definition: hwcontext_vaapi.c:110
vaapi_frames_init
static int vaapi_frames_init(AVHWFramesContext *hwfc)
Definition: hwcontext_vaapi.c:552
PFN_CREATE_DXGI_FACTORY
HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory)
Definition: hwcontext_d3d11va.c:45
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:395
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:441
AVDRMDeviceContext::fd
int fd
File descriptor of DRM device.
Definition: hwcontext_drm.h:166
vaapi_transfer_data_to
static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_vaapi.c:978
vaapi_pool_alloc
static AVBufferRef * vaapi_pool_alloc(void *opaque, size_t size)
Definition: hwcontext_vaapi.c:508
AVVAAPIFramesContext::surface_ids
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
Definition: hwcontext_vaapi.h:101
VAAPIFormat::fourcc
unsigned int fourcc
Definition: hwcontext_vaapi.c:114
fail
#define fail()
Definition: checkasm.h:182
AVDRMLayerDescriptor::nb_planes
int nb_planes
Number of planes in the layer.
Definition: hwcontext_drm.h:106
AV_HWFRAME_MAP_WRITE
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
Definition: hwcontext.h:516
AVDRMLayerDescriptor::planes
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
Definition: hwcontext_drm.h:110
VAAPIDevicePriv::drm_fd
int drm_fd
Definition: hwcontext_vaapi.c:69
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
AVHWFramesConstraints::min_width
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:459
vaapi_get_buffer
static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
Definition: hwcontext_vaapi.c:713
AVVAAPIFramesContext::nb_attributes
int nb_attributes
Definition: hwcontext_vaapi.h:94
AV_HWFRAME_MAP_DIRECT
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
Definition: hwcontext.h:528
AV_HWFRAME_MAP_READ
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
Definition: hwcontext.h:512
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
VAAPIDeviceContext::formats
VAAPISurfaceFormat * formats
Definition: hwcontext_vaapi.c:84
vaapi_transfer_get_formats
static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
Definition: hwcontext_vaapi.c:727
ff_hwcontext_type_vaapi
const HWContextType ff_hwcontext_type_vaapi
Definition: hwcontext_vaapi.c:2028
AVDRMPlaneDescriptor::offset
ptrdiff_t offset
Offset within that object of this plane.
Definition: hwcontext_drm.h:83
AVDRMLayerDescriptor
DRM layer descriptor.
Definition: hwcontext_drm.h:96
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:148
vaapi_map_frame
static int vaapi_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:800
avassert.h
HWContextType::type
enum AVHWDeviceType type
Definition: hwcontext_internal.h:30
ffhwframesctx
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
Definition: hwcontext_internal.h:115
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
match_string
const char * match_string
Definition: hwcontext_vaapi.c:372
AVHWFramesContext::height
int height
Definition: hwcontext.h:217
AVDRMObjectDescriptor
DRM object descriptor.
Definition: hwcontext_drm.h:48
device_init
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pixelformat)
Definition: v4l2.c:205
AVHWFramesConstraints::valid_sw_formats
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:453
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:62
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:384
AVHWFramesContext::pool
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:178
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1406
VAAPISurfaceFormat::pix_fmt
enum AVPixelFormat pix_fmt
Definition: hwcontext_vaapi.c:73
vaapi_get_image_format
static int vaapi_get_image_format(AVHWDeviceContext *hwdev, enum AVPixelFormat pix_fmt, VAImageFormat **image_format)
Definition: hwcontext_vaapi.c:216
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
info
MIPS optimizations info
Definition: mips.txt:2
DRM_FORMAT_MOD_INVALID
#define DRM_FORMAT_MOD_INVALID
Definition: kmsgrab.c:32
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:304
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AVDRMObjectDescriptor::fd
int fd
DRM PRIME fd for the object.
Definition: hwcontext_drm.h:52
VAAPIFormat::rt_format
unsigned int rt_format
Definition: hwcontext_vaapi.c:115
vaapi_buffer_free
static void vaapi_buffer_free(void *opaque, uint8_t *data)
Definition: hwcontext_vaapi.c:492
if
if(ret)
Definition: filter_design.txt:179
context
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option keep it simple and lowercase description are in without and describe what they for example set the foo of the bar offset is the offset of the field in your context
Definition: writing_filters.txt:91
opts
AVDictionary * opts
Definition: movenc.c:51
NULL
#define NULL
Definition: coverity.c:32
vaapi_device_init
static int vaapi_device_init(AVHWDeviceContext *hwdev)
Definition: hwcontext_vaapi.c:395
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:210
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:709
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
V
#define V
Definition: avdct.c:31
VAAPIFramesContext::p
AVVAAPIFramesContext p
The public AVVAAPIFramesContext.
Definition: hwcontext_vaapi.c:92
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
vaapi_transfer_data_from
static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_vaapi.c:947
AVDRMFrameDescriptor::layers
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
Definition: hwcontext_drm.h:149
vaapi_device_create
static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
Definition: hwcontext_vaapi.c:1694
VAAPIFramesContext::derive_works
int derive_works
Definition: hwcontext_vaapi.c:100
P
#define P
av_frame_copy
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:999
VAAPISurfaceFormat
Definition: hwcontext_vaapi.c:72
size
int size
Definition: twinvq_data.h:10344
vaapi_pix_fmt_from_fourcc
static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
Definition: hwcontext_vaapi.c:206
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:461
vaapi_unmap_frame
static void vaapi_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
Definition: hwcontext_vaapi.c:763
buffer.h
VAAPISurfaceFormat::image_format
VAImageFormat image_format
Definition: hwcontext_vaapi.c:74
friendly_name
const char * friendly_name
Definition: hwcontext_vaapi.c:371
AVDRMObjectDescriptor::size
size_t size
Total size of the object.
Definition: hwcontext_drm.h:58
VAAPIFramesContext::rt_format
unsigned int rt_format
Definition: hwcontext_vaapi.c:98
H
#define H
Definition: pixlet.c:39
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AVHWFramesConstraints::max_width
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:466
AV_PIX_FMT_VAAPI
@ AV_PIX_FMT_VAAPI
Hardware acceleration through VA-API, data[3] contains a VASurfaceID.
Definition: pixfmt.h:126
AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES
@ AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES
The driver does not support surface attributes at all.
Definition: hwcontext_vaapi.h:60
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
AV_HWDEVICE_TYPE_VAAPI
@ AV_HWDEVICE_TYPE_VAAPI
Definition: hwcontext.h:31
AVDRMFrameDescriptor::objects
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
Definition: hwcontext_drm.h:141
vaapi_frames_get_constraints
static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, const void *hwconfig, AVHWFramesConstraints *constraints)
Definition: hwcontext_vaapi.c:233
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AV_VAAPI_DRIVER_QUIRK_USER_SET
@ AV_VAAPI_DRIVER_QUIRK_USER_SET
The quirks field has been set by the user and should not be detected automatically by av_hwdevice_ctx...
Definition: hwcontext_vaapi.h:41
AVDRMObjectDescriptor::format_modifier
uint64_t format_modifier
Format modifier applied to the object (DRM_FORMAT_MOD_*).
Definition: hwcontext_drm.h:65
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
common.h
AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE
@ AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE
The driver does not support the VASurfaceAttribMemoryType attribute, so the surface allocation code w...
Definition: hwcontext_vaapi.h:53
VAAPIFramesContext::nb_attributes
int nb_attributes
Definition: hwcontext_vaapi.c:96
vaapi_device_uninit
static void vaapi_device_uninit(AVHWDeviceContext *hwdev)
Definition: hwcontext_vaapi.c:485
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
hwcontext_drm.h
AVDRMPlaneDescriptor::object_index
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor.
Definition: hwcontext_drm.h:79
vaapi_device_connect
static int vaapi_device_connect(AVHWDeviceContext *ctx, VADisplay display)
Definition: hwcontext_vaapi.c:1668
AVHWFrameTransferDirection
AVHWFrameTransferDirection
Definition: hwcontext.h:403
VAAPIMapping
Definition: hwcontext_vaapi.c:106
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:115
hwcontext_vaapi.h
AVDRMLayerDescriptor::format
uint32_t format
Format of the layer (DRM_FORMAT_*).
Definition: hwcontext_drm.h:100
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:72
quirks
unsigned int quirks
Definition: hwcontext_vaapi.c:373
pixfmt.h
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
AVHWFramesContext::device_ctx
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:134
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
vaapi_driver_quirks_table
static const struct @402 vaapi_driver_quirks_table[]
VAAPIFormat::chroma_planes_swapped
int chroma_planes_swapped
Definition: hwcontext_vaapi.c:117
AVHWFramesConstraints::max_height
int max_height
Definition: hwcontext.h:467
vaapi_device_free
static void vaapi_device_free(AVHWDeviceContext *ctx)
Definition: hwcontext_vaapi.c:1633
AVFrame::hw_frames_ctx
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:725
AVFrame::height
int height
Definition: frame.h:446
AVHWFramesConstraints::min_height
int min_height
Definition: hwcontext.h:460
AVVAAPIFramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_vaapi.h:102
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
VAAPIFormat::pix_fmt
enum AVPixelFormat pix_fmt
Definition: hwcontext_vaapi.c:116
VAAPIFramesContext::attributes
VASurfaceAttrib * attributes
Definition: hwcontext_vaapi.c:95
AVHWFramesContext::initial_pool_size
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:187
desc
const char * desc
Definition: libsvtav1.c:79
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
VAAPIFramesContext
Definition: hwcontext_vaapi.c:88
hwcontext_internal.h
AVVAAPIFramesContext
VAAPI-specific data associated with a frame pool.
Definition: hwcontext_vaapi.h:88
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AVDictionaryEntry
Definition: dict.h:89
vaapi_map_from
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:1620
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
RGBA
#define RGBA(r, g, b, a)
Definition: dvbsubdec.c:42
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
hwcontext.h
AVDRMPlaneDescriptor::pitch
ptrdiff_t pitch
Pitch (linesize) of this plane.
Definition: hwcontext_drm.h:87
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:419
vaapi_map_to_memory
static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:1009
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
HWContextType
Definition: hwcontext_internal.h:29
AVVAAPIDeviceContext
VAAPI connection details.
Definition: hwcontext_vaapi.h:68
AVDictionaryEntry::value
char * value
Definition: dict.h:91
AVDRMDeviceContext
DRM device.
Definition: hwcontext_drm.h:157
vaapi_frames_uninit
static void vaapi_frames_uninit(AVHWFramesContext *hwfc)
Definition: hwcontext_vaapi.c:704
AVDRMFrameDescriptor::nb_objects
int nb_objects
Number of DRM objects making up this frame.
Definition: hwcontext_drm.h:137
HWMapDescriptor
Definition: hwcontext_internal.h:120
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:245
snprintf
#define snprintf
Definition: snprintf.h:34
AV_HWDEVICE_TYPE_DRM
@ AV_HWDEVICE_TYPE_DRM
Definition: hwcontext.h:36
vaapi_format_map
static const VAAPIFormatDescriptor vaapi_format_map[]
Definition: hwcontext_vaapi.c:128
VAAPIDevicePriv
Definition: hwcontext_vaapi.c:64
w32dlfcn.h
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2885
MAP
#define MAP(va, rt, av, swap_uv)
Definition: hwcontext_vaapi.c:120