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