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