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