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