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