FFmpeg  4.3.7
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 {
1432  AVHWDeviceContext *ctx = context;
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 {
1439  AVHWDeviceContext *ctx = context;
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,
1628  AVDictionary *opts, int flags)
1629 {
1630 #if HAVE_VAAPI_DRM
1631  if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
1632  AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
1633  VADisplay *display;
1634  VAAPIDevicePriv *priv;
1635  int fd;
1636 
1637  if (src_hwctx->fd < 0) {
1638  av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated "
1639  "device to derive a VA display from.\n");
1640  return AVERROR(EINVAL);
1641  }
1642 
1643 #if CONFIG_LIBDRM
1644  {
1645  int node_type = drmGetNodeTypeFromFd(src_hwctx->fd);
1646  char *render_node;
1647  if (node_type < 0) {
1648  av_log(ctx, AV_LOG_ERROR, "DRM instance fd does not appear "
1649  "to refer to a DRM device.\n");
1650  return AVERROR(EINVAL);
1651  }
1652  if (node_type == DRM_NODE_RENDER) {
1653  fd = src_hwctx->fd;
1654  } else {
1655  render_node = drmGetRenderDeviceNameFromFd(src_hwctx->fd);
1656  if (!render_node) {
1657  av_log(ctx, AV_LOG_ERROR, "Failed to find a render node "
1658  "matching the DRM device.\n");
1659  return AVERROR(ENODEV);
1660  }
1661  fd = open(render_node, O_RDWR);
1662  if (fd < 0) {
1663  av_log(ctx, AV_LOG_ERROR, "Failed to open render node %s"
1664  "matching the DRM device.\n", render_node);
1665  free(render_node);
1666  return AVERROR(errno);
1667  }
1668  av_log(ctx, AV_LOG_VERBOSE, "Using render node %s in place "
1669  "of non-render DRM device.\n", render_node);
1670  free(render_node);
1671  }
1672  }
1673 #else
1674  fd = src_hwctx->fd;
1675 #endif
1676 
1677  priv = av_mallocz(sizeof(*priv));
1678  if (!priv)
1679  return AVERROR(ENOMEM);
1680 
1681  if (fd == src_hwctx->fd) {
1682  // The fd is inherited from the source context and we are holding
1683  // a reference to that, we don't want to close it from here.
1684  priv->drm_fd = -1;
1685  } else {
1686  priv->drm_fd = fd;
1687  }
1688 
1689  ctx->user_opaque = priv;
1690  ctx->free = &vaapi_device_free;
1691 
1692  display = vaGetDisplayDRM(fd);
1693  if (!display) {
1694  av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
1695  "DRM device.\n");
1696  return AVERROR(EIO);
1697  }
1698 
1699  return vaapi_device_connect(ctx, display);
1700  }
1701 #endif
1702  return AVERROR(ENOSYS);
1703 }
1704 
1707  .name = "VAAPI",
1708 
1709  .device_hwctx_size = sizeof(AVVAAPIDeviceContext),
1710  .device_priv_size = sizeof(VAAPIDeviceContext),
1711  .device_hwconfig_size = sizeof(AVVAAPIHWConfig),
1712  .frames_hwctx_size = sizeof(AVVAAPIFramesContext),
1713  .frames_priv_size = sizeof(VAAPIFramesContext),
1714 
1715  .device_create = &vaapi_device_create,
1716  .device_derive = &vaapi_device_derive,
1718  .device_uninit = &vaapi_device_uninit,
1719  .frames_get_constraints = &vaapi_frames_get_constraints,
1720  .frames_init = &vaapi_frames_init,
1721  .frames_uninit = &vaapi_frames_uninit,
1722  .frames_get_buffer = &vaapi_get_buffer,
1723  .transfer_get_formats = &vaapi_transfer_get_formats,
1724  .transfer_data_to = &vaapi_transfer_data_to,
1725  .transfer_data_from = &vaapi_transfer_data_from,
1726  .map_to = &vaapi_map_to,
1727  .map_from = &vaapi_map_from,
1728 
1729  .pix_fmts = (const enum AVPixelFormat[]) {
1732  },
1733 };
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:125
int size
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:300
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
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:491
The mapping must be direct.
Definition: hwcontext.h:540
const char * desc
Definition: nvenc.c:79
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)
#define RGBA(r, g, b, a)
Definition: dvbsubdec.c:39
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:639
static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vaapi_device_init(AVHWDeviceContext *hwdev)
DRM frame descriptor.
#define HAVE_VAAPI_X11
Definition: config.h:330
#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[]
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:534
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)
static AVFrame * frame
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
const char data[16]
Definition: mxf.c:91
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
Definition: vf_addroi.c:26
#define HAVE_VAAPI_DRM
Definition: config.h:329
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
#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:269
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:358
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
VAAPI hardware pipeline configuration details.
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
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
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
DRM object descriptor.
Definition: hwcontext_drm.h:48
simple assert() macros that are a bit more flexible than ISO C assert().
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
int 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
The mapping must be readable.
Definition: hwcontext.h:524
#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: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
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
AVFormatContext * ctx
Definition: movenc.c:48
#define MAP(va, rt, av, swap_uv)
The quirks field has been set by the user and should not be detected automatically by av_hwdevice_ctx...
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
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:218
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)
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:373
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.
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:331
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
The mapping must be writeable.
Definition: hwcontext.h:528
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
cl_device_type type
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
The driver does not support the VASurfaceAttribMemoryType attribute, so the surface allocation code w...
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:565
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:314
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
if(ret< 0)
Definition: vf_mcdeint.c:279
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
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:358
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:337
#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
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
static const struct @299 vaapi_driver_quirks_table[]
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:659
The driver does not support surface attributes at all.
#define V
Definition: avdct.c:30