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.
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++)
150  if (vaapi_format_map[i].fourcc == fourcc)
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++)
160  if (vaapi_format_map[i].pix_fmt == pix_fmt)
161  return &vaapi_format_map[i];
162  return NULL;
163 }
164 
166 {
168  desc = vaapi_format_from_fourcc(fourcc);
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;
237  pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
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;
276  pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
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;
389  pix_fmt = vaapi_pix_fmt_from_fourcc(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",
395  fourcc, av_get_pix_fmt_name(pix_fmt));
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 
467 static AVBufferRef *vaapi_pool_alloc(void *opaque, int size)
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 
524  desc = vaapi_format_from_pix_fmt(hwfc->sw_format);
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;
679  frame->format = AV_PIX_FMT_VAAPI;
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  }
716  pix_fmts[k] = AV_PIX_FMT_NONE;
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 &&
814  ((flags & AV_HWFRAME_MAP_DIRECT) || !(flags & AV_HWFRAME_MAP_READ))) {
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  }
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 
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 
908  err = vaapi_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ);
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;
1167  if (flags & AV_HWFRAME_MAP_WRITE)
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 
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 {
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 {
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 };
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
#define NULL
Definition: coverity.c:32
enum AVPixelFormat pix_fmt
#define P
static enum AVPixelFormat pix_fmt
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
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
VAAPI-specific data associated with a frame pool.
static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static void vaapi_device_free(AVHWDeviceContext *ctx)
const char * desc
Definition: libsvtav1.c:79
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pixelformat)
Definition: v4l2.c:192
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
Memory handling functions.
VASurfaceAttrib * attributes
Set by the user to apply surface attributes to all surfaces in the frame pool.
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:499
The driver does not support surface attributes at all.
uint32_t fourcc
Definition: vaapi_decode.c:239
The mapping must be writeable.
Definition: hwcontext.h:528
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:229
static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
GLint GLenum type
Definition: opengl_enc.c:104
#define RGBA(r, g, b, a)
Definition: dvbsubdec.c:39
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
static const VAAPIFormatDescriptor * vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt)
static int vaapi_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:478
int nb_objects
Number of DRM objects making up this frame.
static const VAAPIFormatDescriptor * vaapi_format_from_fourcc(unsigned int fourcc)
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:647
static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vaapi_device_init(AVHWDeviceContext *hwdev)
DRM frame descriptor.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AVBufferPool * pool_internal
enum AVHWDeviceType type
uint8_t
#define av_malloc(s)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:190
static const VAAPIFormatDescriptor vaapi_format_map[]
static void vaapi_buffer_free(void *opaque, uint8_t *data)
static int vaapi_device_connect(AVHWDeviceContext *ctx, VADisplay display)
size_t size
Total size of the object.
Definition: hwcontext_drm.h:58
DRM plane descriptor.
Definition: hwcontext_drm.h:74
static void vaapi_frames_uninit(AVHWFramesContext *hwfc)
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
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
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:113
ptrdiff_t size
Definition: opengl_enc.c:100
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
#define av_log(a,...)
static int vaapi_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
int fd
DRM PRIME fd for the object.
Definition: hwcontext_drm.h:52
#define src
Definition: vp8dsp.c:254
int nb_layers
Number of layers in the frame.
DRM layer descriptor.
Definition: hwcontext_drm.h:96
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor...
Definition: hwcontext_drm.h:79
int width
Definition: frame.h:366
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
VAAPI hardware pipeline configuration details.
The mapping must be direct.
Definition: hwcontext.h:540
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
ptrdiff_t pitch
Pitch (linesize) of this plane.
Definition: hwcontext_drm.h:87
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
The driver does not support the VASurfaceAttribMemoryType attribute, so the surface allocation code w...
DRM object descriptor.
Definition: hwcontext_drm.h:48
simple assert() macros that are a bit more flexible than ISO C assert().
int nb_planes
Number of planes in the layer.
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:29
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:79
VASurfaceAttrib * attributes
#define fail()
Definition: checkasm.h:123
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:812
const char * match_string
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:199
AVDictionary * opts
Definition: movenc.c:50
MIPS optimizations info
Definition: mips.txt:2
static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
AVFrame * source
A reference to the original source of the mapping.
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:149
#define DRM_FORMAT_MOD_INVALID
Definition: kmsgrab.c:32
AVFormatContext * ctx
Definition: movenc.c:48
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
#define MAP(va, rt, av, swap_uv)
static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
uint64_t format_modifier
Format modifier applied to the object (DRM_FORMAT_MOD_*).
Definition: hwcontext_drm.h:65
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:245
static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static void vaapi_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
#define FF_ARRAY_ELEMS(a)
if(ret)
VADisplay display
The VADisplay handle, to be filled by the user.
VAAPISurfaceFormat * formats
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:381
static const struct @307 vaapi_driver_quirks_table[]
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:471
void * priv
Hardware-specific private data associated with the mapping.
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:534
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:453
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:339
const char * friendly_name
uint8_t * data
The data buffer.
Definition: buffer.h:89
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int vaapi_frames_init(AVHWFramesContext *hwfc)
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:162
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
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
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:328
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
refcounted data buffer API
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
const VDPAUPixFmtMap * map
static int vaapi_get_image_format(AVHWDeviceContext *hwdev, enum AVPixelFormat pix_fmt, VAImageFormat **image_format)
#define snprintf
Definition: snprintf.h:34
API-specific header for AV_HWDEVICE_TYPE_DRM.
AVHWFramesInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:134
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:300
static void vaapi_device_uninit(AVHWDeviceContext *hwdev)
#define flags(name, subs,...)
Definition: cbs_av1.c:560
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
void * user_opaque
Arbitrary user data, to be used e.g.
Definition: hwcontext.h:109
VAImageFormat image_format
enum AVPixelFormat pix_fmt
static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
A reference to a data buffer.
Definition: buffer.h:81
common internal and external API header
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
int fd
File descriptor of DRM device.
static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, const void *hwconfig, AVHWFramesConstraints *constraints)
uint32_t format
Format of the layer (DRM_FORMAT_*).
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
AVHWFrameTransferDirection
Definition: hwcontext.h:415
static AVBufferRef * vaapi_pool_alloc(void *opaque, int size)
pixel format definitions
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:190
#define av_free(p)
char * value
Definition: dict.h:87
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
ptrdiff_t offset
Offset within that object of this plane.
Definition: hwcontext_drm.h:83
#define H
Definition: pixlet.c:39
unsigned int quirks
VAAPI connection details.
VAConfigID config_id
ID of a VAAPI pipeline configuration.
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
Definition: hwcontext.h:104
int height
Definition: frame.h:366
const HWContextType ff_hwcontext_type_vaapi
#define av_freep(p)
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:364
The mapping must be readable.
Definition: hwcontext.h:524
#define av_malloc_array(a, b)
formats
Definition: signature.h:48
#define FFSWAP(type, a, b)
Definition: common.h:99
AVHWDeviceInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:71
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
unsigned int rt_format
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
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 local context
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:222
The quirks field has been set by the user and should not be detected automatically by av_hwdevice_ctx...
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:671
int i
Definition: input.c:407
#define V
Definition: avdct.c:30