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