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