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