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