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  VAAPIFramesContext *src_vafc = src_fc->internal->priv;
1030  AVHWFramesContext *dst_fc =
1032  AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
1033  const AVDRMFrameDescriptor *desc;
1034  const VAAPIFormatDescriptor *format_desc;
1035  VASurfaceID surface_id;
1036  VAStatus vas = VA_STATUS_SUCCESS;
1037  int use_prime2;
1038  uint32_t va_fourcc;
1039  int err, i, j;
1040 
1041  desc = (AVDRMFrameDescriptor*)src->data[0];
1042 
1043  if (desc->nb_objects != 1) {
1044  av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames "
1045  "made from a single DRM object.\n");
1046  return AVERROR(EINVAL);
1047  }
1048 
1049  va_fourcc = 0;
1050  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
1051  if (desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats)
1052  continue;
1053  for (j = 0; j < desc->nb_layers; j++) {
1054  if (desc->layers[j].format !=
1055  vaapi_drm_format_map[i].layer_formats[j])
1056  break;
1057  }
1058  if (j != desc->nb_layers)
1059  continue;
1060  va_fourcc = vaapi_drm_format_map[i].va_fourcc;
1061  break;
1062  }
1063  if (!va_fourcc) {
1064  av_log(dst_fc, AV_LOG_ERROR, "DRM format not supported "
1065  "by VAAPI.\n");
1066  return AVERROR(EINVAL);
1067  }
1068 
1069  av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as "
1070  "%08x.\n", desc->objects[0].fd, va_fourcc);
1071 
1072  format_desc = vaapi_format_from_fourcc(va_fourcc);
1073  av_assert0(format_desc);
1074 
1075  use_prime2 = !src_vafc->prime_2_import_unsupported &&
1076  desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID;
1077  if (use_prime2) {
1078  VADRMPRIMESurfaceDescriptor prime_desc;
1079  VASurfaceAttrib prime_attrs[2] = {
1080  {
1081  .type = VASurfaceAttribMemoryType,
1082  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1083  .value.type = VAGenericValueTypeInteger,
1084  .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1085  },
1086  {
1087  .type = VASurfaceAttribExternalBufferDescriptor,
1088  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1089  .value.type = VAGenericValueTypePointer,
1090  .value.value.p = &prime_desc,
1091  }
1092  };
1093  prime_desc.fourcc = va_fourcc;
1094  prime_desc.width = src_fc->width;
1095  prime_desc.height = src_fc->height;
1096  prime_desc.num_objects = desc->nb_objects;
1097  for (i = 0; i < desc->nb_objects; ++i) {
1098  prime_desc.objects[i].fd = desc->objects[i].fd;
1099  prime_desc.objects[i].size = desc->objects[i].size;
1100  prime_desc.objects[i].drm_format_modifier =
1101  desc->objects[i].format_modifier;
1102  }
1103 
1104  prime_desc.num_layers = desc->nb_layers;
1105  for (i = 0; i < desc->nb_layers; ++i) {
1106  prime_desc.layers[i].drm_format = desc->layers[i].format;
1107  prime_desc.layers[i].num_planes = desc->layers[i].nb_planes;
1108  for (j = 0; j < desc->layers[i].nb_planes; ++j) {
1109  prime_desc.layers[i].object_index[j] =
1110  desc->layers[i].planes[j].object_index;
1111  prime_desc.layers[i].offset[j] = desc->layers[i].planes[j].offset;
1112  prime_desc.layers[i].pitch[j] = desc->layers[i].planes[j].pitch;
1113  }
1114 
1115  if (format_desc->chroma_planes_swapped &&
1116  desc->layers[i].nb_planes == 3) {
1117  FFSWAP(uint32_t, prime_desc.layers[i].pitch[1],
1118  prime_desc.layers[i].pitch[2]);
1119  FFSWAP(uint32_t, prime_desc.layers[i].offset[1],
1120  prime_desc.layers[i].offset[2]);
1121  }
1122  }
1123 
1124  /*
1125  * We can query for PRIME_2 support with vaQuerySurfaceAttributes, but that
1126  * that needs the config_id which we don't have here . Both Intel and
1127  * Gallium seem to do the correct error checks, so lets just try the
1128  * PRIME_2 import first.
1129  */
1130  vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1131  src->width, src->height, &surface_id, 1,
1132  prime_attrs, FF_ARRAY_ELEMS(prime_attrs));
1133  if (vas != VA_STATUS_SUCCESS)
1134  src_vafc->prime_2_import_unsupported = 1;
1135  }
1136 
1137  if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1138  int k;
1139  unsigned long buffer_handle;
1140  VASurfaceAttribExternalBuffers buffer_desc;
1141  VASurfaceAttrib buffer_attrs[2] = {
1142  {
1143  .type = VASurfaceAttribMemoryType,
1144  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1145  .value.type = VAGenericValueTypeInteger,
1146  .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1147  },
1148  {
1149  .type = VASurfaceAttribExternalBufferDescriptor,
1150  .flags = VA_SURFACE_ATTRIB_SETTABLE,
1151  .value.type = VAGenericValueTypePointer,
1152  .value.value.p = &buffer_desc,
1153  }
1154  };
1155 
1156  buffer_handle = desc->objects[0].fd;
1157  buffer_desc.pixel_format = va_fourcc;
1158  buffer_desc.width = src_fc->width;
1159  buffer_desc.height = src_fc->height;
1160  buffer_desc.data_size = desc->objects[0].size;
1161  buffer_desc.buffers = &buffer_handle;
1162  buffer_desc.num_buffers = 1;
1163  buffer_desc.flags = 0;
1164 
1165  k = 0;
1166  for (i = 0; i < desc->nb_layers; i++) {
1167  for (j = 0; j < desc->layers[i].nb_planes; j++) {
1168  buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch;
1169  buffer_desc.offsets[k] = desc->layers[i].planes[j].offset;
1170  ++k;
1171  }
1172  }
1173  buffer_desc.num_planes = k;
1174 
1175  if (format_desc->chroma_planes_swapped &&
1176  buffer_desc.num_planes == 3) {
1177  FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1178  FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1179  }
1180 
1181  vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1182  src->width, src->height,
1183  &surface_id, 1,
1184  buffer_attrs, FF_ARRAY_ELEMS(buffer_attrs));
1185  }
1186  if (vas != VA_STATUS_SUCCESS) {
1187  av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM "
1188  "object: %d (%s).\n", vas, vaErrorStr(vas));
1189  return AVERROR(EIO);
1190  }
1191  av_log(dst_fc, AV_LOG_DEBUG, "Create surface %#x.\n", surface_id);
1192 
1193  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
1194  &vaapi_unmap_from_drm,
1195  (void*)(uintptr_t)surface_id);
1196  if (err < 0)
1197  return err;
1198 
1199  dst->width = src->width;
1200  dst->height = src->height;
1201  dst->data[3] = (uint8_t*)(uintptr_t)surface_id;
1202 
1203  av_log(dst_fc, AV_LOG_DEBUG, "Mapped DRM object %d to "
1204  "surface %#x.\n", desc->objects[0].fd, surface_id);
1205 
1206  return 0;
1207 }
1208 
1209 #if VA_CHECK_VERSION(1, 1, 0)
1210 static void vaapi_unmap_to_drm_esh(AVHWFramesContext *hwfc,
1211  HWMapDescriptor *hwmap)
1212 {
1213  AVDRMFrameDescriptor *drm_desc = hwmap->priv;
1214  int i;
1215 
1216  for (i = 0; i < drm_desc->nb_objects; i++)
1217  close(drm_desc->objects[i].fd);
1218 
1219  av_freep(&drm_desc);
1220 }
1221 
1222 static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
1223  const AVFrame *src, int flags)
1224 {
1225  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1226  VASurfaceID surface_id;
1227  VAStatus vas;
1228  VADRMPRIMESurfaceDescriptor va_desc;
1229  AVDRMFrameDescriptor *drm_desc = NULL;
1230  uint32_t export_flags;
1231  int err, i, j;
1232 
1233  surface_id = (VASurfaceID)(uintptr_t)src->data[3];
1234 
1235  export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1236  if (flags & AV_HWFRAME_MAP_READ)
1237  export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1239  export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1240 
1241  vas = vaExportSurfaceHandle(hwctx->display, surface_id,
1242  VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1243  export_flags, &va_desc);
1244  if (vas != VA_STATUS_SUCCESS) {
1245  if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1246  return AVERROR(ENOSYS);
1247  av_log(hwfc, AV_LOG_ERROR, "Failed to export surface %#x: "
1248  "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1249  return AVERROR(EIO);
1250  }
1251 
1252  drm_desc = av_mallocz(sizeof(*drm_desc));
1253  if (!drm_desc) {
1254  err = AVERROR(ENOMEM);
1255  goto fail;
1256  }
1257 
1258  // By some bizarre coincidence, these structures are very similar...
1259  drm_desc->nb_objects = va_desc.num_objects;
1260  for (i = 0; i < va_desc.num_objects; i++) {
1261  drm_desc->objects[i].fd = va_desc.objects[i].fd;
1262  drm_desc->objects[i].size = va_desc.objects[i].size;
1263  drm_desc->objects[i].format_modifier =
1264  va_desc.objects[i].drm_format_modifier;
1265  }
1266  drm_desc->nb_layers = va_desc.num_layers;
1267  for (i = 0; i < va_desc.num_layers; i++) {
1268  drm_desc->layers[i].format = va_desc.layers[i].drm_format;
1269  drm_desc->layers[i].nb_planes = va_desc.layers[i].num_planes;
1270  for (j = 0; j < va_desc.layers[i].num_planes; j++) {
1271  drm_desc->layers[i].planes[j].object_index =
1272  va_desc.layers[i].object_index[j];
1273  drm_desc->layers[i].planes[j].offset =
1274  va_desc.layers[i].offset[j];
1275  drm_desc->layers[i].planes[j].pitch =
1276  va_desc.layers[i].pitch[j];
1277  }
1278  }
1279 
1280  err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
1281  &vaapi_unmap_to_drm_esh, drm_desc);
1282  if (err < 0)
1283  goto fail;
1284 
1285  dst->width = src->width;
1286  dst->height = src->height;
1287  dst->data[0] = (uint8_t*)drm_desc;
1288 
1289  return 0;
1290 
1291 fail:
1292  for (i = 0; i < va_desc.num_objects; i++)
1293  close(va_desc.objects[i].fd);
1294  av_freep(&drm_desc);
1295  return err;
1296 }
1297 #endif
1298 
1299 #if VA_CHECK_VERSION(0, 36, 0)
1300 typedef struct VAAPIDRMImageBufferMapping {
1301  VAImage image;
1302  VABufferInfo buffer_info;
1303 
1304  AVDRMFrameDescriptor drm_desc;
1305 } VAAPIDRMImageBufferMapping;
1306 
1307 static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc,
1308  HWMapDescriptor *hwmap)
1309 {
1310  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1311  VAAPIDRMImageBufferMapping *mapping = hwmap->priv;
1312  VASurfaceID surface_id;
1313  VAStatus vas;
1314 
1315  surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
1316  av_log(hwfc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from DRM.\n",
1317  surface_id);
1318 
1319  // DRM PRIME file descriptors are closed by vaReleaseBufferHandle(),
1320  // so we shouldn't close them separately.
1321 
1322  vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1323  if (vas != VA_STATUS_SUCCESS) {
1324  av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer "
1325  "handle of image %#x (derived from surface %#x): "
1326  "%d (%s).\n", mapping->image.buf, surface_id,
1327  vas, vaErrorStr(vas));
1328  }
1329 
1330  vas = vaDestroyImage(hwctx->display, mapping->image.image_id);
1331  if (vas != VA_STATUS_SUCCESS) {
1332  av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image "
1333  "derived from surface %#x: %d (%s).\n",
1334  surface_id, vas, vaErrorStr(vas));
1335  }
1336 
1337  av_free(mapping);
1338 }
1339 
1340 static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
1341  const AVFrame *src, int flags)
1342 {
1343  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1344  VAAPIDRMImageBufferMapping *mapping = NULL;
1345  VASurfaceID surface_id;
1346  VAStatus vas;
1347  int err, i, p;
1348 
1349  surface_id = (VASurfaceID)(uintptr_t)src->data[3];
1350  av_log(hwfc, AV_LOG_DEBUG, "Map VAAPI surface %#x to DRM.\n",
1351  surface_id);
1352 
1353  mapping = av_mallocz(sizeof(*mapping));
1354  if (!mapping)
1355  return AVERROR(ENOMEM);
1356 
1357  vas = vaDeriveImage(hwctx->display, surface_id,
1358  &mapping->image);
1359  if (vas != VA_STATUS_SUCCESS) {
1360  av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
1361  "surface %#x: %d (%s).\n",
1362  surface_id, vas, vaErrorStr(vas));
1363  err = AVERROR(EIO);
1364  goto fail;
1365  }
1366 
1367  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
1368  if (vaapi_drm_format_map[i].va_fourcc ==
1369  mapping->image.format.fourcc)
1370  break;
1371  }
1372  if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) {
1373  av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for "
1374  "VAAPI format %#x.\n", mapping->image.format.fourcc);
1375  err = AVERROR(EINVAL);
1376  goto fail_derived;
1377  }
1378 
1379  mapping->buffer_info.mem_type =
1380  VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1381 
1382  mapping->drm_desc.nb_layers =
1383  vaapi_drm_format_map[i].nb_layer_formats;
1384  if (mapping->drm_desc.nb_layers > 1) {
1385  if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1386  av_log(hwfc, AV_LOG_ERROR, "Image properties do not match "
1387  "expected format: got %d planes, but expected %d.\n",
1388  mapping->image.num_planes, mapping->drm_desc.nb_layers);
1389  err = AVERROR(EINVAL);
1390  goto fail_derived;
1391  }
1392 
1393  for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1394  mapping->drm_desc.layers[p] = (AVDRMLayerDescriptor) {
1395  .format = vaapi_drm_format_map[i].layer_formats[p],
1396  .nb_planes = 1,
1397  .planes[0] = {
1398  .object_index = 0,
1399  .offset = mapping->image.offsets[p],
1400  .pitch = mapping->image.pitches[p],
1401  },
1402  };
1403  }
1404  } else {
1405  mapping->drm_desc.layers[0].format =
1406  vaapi_drm_format_map[i].layer_formats[0];
1407  mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1408  for (p = 0; p < mapping->image.num_planes; p++) {
1409  mapping->drm_desc.layers[0].planes[p] = (AVDRMPlaneDescriptor) {
1410  .object_index = 0,
1411  .offset = mapping->image.offsets[p],
1412  .pitch = mapping->image.pitches[p],
1413  };
1414  }
1415  }
1416 
1417  vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf,
1418  &mapping->buffer_info);
1419  if (vas != VA_STATUS_SUCCESS) {
1420  av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer "
1421  "handle from image %#x (derived from surface %#x): "
1422  "%d (%s).\n", mapping->image.buf, surface_id,
1423  vas, vaErrorStr(vas));
1424  err = AVERROR(EIO);
1425  goto fail_derived;
1426  }
1427 
1428  av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n",
1429  mapping->buffer_info.handle);
1430 
1431  mapping->drm_desc.nb_objects = 1;
1432  mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) {
1433  .fd = mapping->buffer_info.handle,
1434  .size = mapping->image.data_size,
1435  // There is no way to get the format modifier with this API.
1436  .format_modifier = DRM_FORMAT_MOD_INVALID,
1437  };
1438 
1439  err = ff_hwframe_map_create(src->hw_frames_ctx,
1440  dst, src, &vaapi_unmap_to_drm_abh,
1441  mapping);
1442  if (err < 0)
1443  goto fail_mapped;
1444 
1445  dst->data[0] = (uint8_t*)&mapping->drm_desc;
1446  dst->width = src->width;
1447  dst->height = src->height;
1448 
1449  return 0;
1450 
1451 fail_mapped:
1452  vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1453 fail_derived:
1454  vaDestroyImage(hwctx->display, mapping->image.image_id);
1455 fail:
1456  av_freep(&mapping);
1457  return err;
1458 }
1459 #endif
1460 
1461 static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
1462  const AVFrame *src, int flags)
1463 {
1464 #if VA_CHECK_VERSION(1, 1, 0)
1465  int err;
1466  err = vaapi_map_to_drm_esh(hwfc, dst, src, flags);
1467  if (err != AVERROR(ENOSYS))
1468  return err;
1469 #endif
1470 #if VA_CHECK_VERSION(0, 36, 0)
1471  return vaapi_map_to_drm_abh(hwfc, dst, src, flags);
1472 #endif
1473  return AVERROR(ENOSYS);
1474 }
1475 
1476 #endif /* CONFIG_LIBDRM */
1477 
1478 static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
1479  const AVFrame *src, int flags)
1480 {
1481  switch (src->format) {
1482 #if CONFIG_LIBDRM
1483  case AV_PIX_FMT_DRM_PRIME:
1484  return vaapi_map_from_drm(hwfc, dst, src, flags);
1485 #endif
1486  default:
1487  return AVERROR(ENOSYS);
1488  }
1489 }
1490 
1492  const AVFrame *src, int flags)
1493 {
1494  switch (dst->format) {
1495 #if CONFIG_LIBDRM
1496  case AV_PIX_FMT_DRM_PRIME:
1497  return vaapi_map_to_drm(hwfc, dst, src, flags);
1498 #endif
1499  default:
1500  return vaapi_map_to_memory(hwfc, dst, src, flags);
1501  }
1502 }
1503 
1505 {
1506  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1507  VAAPIDevicePriv *priv = ctx->user_opaque;
1508 
1509  if (hwctx->display)
1510  vaTerminate(hwctx->display);
1511 
1512 #if HAVE_VAAPI_X11
1513  if (priv->x11_display)
1514  XCloseDisplay(priv->x11_display);
1515 #endif
1516 
1517  if (priv->drm_fd >= 0)
1518  close(priv->drm_fd);
1519 
1520  av_freep(&priv);
1521 }
1522 
1523 #if CONFIG_VAAPI_1
1524 static void vaapi_device_log_error(void *context, const char *message)
1525 {
1527 
1528  av_log(ctx, AV_LOG_ERROR, "libva: %s", message);
1529 }
1530 
1531 static void vaapi_device_log_info(void *context, const char *message)
1532 {
1534 
1535  av_log(ctx, AV_LOG_VERBOSE, "libva: %s", message);
1536 }
1537 #endif
1538 
1540  VADisplay display)
1541 {
1542  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1543  int major, minor;
1544  VAStatus vas;
1545 
1546 #if CONFIG_VAAPI_1
1547  vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
1548  vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
1549 #endif
1550 
1551  hwctx->display = display;
1552 
1553  vas = vaInitialize(display, &major, &minor);
1554  if (vas != VA_STATUS_SUCCESS) {
1555  av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
1556  "connection: %d (%s).\n", vas, vaErrorStr(vas));
1557  return AVERROR(EIO);
1558  }
1559  av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
1560  "version %d.%d\n", major, minor);
1561 
1562  return 0;
1563 }
1564 
1565 static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
1566  AVDictionary *opts, int flags)
1567 {
1568  VAAPIDevicePriv *priv;
1569  VADisplay display = NULL;
1570  const AVDictionaryEntry *ent;
1571  int try_drm, try_x11, try_all;
1572 
1573  priv = av_mallocz(sizeof(*priv));
1574  if (!priv)
1575  return AVERROR(ENOMEM);
1576 
1577  priv->drm_fd = -1;
1578 
1579  ctx->user_opaque = priv;
1580  ctx->free = vaapi_device_free;
1581 
1582  ent = av_dict_get(opts, "connection_type", NULL, 0);
1583  if (ent) {
1584  try_all = try_drm = try_x11 = 0;
1585  if (!strcmp(ent->value, "drm")) {
1586  try_drm = 1;
1587  } else if (!strcmp(ent->value, "x11")) {
1588  try_x11 = 1;
1589  } else {
1590  av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n",
1591  ent->value);
1592  return AVERROR(EINVAL);
1593  }
1594  } else {
1595  try_all = 1;
1596  try_drm = HAVE_VAAPI_DRM;
1597  try_x11 = HAVE_VAAPI_X11;
1598  }
1599 
1600 #if HAVE_VAAPI_DRM
1601  while (!display && try_drm) {
1602  // If the device is specified, try to open it as a DRM device node.
1603  // If not, look for a usable render node, possibly restricted to those
1604  // using a specified kernel driver.
1605  int loglevel = try_all ? AV_LOG_VERBOSE : AV_LOG_ERROR;
1606  if (device) {
1607  priv->drm_fd = open(device, O_RDWR);
1608  if (priv->drm_fd < 0) {
1609  av_log(ctx, loglevel, "Failed to open %s as "
1610  "DRM device node.\n", device);
1611  break;
1612  }
1613  } else {
1614  char path[64];
1615  int n, max_devices = 8;
1616 #if CONFIG_LIBDRM
1617  const AVDictionaryEntry *kernel_driver;
1618  kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0);
1619 #endif
1620  for (n = 0; n < max_devices; n++) {
1621  snprintf(path, sizeof(path),
1622  "/dev/dri/renderD%d", 128 + n);
1623  priv->drm_fd = open(path, O_RDWR);
1624  if (priv->drm_fd < 0) {
1625  av_log(ctx, AV_LOG_VERBOSE, "Cannot open "
1626  "DRM render node for device %d.\n", n);
1627  break;
1628  }
1629 #if CONFIG_LIBDRM
1630  if (kernel_driver) {
1631  drmVersion *info;
1632  info = drmGetVersion(priv->drm_fd);
1633  if (strcmp(kernel_driver->value, info->name)) {
1634  av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d "
1635  "with non-matching kernel driver (%s).\n",
1636  n, info->name);
1637  drmFreeVersion(info);
1638  close(priv->drm_fd);
1639  priv->drm_fd = -1;
1640  continue;
1641  }
1642  av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1643  "DRM render node for device %d, "
1644  "with matching kernel driver (%s).\n",
1645  n, info->name);
1646  drmFreeVersion(info);
1647  } else
1648 #endif
1649  {
1650  av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1651  "DRM render node for device %d.\n", n);
1652  }
1653  break;
1654  }
1655  if (n >= max_devices)
1656  break;
1657  }
1658 
1659  display = vaGetDisplayDRM(priv->drm_fd);
1660  if (!display) {
1661  av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display "
1662  "from DRM device %s.\n", device);
1663  return AVERROR_EXTERNAL;
1664  }
1665  break;
1666  }
1667 #endif
1668 
1669 #if HAVE_VAAPI_X11
1670  if (!display && try_x11) {
1671  // Try to open the device as an X11 display.
1672  priv->x11_display = XOpenDisplay(device);
1673  if (!priv->x11_display) {
1674  av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
1675  "%s.\n", XDisplayName(device));
1676  } else {
1677  display = vaGetDisplay(priv->x11_display);
1678  if (!display) {
1679  av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1680  "from X11 display %s.\n", XDisplayName(device));
1681  return AVERROR_UNKNOWN;
1682  }
1683 
1684  av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1685  "X11 display %s.\n", XDisplayName(device));
1686  }
1687  }
1688 #endif
1689 
1690  if (!display) {
1691  if (device)
1692  av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1693  "device %s.\n", device);
1694  else
1695  av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1696  "any default device.\n");
1697  return AVERROR(EINVAL);
1698  }
1699 
1700  ent = av_dict_get(opts, "driver", NULL, 0);
1701  if (ent) {
1702 #if VA_CHECK_VERSION(0, 38, 0)
1703  VAStatus vas;
1704  vas = vaSetDriverName(display, ent->value);
1705  if (vas != VA_STATUS_SUCCESS) {
1706  av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to "
1707  "%s: %d (%s).\n", ent->value, vas, vaErrorStr(vas));
1708  vaTerminate(display);
1709  return AVERROR_EXTERNAL;
1710  }
1711 #else
1712  av_log(ctx, AV_LOG_WARNING, "Driver name setting is not "
1713  "supported with this VAAPI version.\n");
1714 #endif
1715  }
1716 
1717  return vaapi_device_connect(ctx, display);
1718 }
1719 
1721  AVHWDeviceContext *src_ctx,
1722  AVDictionary *opts, int flags)
1723 {
1724 #if HAVE_VAAPI_DRM
1725  if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
1726  AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
1727  VADisplay *display;
1728  VAAPIDevicePriv *priv;
1729  int fd;
1730 
1731  if (src_hwctx->fd < 0) {
1732  av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated "
1733  "device to derive a VA display from.\n");
1734  return AVERROR(EINVAL);
1735  }
1736 
1737 #if CONFIG_LIBDRM
1738  {
1739  int node_type = drmGetNodeTypeFromFd(src_hwctx->fd);
1740  char *render_node;
1741  if (node_type < 0) {
1742  av_log(ctx, AV_LOG_ERROR, "DRM instance fd does not appear "
1743  "to refer to a DRM device.\n");
1744  return AVERROR(EINVAL);
1745  }
1746  if (node_type == DRM_NODE_RENDER) {
1747  fd = src_hwctx->fd;
1748  } else {
1749  render_node = drmGetRenderDeviceNameFromFd(src_hwctx->fd);
1750  if (!render_node) {
1751  av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
1752  "because the device does not have an "
1753  "associated render node.\n");
1754  fd = src_hwctx->fd;
1755  } else {
1756  fd = open(render_node, O_RDWR);
1757  if (fd < 0) {
1758  av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
1759  "because the associated render node "
1760  "could not be opened.\n");
1761  fd = src_hwctx->fd;
1762  } else {
1763  av_log(ctx, AV_LOG_VERBOSE, "Using render node %s "
1764  "in place of non-render DRM device.\n",
1765  render_node);
1766  }
1767  free(render_node);
1768  }
1769  }
1770  }
1771 #else
1772  fd = src_hwctx->fd;
1773 #endif
1774 
1775  priv = av_mallocz(sizeof(*priv));
1776  if (!priv) {
1777  if (fd != src_hwctx->fd) {
1778  // The fd was opened in this function.
1779  close(fd);
1780  }
1781  return AVERROR(ENOMEM);
1782  }
1783 
1784  if (fd == src_hwctx->fd) {
1785  // The fd is inherited from the source context and we are holding
1786  // a reference to that, we don't want to close it from here.
1787  priv->drm_fd = -1;
1788  } else {
1789  priv->drm_fd = fd;
1790  }
1791 
1792  ctx->user_opaque = priv;
1793  ctx->free = &vaapi_device_free;
1794 
1795  display = vaGetDisplayDRM(fd);
1796  if (!display) {
1797  av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
1798  "DRM device.\n");
1799  return AVERROR(EIO);
1800  }
1801 
1802  return vaapi_device_connect(ctx, display);
1803  }
1804 #endif
1805  return AVERROR(ENOSYS);
1806 }
1807 
1810  .name = "VAAPI",
1811 
1812  .device_hwctx_size = sizeof(AVVAAPIDeviceContext),
1813  .device_priv_size = sizeof(VAAPIDeviceContext),
1814  .device_hwconfig_size = sizeof(AVVAAPIHWConfig),
1815  .frames_hwctx_size = sizeof(AVVAAPIFramesContext),
1816  .frames_priv_size = sizeof(VAAPIFramesContext),
1817 
1818  .device_create = &vaapi_device_create,
1819  .device_derive = &vaapi_device_derive,
1821  .device_uninit = &vaapi_device_uninit,
1822  .frames_get_constraints = &vaapi_frames_get_constraints,
1823  .frames_init = &vaapi_frames_init,
1824  .frames_uninit = &vaapi_frames_uninit,
1825  .frames_get_buffer = &vaapi_get_buffer,
1826  .transfer_get_formats = &vaapi_transfer_get_formats,
1827  .transfer_data_to = &vaapi_transfer_data_to,
1828  .transfer_data_from = &vaapi_transfer_data_from,
1829  .map_to = &vaapi_map_to,
1830  .map_from = &vaapi_map_from,
1831 
1832  .pix_fmts = (const enum AVPixelFormat[]) {
1835  },
1836 };
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:1720
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
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
AV_HWFRAME_MAP_WRITE
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
Definition: hwcontext.h:528
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:109
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:317
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:389
vaapi_map_to
static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:1478
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:318
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
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:737
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:338
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:453
AVDRMDeviceContext::fd
int fd
File descriptor of DRM device.
Definition: hwcontext_drm.h:166
AV_HWFRAME_MAP_READ
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
Definition: hwcontext.h:524
vaapi_transfer_data_to
static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_vaapi.c:928
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
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:127
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:1808
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:97
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:194
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:1318
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
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
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:537
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
vaapi_driver_quirks_table
static const struct @305 vaapi_driver_quirks_table[]
V
#define V
Definition: avdct.c:30
src
#define src
Definition: vp8dsp.c:255
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:1565
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:678
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
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
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:404
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
VAAPIFramesContext::rt_format
unsigned int rt_format
Definition: hwcontext_vaapi.c:79
H
#define H
Definition: pixlet.c:39
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AVHWFramesConstraints::max_width
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h: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
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
AVDRMObjectDescriptor::format_modifier
uint64_t format_modifier
Format modifier applied to the object (DRM_FORMAT_MOD_*).
Definition: hwcontext_drm.h:65
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
common.h
VAAPIFramesContext::nb_attributes
int nb_attributes
Definition: hwcontext_vaapi.c: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:263
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:1539
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: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
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
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:1504
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:643
AVFrame::height
int height
Definition: frame.h:389
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_DIRECT
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
Definition: hwcontext.h:540
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
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:79
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:34
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:1491
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
RGBA
#define RGBA(r, g, b, a)
Definition: dvbsubdec.c:40
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:362
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:28
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
HWMapDescriptor
Definition: hwcontext_internal.h:132
AV_DRM_MAX_PLANES
@ AV_DRM_MAX_PLANES
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:239
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:2580
MAP
#define MAP(va, rt, av, swap_uv)
Definition: hwcontext_vaapi.c:101