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