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;
1325  export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1326 
1327  vas = vaExportSurfaceHandle(hwctx->display, surface_id,
1328  VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1329  export_flags, &va_desc);
1330  if (vas != VA_STATUS_SUCCESS) {
1331  if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1332  return AVERROR(ENOSYS);
1333  av_log(hwfc, AV_LOG_ERROR, "Failed to export surface %#x: "
1334  "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1335  return AVERROR(EIO);
1336  }
1337 
1338  drm_desc = av_mallocz(sizeof(*drm_desc));
1339  if (!drm_desc) {
1340  err = AVERROR(ENOMEM);
1341  goto fail;
1342  }
1343 
1344  // By some bizarre coincidence, these structures are very similar...
1345  drm_desc->nb_objects = va_desc.num_objects;
1346  for (i = 0; i < va_desc.num_objects; i++) {
1347  drm_desc->objects[i].fd = va_desc.objects[i].fd;
1348  drm_desc->objects[i].size = va_desc.objects[i].size;
1349  drm_desc->objects[i].format_modifier =
1350  va_desc.objects[i].drm_format_modifier;
1351  }
1352  drm_desc->nb_layers = va_desc.num_layers;
1353  for (i = 0; i < va_desc.num_layers; i++) {
1354  drm_desc->layers[i].format = va_desc.layers[i].drm_format;
1355  drm_desc->layers[i].nb_planes = va_desc.layers[i].num_planes;
1356  for (j = 0; j < va_desc.layers[i].num_planes; j++) {
1357  drm_desc->layers[i].planes[j].object_index =
1358  va_desc.layers[i].object_index[j];
1359  drm_desc->layers[i].planes[j].offset =
1360  va_desc.layers[i].offset[j];
1361  drm_desc->layers[i].planes[j].pitch =
1362  va_desc.layers[i].pitch[j];
1363  }
1364  }
1365 
1366  err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
1367  &vaapi_unmap_to_drm_esh, drm_desc);
1368  if (err < 0)
1369  goto fail;
1370 
1371  dst->width = src->width;
1372  dst->height = src->height;
1373  dst->data[0] = (uint8_t*)drm_desc;
1374 
1375  return 0;
1376 
1377 fail:
1378  for (i = 0; i < va_desc.num_objects; i++)
1379  close(va_desc.objects[i].fd);
1380  av_freep(&drm_desc);
1381  return err;
1382 }
1383 #endif
1384 
1385 #if VA_CHECK_VERSION(0, 36, 0)
1386 typedef struct VAAPIDRMImageBufferMapping {
1387  VAImage image;
1388  VABufferInfo buffer_info;
1389 
1390  AVDRMFrameDescriptor drm_desc;
1391 } VAAPIDRMImageBufferMapping;
1392 
1393 static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc,
1394  HWMapDescriptor *hwmap)
1395 {
1396  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1397  VAAPIDRMImageBufferMapping *mapping = hwmap->priv;
1398  VASurfaceID surface_id;
1399  VAStatus vas;
1400 
1401  surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
1402  av_log(hwfc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from DRM.\n",
1403  surface_id);
1404 
1405  // DRM PRIME file descriptors are closed by vaReleaseBufferHandle(),
1406  // so we shouldn't close them separately.
1407 
1408  vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1409  if (vas != VA_STATUS_SUCCESS) {
1410  av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer "
1411  "handle of image %#x (derived from surface %#x): "
1412  "%d (%s).\n", mapping->image.buf, surface_id,
1413  vas, vaErrorStr(vas));
1414  }
1415 
1416  vas = vaDestroyImage(hwctx->display, mapping->image.image_id);
1417  if (vas != VA_STATUS_SUCCESS) {
1418  av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image "
1419  "derived from surface %#x: %d (%s).\n",
1420  surface_id, vas, vaErrorStr(vas));
1421  }
1422 
1423  av_free(mapping);
1424 }
1425 
1426 static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
1427  const AVFrame *src, int flags)
1428 {
1429  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1430  VAAPIDRMImageBufferMapping *mapping = NULL;
1431  VASurfaceID surface_id;
1432  VAStatus vas;
1433  int err, i, p;
1434 
1435  surface_id = (VASurfaceID)(uintptr_t)src->data[3];
1436  av_log(hwfc, AV_LOG_DEBUG, "Map VAAPI surface %#x to DRM.\n",
1437  surface_id);
1438 
1439  mapping = av_mallocz(sizeof(*mapping));
1440  if (!mapping)
1441  return AVERROR(ENOMEM);
1442 
1443  vas = vaDeriveImage(hwctx->display, surface_id,
1444  &mapping->image);
1445  if (vas != VA_STATUS_SUCCESS) {
1446  av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
1447  "surface %#x: %d (%s).\n",
1448  surface_id, vas, vaErrorStr(vas));
1449  err = AVERROR(EIO);
1450  goto fail;
1451  }
1452 
1453  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
1454  if (vaapi_drm_format_map[i].va_fourcc ==
1455  mapping->image.format.fourcc)
1456  break;
1457  }
1458  if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) {
1459  av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for "
1460  "VAAPI format %#x.\n", mapping->image.format.fourcc);
1461  err = AVERROR(EINVAL);
1462  goto fail_derived;
1463  }
1464 
1465  mapping->buffer_info.mem_type =
1466  VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1467 
1468  mapping->drm_desc.nb_layers =
1469  vaapi_drm_format_map[i].nb_layer_formats;
1470  if (mapping->drm_desc.nb_layers > 1) {
1471  if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1472  av_log(hwfc, AV_LOG_ERROR, "Image properties do not match "
1473  "expected format: got %d planes, but expected %d.\n",
1474  mapping->image.num_planes, mapping->drm_desc.nb_layers);
1475  err = AVERROR(EINVAL);
1476  goto fail_derived;
1477  }
1478 
1479  for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1480  mapping->drm_desc.layers[p] = (AVDRMLayerDescriptor) {
1481  .format = vaapi_drm_format_map[i].layer_formats[p],
1482  .nb_planes = 1,
1483  .planes[0] = {
1484  .object_index = 0,
1485  .offset = mapping->image.offsets[p],
1486  .pitch = mapping->image.pitches[p],
1487  },
1488  };
1489  }
1490  } else {
1491  mapping->drm_desc.layers[0].format =
1492  vaapi_drm_format_map[i].layer_formats[0];
1493  mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1494  for (p = 0; p < mapping->image.num_planes; p++) {
1495  mapping->drm_desc.layers[0].planes[p] = (AVDRMPlaneDescriptor) {
1496  .object_index = 0,
1497  .offset = mapping->image.offsets[p],
1498  .pitch = mapping->image.pitches[p],
1499  };
1500  }
1501  }
1502 
1503  vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf,
1504  &mapping->buffer_info);
1505  if (vas != VA_STATUS_SUCCESS) {
1506  av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer "
1507  "handle from image %#x (derived from surface %#x): "
1508  "%d (%s).\n", mapping->image.buf, surface_id,
1509  vas, vaErrorStr(vas));
1510  err = AVERROR(EIO);
1511  goto fail_derived;
1512  }
1513 
1514  av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %"PRIdPTR".\n",
1515  mapping->buffer_info.handle);
1516 
1517  mapping->drm_desc.nb_objects = 1;
1518  mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) {
1519  .fd = mapping->buffer_info.handle,
1520  .size = mapping->image.data_size,
1521  // There is no way to get the format modifier with this API.
1522  .format_modifier = DRM_FORMAT_MOD_INVALID,
1523  };
1524 
1525  err = ff_hwframe_map_create(src->hw_frames_ctx,
1526  dst, src, &vaapi_unmap_to_drm_abh,
1527  mapping);
1528  if (err < 0)
1529  goto fail_mapped;
1530 
1531  dst->data[0] = (uint8_t*)&mapping->drm_desc;
1532  dst->width = src->width;
1533  dst->height = src->height;
1534 
1535  return 0;
1536 
1537 fail_mapped:
1538  vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1539 fail_derived:
1540  vaDestroyImage(hwctx->display, mapping->image.image_id);
1541 fail:
1542  av_freep(&mapping);
1543  return err;
1544 }
1545 #endif
1546 
1547 static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
1548  const AVFrame *src, int flags)
1549 {
1550 #if VA_CHECK_VERSION(1, 1, 0)
1551  int err;
1552  err = vaapi_map_to_drm_esh(hwfc, dst, src, flags);
1553  if (err != AVERROR(ENOSYS))
1554  return err;
1555 #endif
1556 #if VA_CHECK_VERSION(0, 36, 0)
1557  return vaapi_map_to_drm_abh(hwfc, dst, src, flags);
1558 #endif
1559  return AVERROR(ENOSYS);
1560 }
1561 
1562 #endif /* CONFIG_LIBDRM */
1563 
1564 static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
1565  const AVFrame *src, int flags)
1566 {
1567  switch (src->format) {
1568 #if CONFIG_LIBDRM
1569  case AV_PIX_FMT_DRM_PRIME:
1570  return vaapi_map_from_drm(hwfc, dst, src, flags);
1571 #endif
1572  default:
1573  return AVERROR(ENOSYS);
1574  }
1575 }
1576 
1578  const AVFrame *src, int flags)
1579 {
1580  switch (dst->format) {
1581 #if CONFIG_LIBDRM
1582  case AV_PIX_FMT_DRM_PRIME:
1583  return vaapi_map_to_drm(hwfc, dst, src, flags);
1584 #endif
1585  default:
1586  return vaapi_map_to_memory(hwfc, dst, src, flags);
1587  }
1588 }
1589 
1591 {
1592  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1593  VAAPIDevicePriv *priv = ctx->user_opaque;
1594 
1595  if (hwctx->display)
1596  vaTerminate(hwctx->display);
1597 
1598 #if HAVE_VAAPI_X11
1599  if (priv->x11_display)
1600  XCloseDisplay(priv->x11_display);
1601 #endif
1602 
1603  if (priv->drm_fd >= 0)
1604  close(priv->drm_fd);
1605 
1606  av_freep(&priv);
1607 }
1608 
1609 #if CONFIG_VAAPI_1
1610 static void vaapi_device_log_error(void *context, const char *message)
1611 {
1613 
1614  av_log(ctx, AV_LOG_ERROR, "libva: %s", message);
1615 }
1616 
1617 static void vaapi_device_log_info(void *context, const char *message)
1618 {
1620 
1621  av_log(ctx, AV_LOG_VERBOSE, "libva: %s", message);
1622 }
1623 #endif
1624 
1626  VADisplay display)
1627 {
1628  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1629  int major, minor;
1630  VAStatus vas;
1631 
1632 #if CONFIG_VAAPI_1
1633  vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
1634  vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
1635 #endif
1636 
1637  hwctx->display = display;
1638 
1639  vas = vaInitialize(display, &major, &minor);
1640  if (vas != VA_STATUS_SUCCESS) {
1641  av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
1642  "connection: %d (%s).\n", vas, vaErrorStr(vas));
1643  return AVERROR(EIO);
1644  }
1645  av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
1646  "version %d.%d\n", major, minor);
1647 
1648  return 0;
1649 }
1650 
1651 static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
1652  AVDictionary *opts, int flags)
1653 {
1654  VAAPIDevicePriv *priv;
1655  VADisplay display = NULL;
1656  const AVDictionaryEntry *ent;
1657  int try_drm, try_x11, try_all;
1658 
1659  priv = av_mallocz(sizeof(*priv));
1660  if (!priv)
1661  return AVERROR(ENOMEM);
1662 
1663  priv->drm_fd = -1;
1664 
1665  ctx->user_opaque = priv;
1666  ctx->free = vaapi_device_free;
1667 
1668  ent = av_dict_get(opts, "connection_type", NULL, 0);
1669  if (ent) {
1670  try_all = try_drm = try_x11 = 0;
1671  if (!strcmp(ent->value, "drm")) {
1672  try_drm = 1;
1673  } else if (!strcmp(ent->value, "x11")) {
1674  try_x11 = 1;
1675  } else {
1676  av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n",
1677  ent->value);
1678  return AVERROR(EINVAL);
1679  }
1680  } else {
1681  try_all = 1;
1682  try_drm = HAVE_VAAPI_DRM;
1683  try_x11 = HAVE_VAAPI_X11;
1684  }
1685 
1686 #if HAVE_VAAPI_DRM
1687  while (!display && try_drm) {
1688  // If the device is specified, try to open it as a DRM device node.
1689  // If not, look for a usable render node, possibly restricted to those
1690  // using a specified kernel driver.
1691  int loglevel = try_all ? AV_LOG_VERBOSE : AV_LOG_ERROR;
1692  if (device) {
1693  priv->drm_fd = open(device, O_RDWR);
1694  if (priv->drm_fd < 0) {
1695  av_log(ctx, loglevel, "Failed to open %s as "
1696  "DRM device node.\n", device);
1697  break;
1698  }
1699  } else {
1700  char path[64];
1701  int n, max_devices = 8;
1702 #if CONFIG_LIBDRM
1703  drmVersion *info;
1704  const AVDictionaryEntry *kernel_driver;
1705  kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0);
1706 #endif
1707  for (n = 0; n < max_devices; n++) {
1708  snprintf(path, sizeof(path),
1709  "/dev/dri/renderD%d", 128 + n);
1710  priv->drm_fd = open(path, O_RDWR);
1711  if (priv->drm_fd < 0) {
1712  av_log(ctx, AV_LOG_VERBOSE, "Cannot open "
1713  "DRM render node for device %d.\n", n);
1714  break;
1715  }
1716 #if CONFIG_LIBDRM
1717  info = drmGetVersion(priv->drm_fd);
1718  if (!info) {
1720  "Failed to get DRM version for device %d.\n", n);
1721  close(priv->drm_fd);
1722  priv->drm_fd = -1;
1723  continue;
1724  }
1725  if (kernel_driver) {
1726  if (strcmp(kernel_driver->value, info->name)) {
1727  av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d "
1728  "with non-matching kernel driver (%s).\n",
1729  n, info->name);
1730  drmFreeVersion(info);
1731  close(priv->drm_fd);
1732  priv->drm_fd = -1;
1733  continue;
1734  }
1735  av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1736  "DRM render node for device %d, "
1737  "with matching kernel driver (%s).\n",
1738  n, info->name);
1739  drmFreeVersion(info);
1740  break;
1741  // drmGetVersion() ensures |info->name| is 0-terminated.
1742  } else if (!strcmp(info->name, "vgem")) {
1744  "Skipping vgem node for device %d.\n", n);
1745  drmFreeVersion(info);
1746  close(priv->drm_fd);
1747  priv->drm_fd = -1;
1748  continue;
1749  }
1750  drmFreeVersion(info);
1751 #endif
1752  av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1753  "DRM render node for device %d.\n", n);
1754  break;
1755  }
1756  if (n >= max_devices)
1757  break;
1758  }
1759 
1760  display = vaGetDisplayDRM(priv->drm_fd);
1761  if (!display) {
1762  av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display "
1763  "from DRM device %s.\n", device);
1764  return AVERROR_EXTERNAL;
1765  }
1766  break;
1767  }
1768 #endif
1769 
1770 #if HAVE_VAAPI_X11
1771  if (!display && try_x11) {
1772  // Try to open the device as an X11 display.
1773  priv->x11_display = XOpenDisplay(device);
1774  if (!priv->x11_display) {
1775  av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
1776  "%s.\n", XDisplayName(device));
1777  } else {
1778  display = vaGetDisplay(priv->x11_display);
1779  if (!display) {
1780  av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1781  "from X11 display %s.\n", XDisplayName(device));
1782  return AVERROR_UNKNOWN;
1783  }
1784 
1785  av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1786  "X11 display %s.\n", XDisplayName(device));
1787  }
1788  }
1789 #endif
1790 
1791  if (!display) {
1792  if (device)
1793  av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1794  "device %s.\n", device);
1795  else
1796  av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1797  "any default device.\n");
1798  return AVERROR(EINVAL);
1799  }
1800 
1801  ent = av_dict_get(opts, "driver", NULL, 0);
1802  if (ent) {
1803 #if VA_CHECK_VERSION(0, 38, 0)
1804  VAStatus vas;
1805  vas = vaSetDriverName(display, ent->value);
1806  if (vas != VA_STATUS_SUCCESS) {
1807  av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to "
1808  "%s: %d (%s).\n", ent->value, vas, vaErrorStr(vas));
1809  vaTerminate(display);
1810  return AVERROR_EXTERNAL;
1811  }
1812 #else
1813  av_log(ctx, AV_LOG_WARNING, "Driver name setting is not "
1814  "supported with this VAAPI version.\n");
1815 #endif
1816  }
1817 
1818  return vaapi_device_connect(ctx, display);
1819 }
1820 
1822  AVHWDeviceContext *src_ctx,
1823  AVDictionary *opts, int flags)
1824 {
1825 #if HAVE_VAAPI_DRM
1826  if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
1827  AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
1828  VADisplay *display;
1829  VAAPIDevicePriv *priv;
1830  int fd;
1831 
1832  if (src_hwctx->fd < 0) {
1833  av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated "
1834  "device to derive a VA display from.\n");
1835  return AVERROR(EINVAL);
1836  }
1837 
1838 #if CONFIG_LIBDRM
1839  {
1840  int node_type = drmGetNodeTypeFromFd(src_hwctx->fd);
1841  char *render_node;
1842  if (node_type < 0) {
1843  av_log(ctx, AV_LOG_ERROR, "DRM instance fd does not appear "
1844  "to refer to a DRM device.\n");
1845  return AVERROR(EINVAL);
1846  }
1847  if (node_type == DRM_NODE_RENDER) {
1848  fd = src_hwctx->fd;
1849  } else {
1850  render_node = drmGetRenderDeviceNameFromFd(src_hwctx->fd);
1851  if (!render_node) {
1852  av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
1853  "because the device does not have an "
1854  "associated render node.\n");
1855  fd = src_hwctx->fd;
1856  } else {
1857  fd = open(render_node, O_RDWR);
1858  if (fd < 0) {
1859  av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
1860  "because the associated render node "
1861  "could not be opened.\n");
1862  fd = src_hwctx->fd;
1863  } else {
1864  av_log(ctx, AV_LOG_VERBOSE, "Using render node %s "
1865  "in place of non-render DRM device.\n",
1866  render_node);
1867  }
1868  free(render_node);
1869  }
1870  }
1871  }
1872 #else
1873  fd = src_hwctx->fd;
1874 #endif
1875 
1876  priv = av_mallocz(sizeof(*priv));
1877  if (!priv) {
1878  if (fd != src_hwctx->fd) {
1879  // The fd was opened in this function.
1880  close(fd);
1881  }
1882  return AVERROR(ENOMEM);
1883  }
1884 
1885  if (fd == src_hwctx->fd) {
1886  // The fd is inherited from the source context and we are holding
1887  // a reference to that, we don't want to close it from here.
1888  priv->drm_fd = -1;
1889  } else {
1890  priv->drm_fd = fd;
1891  }
1892 
1893  ctx->user_opaque = priv;
1894  ctx->free = &vaapi_device_free;
1895 
1896  display = vaGetDisplayDRM(fd);
1897  if (!display) {
1898  av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
1899  "DRM device.\n");
1900  return AVERROR(EIO);
1901  }
1902 
1903  return vaapi_device_connect(ctx, display);
1904  }
1905 #endif
1906  return AVERROR(ENOSYS);
1907 }
1908 
1911  .name = "VAAPI",
1912 
1913  .device_hwctx_size = sizeof(AVVAAPIDeviceContext),
1914  .device_priv_size = sizeof(VAAPIDeviceContext),
1915  .device_hwconfig_size = sizeof(AVVAAPIHWConfig),
1916  .frames_hwctx_size = sizeof(AVVAAPIFramesContext),
1917  .frames_priv_size = sizeof(VAAPIFramesContext),
1918 
1919  .device_create = &vaapi_device_create,
1920  .device_derive = &vaapi_device_derive,
1922  .device_uninit = &vaapi_device_uninit,
1923  .frames_get_constraints = &vaapi_frames_get_constraints,
1924  .frames_init = &vaapi_frames_init,
1925  .frames_uninit = &vaapi_frames_uninit,
1926  .frames_get_buffer = &vaapi_get_buffer,
1927  .transfer_get_formats = &vaapi_transfer_get_formats,
1928  .transfer_data_to = &vaapi_transfer_data_to,
1929  .transfer_data_from = &vaapi_transfer_data_from,
1930  .map_to = &vaapi_map_to,
1931  .map_from = &vaapi_map_from,
1932 
1933  .pix_fmts = (const enum AVPixelFormat[]) {
1936  },
1937 };
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:1821
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
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
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:99
vaapi_driver_quirks_table
static const struct @330 vaapi_driver_quirks_table[]
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
vaapi_map_to
static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:1564
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
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
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
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
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
AV_HWFRAME_MAP_READ
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
Definition: hwcontext.h:524
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:1909
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:87
vaapi_map_frame
static int vaapi_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:781
avassert.h
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
AV_HWFRAME_MAP_DIRECT
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
Definition: hwcontext.h:540
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
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:594
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
AV_DRM_MAX_PLANES
@ AV_DRM_MAX_PLANES
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
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:1651
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:762
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
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
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
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:1625
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:1590
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:678
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
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
AV_HWFRAME_MAP_WRITE
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
Definition: hwcontext.h:528
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
vaapi_map_from
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vaapi.c:1577
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
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