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