FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 <drm_fourcc.h>
31 #endif
32 
33 #include <fcntl.h>
34 #if HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 
38 
39 #include "avassert.h"
40 #include "buffer.h"
41 #include "common.h"
42 #include "hwcontext.h"
43 #include "hwcontext_internal.h"
44 #include "hwcontext_vaapi.h"
45 #include "mem.h"
46 #include "pixdesc.h"
47 #include "pixfmt.h"
48 
49 #if CONFIG_LIBDRM
50 # include "hwcontext_drm.h"
51 #endif
52 
53 typedef struct VAAPIDevicePriv {
54 #if HAVE_VAAPI_X11
55  Display *x11_display;
56 #endif
57 
58  int drm_fd;
60 
61 typedef struct VAAPISurfaceFormat {
63  VAImageFormat image_format;
65 
66 typedef struct VAAPIDeviceContext {
67  // Surface formats which can be used with this device.
71 
72 typedef struct VAAPIFramesContext {
73  // Surface attributes set at create time.
74  VASurfaceAttrib *attributes;
76  // RT format of the underlying surface (Intel driver ignores this anyway).
77  unsigned int rt_format;
78  // Whether vaDeriveImage works.
81 
82 typedef struct VAAPIMapping {
83  // Handle to the derived or copied image which is mapped.
84  VAImage image;
85  // The mapping flags actually used.
86  int flags;
87 } VAAPIMapping;
88 
89 #define MAP(va, rt, av) { \
90  VA_FOURCC_ ## va, \
91  VA_RT_FORMAT_ ## rt, \
92  AV_PIX_FMT_ ## av \
93  }
94 // The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V
95 // plane swap cases. The frame handling below tries to hide these.
96 static const struct {
97  unsigned int fourcc;
98  unsigned int rt_format;
100 } vaapi_format_map[] = {
101  MAP(NV12, YUV420, NV12),
102  MAP(YV12, YUV420, YUV420P), // With U/V planes swapped.
103  MAP(IYUV, YUV420, YUV420P),
104  //MAP(I420, YUV420, YUV420P), // Not in libva but used by Intel driver.
105 #ifdef VA_FOURCC_YV16
106  MAP(YV16, YUV422, YUV422P), // With U/V planes swapped.
107 #endif
108  MAP(422H, YUV422, YUV422P),
109  MAP(UYVY, YUV422, UYVY422),
110  MAP(YUY2, YUV422, YUYV422),
111  MAP(Y800, YUV400, GRAY8),
112 #ifdef VA_FOURCC_P010
113  MAP(P010, YUV420_10BPP, P010),
114 #endif
115  MAP(BGRA, RGB32, BGRA),
116  MAP(BGRX, RGB32, BGR0),
117  MAP(RGBA, RGB32, RGBA),
118  MAP(RGBX, RGB32, RGB0),
119 #ifdef VA_FOURCC_ABGR
120  MAP(ABGR, RGB32, ABGR),
121  MAP(XBGR, RGB32, 0BGR),
122 #endif
123  MAP(ARGB, RGB32, ARGB),
124  MAP(XRGB, RGB32, 0RGB),
125 };
126 #undef MAP
127 
129 {
130  int i;
131  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
132  if (vaapi_format_map[i].fourcc == fourcc)
133  return vaapi_format_map[i].pix_fmt;
134  return AV_PIX_FMT_NONE;
135 }
136 
138  enum AVPixelFormat pix_fmt,
139  VAImageFormat **image_format)
140 {
141  VAAPIDeviceContext *ctx = hwdev->internal->priv;
142  int i;
143 
144  for (i = 0; i < ctx->nb_formats; i++) {
145  if (ctx->formats[i].pix_fmt == pix_fmt) {
146  if (image_format)
147  *image_format = &ctx->formats[i].image_format;
148  return 0;
149  }
150  }
151  return AVERROR(EINVAL);
152 }
153 
155  const void *hwconfig,
156  AVHWFramesConstraints *constraints)
157 {
158  AVVAAPIDeviceContext *hwctx = hwdev->hwctx;
159  const AVVAAPIHWConfig *config = hwconfig;
160  VAAPIDeviceContext *ctx = hwdev->internal->priv;
161  VASurfaceAttrib *attr_list = NULL;
162  VAStatus vas;
163  enum AVPixelFormat pix_fmt;
164  unsigned int fourcc;
165  int err, i, j, attr_count, pix_fmt_count;
166 
167  if (config &&
169  attr_count = 0;
170  vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
171  0, &attr_count);
172  if (vas != VA_STATUS_SUCCESS) {
173  av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
174  "%d (%s).\n", vas, vaErrorStr(vas));
175  err = AVERROR(ENOSYS);
176  goto fail;
177  }
178 
179  attr_list = av_malloc(attr_count * sizeof(*attr_list));
180  if (!attr_list) {
181  err = AVERROR(ENOMEM);
182  goto fail;
183  }
184 
185  vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
186  attr_list, &attr_count);
187  if (vas != VA_STATUS_SUCCESS) {
188  av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
189  "%d (%s).\n", vas, vaErrorStr(vas));
190  err = AVERROR(ENOSYS);
191  goto fail;
192  }
193 
194  pix_fmt_count = 0;
195  for (i = 0; i < attr_count; i++) {
196  switch (attr_list[i].type) {
197  case VASurfaceAttribPixelFormat:
198  fourcc = attr_list[i].value.value.i;
199  pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
200  if (pix_fmt != AV_PIX_FMT_NONE) {
201  ++pix_fmt_count;
202  } else {
203  // Something unsupported - ignore.
204  }
205  break;
206  case VASurfaceAttribMinWidth:
207  constraints->min_width = attr_list[i].value.value.i;
208  break;
209  case VASurfaceAttribMinHeight:
210  constraints->min_height = attr_list[i].value.value.i;
211  break;
212  case VASurfaceAttribMaxWidth:
213  constraints->max_width = attr_list[i].value.value.i;
214  break;
215  case VASurfaceAttribMaxHeight:
216  constraints->max_height = attr_list[i].value.value.i;
217  break;
218  }
219  }
220  if (pix_fmt_count == 0) {
221  // Nothing usable found. Presumably there exists something which
222  // works, so leave the set null to indicate unknown.
223  constraints->valid_sw_formats = NULL;
224  } else {
225  constraints->valid_sw_formats = av_malloc_array(pix_fmt_count + 1,
226  sizeof(pix_fmt));
227  if (!constraints->valid_sw_formats) {
228  err = AVERROR(ENOMEM);
229  goto fail;
230  }
231 
232  for (i = j = 0; i < attr_count; i++) {
233  if (attr_list[i].type != VASurfaceAttribPixelFormat)
234  continue;
235  fourcc = attr_list[i].value.value.i;
236  pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
237  if (pix_fmt != AV_PIX_FMT_NONE)
238  constraints->valid_sw_formats[j++] = pix_fmt;
239  }
240  av_assert0(j == pix_fmt_count);
241  constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
242  }
243  } else {
244  // No configuration supplied.
245  // Return the full set of image formats known by the implementation.
246  constraints->valid_sw_formats = av_malloc_array(ctx->nb_formats + 1,
247  sizeof(pix_fmt));
248  if (!constraints->valid_sw_formats) {
249  err = AVERROR(ENOMEM);
250  goto fail;
251  }
252  for (i = 0; i < ctx->nb_formats; i++)
253  constraints->valid_sw_formats[i] = ctx->formats[i].pix_fmt;
254  constraints->valid_sw_formats[i] = AV_PIX_FMT_NONE;
255  }
256 
257  constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt));
258  if (!constraints->valid_hw_formats) {
259  err = AVERROR(ENOMEM);
260  goto fail;
261  }
262  constraints->valid_hw_formats[0] = AV_PIX_FMT_VAAPI;
263  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
264 
265  err = 0;
266 fail:
267  av_freep(&attr_list);
268  return err;
269 }
270 
271 static const struct {
272  const char *friendly_name;
273  const char *match_string;
274  unsigned int quirks;
276  {
277  "Intel i965 (Quick Sync)",
278  "i965",
280  },
281  {
282  "Intel iHD",
283  "ubit",
285  },
286  {
287  "VDPAU wrapper",
288  "Splitted-Desktop Systems VDPAU backend for VA-API",
290  },
291 };
292 
294 {
295  VAAPIDeviceContext *ctx = hwdev->internal->priv;
296  AVVAAPIDeviceContext *hwctx = hwdev->hwctx;
297  VAImageFormat *image_list = NULL;
298  VAStatus vas;
299  const char *vendor_string;
300  int err, i, image_count;
301  enum AVPixelFormat pix_fmt;
302  unsigned int fourcc;
303 
304  image_count = vaMaxNumImageFormats(hwctx->display);
305  if (image_count <= 0) {
306  err = AVERROR(EIO);
307  goto fail;
308  }
309  image_list = av_malloc(image_count * sizeof(*image_list));
310  if (!image_list) {
311  err = AVERROR(ENOMEM);
312  goto fail;
313  }
314  vas = vaQueryImageFormats(hwctx->display, image_list, &image_count);
315  if (vas != VA_STATUS_SUCCESS) {
316  err = AVERROR(EIO);
317  goto fail;
318  }
319 
320  ctx->formats = av_malloc(image_count * sizeof(*ctx->formats));
321  if (!ctx->formats) {
322  err = AVERROR(ENOMEM);
323  goto fail;
324  }
325  ctx->nb_formats = 0;
326  for (i = 0; i < image_count; i++) {
327  fourcc = image_list[i].fourcc;
328  pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
329  if (pix_fmt == AV_PIX_FMT_NONE) {
330  av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> unknown.\n",
331  fourcc);
332  } else {
333  av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n",
334  fourcc, av_get_pix_fmt_name(pix_fmt));
335  ctx->formats[ctx->nb_formats].pix_fmt = pix_fmt;
336  ctx->formats[ctx->nb_formats].image_format = image_list[i];
337  ++ctx->nb_formats;
338  }
339  }
340 
342  av_log(hwdev, AV_LOG_VERBOSE, "Not detecting driver: "
343  "quirks set by user.\n");
344  } else {
345  // Detect the driver in use and set quirk flags if necessary.
346  vendor_string = vaQueryVendorString(hwctx->display);
347  hwctx->driver_quirks = 0;
348  if (vendor_string) {
349  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) {
350  if (strstr(vendor_string,
352  av_log(hwdev, AV_LOG_VERBOSE, "Matched \"%s\" as known "
353  "driver \"%s\".\n", vendor_string,
355  hwctx->driver_quirks |=
356  vaapi_driver_quirks_table[i].quirks;
357  break;
358  }
359  }
361  av_log(hwdev, AV_LOG_VERBOSE, "Unknown driver \"%s\", "
362  "assuming standard behaviour.\n", vendor_string);
363  }
364  }
365  }
366 
367  av_free(image_list);
368  return 0;
369 fail:
370  av_freep(&ctx->formats);
371  av_free(image_list);
372  return err;
373 }
374 
376 {
377  VAAPIDeviceContext *ctx = hwdev->internal->priv;
378 
379  av_freep(&ctx->formats);
380 }
381 
382 static void vaapi_buffer_free(void *opaque, uint8_t *data)
383 {
384  AVHWFramesContext *hwfc = opaque;
385  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
386  VASurfaceID surface_id;
387  VAStatus vas;
388 
389  surface_id = (VASurfaceID)(uintptr_t)data;
390 
391  vas = vaDestroySurfaces(hwctx->display, &surface_id, 1);
392  if (vas != VA_STATUS_SUCCESS) {
393  av_log(hwfc, AV_LOG_ERROR, "Failed to destroy surface %#x: "
394  "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
395  }
396 }
397 
398 static AVBufferRef *vaapi_pool_alloc(void *opaque, int size)
399 {
400  AVHWFramesContext *hwfc = opaque;
402  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
403  AVVAAPIFramesContext *avfc = hwfc->hwctx;
404  VASurfaceID surface_id;
405  VAStatus vas;
406  AVBufferRef *ref;
407 
408  if (hwfc->initial_pool_size > 0 &&
409  avfc->nb_surfaces >= hwfc->initial_pool_size)
410  return NULL;
411 
412  vas = vaCreateSurfaces(hwctx->display, ctx->rt_format,
413  hwfc->width, hwfc->height,
414  &surface_id, 1,
415  ctx->attributes, ctx->nb_attributes);
416  if (vas != VA_STATUS_SUCCESS) {
417  av_log(hwfc, AV_LOG_ERROR, "Failed to create surface: "
418  "%d (%s).\n", vas, vaErrorStr(vas));
419  return NULL;
420  }
421  av_log(hwfc, AV_LOG_DEBUG, "Created surface %#x.\n", surface_id);
422 
423  ref = av_buffer_create((uint8_t*)(uintptr_t)surface_id,
424  sizeof(surface_id), &vaapi_buffer_free,
426  if (!ref) {
427  vaDestroySurfaces(hwctx->display, &surface_id, 1);
428  return NULL;
429  }
430 
431  if (hwfc->initial_pool_size > 0) {
432  // This is a fixed-size pool, so we must still be in the initial
433  // allocation sequence.
435  avfc->surface_ids[avfc->nb_surfaces] = surface_id;
436  ++avfc->nb_surfaces;
437  }
438 
439  return ref;
440 }
441 
443 {
444  AVVAAPIFramesContext *avfc = hwfc->hwctx;
446  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
447  VAImageFormat *expected_format;
448  AVBufferRef *test_surface = NULL;
449  VASurfaceID test_surface_id;
450  VAImage test_image;
451  VAStatus vas;
452  int err, i;
453  unsigned int fourcc, rt_format;
454 
455  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
456  if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) {
457  fourcc = vaapi_format_map[i].fourcc;
458  rt_format = vaapi_format_map[i].rt_format;
459  break;
460  }
461  }
462  if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) {
463  av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
465  return AVERROR(EINVAL);
466  }
467 
468  if (!hwfc->pool) {
470  int need_memory_type = !(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE);
471  int need_pixel_format = 1;
472  for (i = 0; i < avfc->nb_attributes; i++) {
473  if (ctx->attributes[i].type == VASurfaceAttribMemoryType)
474  need_memory_type = 0;
475  if (ctx->attributes[i].type == VASurfaceAttribPixelFormat)
476  need_pixel_format = 0;
477  }
478  ctx->nb_attributes =
479  avfc->nb_attributes + need_memory_type + need_pixel_format;
480 
481  ctx->attributes = av_malloc(ctx->nb_attributes *
482  sizeof(*ctx->attributes));
483  if (!ctx->attributes) {
484  err = AVERROR(ENOMEM);
485  goto fail;
486  }
487 
488  for (i = 0; i < avfc->nb_attributes; i++)
489  ctx->attributes[i] = avfc->attributes[i];
490  if (need_memory_type) {
491  ctx->attributes[i++] = (VASurfaceAttrib) {
492  .type = VASurfaceAttribMemoryType,
493  .flags = VA_SURFACE_ATTRIB_SETTABLE,
494  .value.type = VAGenericValueTypeInteger,
495  .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
496  };
497  }
498  if (need_pixel_format) {
499  ctx->attributes[i++] = (VASurfaceAttrib) {
500  .type = VASurfaceAttribPixelFormat,
501  .flags = VA_SURFACE_ATTRIB_SETTABLE,
502  .value.type = VAGenericValueTypeInteger,
503  .value.value.i = fourcc,
504  };
505  }
506  av_assert0(i == ctx->nb_attributes);
507  } else {
508  ctx->attributes = NULL;
509  ctx->nb_attributes = 0;
510  }
511 
512  ctx->rt_format = rt_format;
513 
514  if (hwfc->initial_pool_size > 0) {
515  // This pool will be usable as a render target, so we need to store
516  // all of the surface IDs somewhere that vaCreateContext() calls
517  // will be able to access them.
518  avfc->nb_surfaces = 0;
519  avfc->surface_ids = av_malloc(hwfc->initial_pool_size *
520  sizeof(*avfc->surface_ids));
521  if (!avfc->surface_ids) {
522  err = AVERROR(ENOMEM);
523  goto fail;
524  }
525  } else {
526  // This pool allows dynamic sizing, and will not be usable as a
527  // render target.
528  avfc->nb_surfaces = 0;
529  avfc->surface_ids = NULL;
530  }
531 
532  hwfc->internal->pool_internal =
533  av_buffer_pool_init2(sizeof(VASurfaceID), hwfc,
535  if (!hwfc->internal->pool_internal) {
536  av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n");
537  err = AVERROR(ENOMEM);
538  goto fail;
539  }
540  }
541 
542  // Allocate a single surface to test whether vaDeriveImage() is going
543  // to work for the specific configuration.
544  if (hwfc->pool) {
545  test_surface = av_buffer_pool_get(hwfc->pool);
546  if (!test_surface) {
547  av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
548  "user-configured buffer pool.\n");
549  err = AVERROR(ENOMEM);
550  goto fail;
551  }
552  } else {
553  test_surface = av_buffer_pool_get(hwfc->internal->pool_internal);
554  if (!test_surface) {
555  av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
556  "internal buffer pool.\n");
557  err = AVERROR(ENOMEM);
558  goto fail;
559  }
560  }
561  test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data;
562 
563  ctx->derive_works = 0;
564 
566  hwfc->sw_format, &expected_format);
567  if (err == 0) {
568  vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image);
569  if (vas == VA_STATUS_SUCCESS) {
570  if (expected_format->fourcc == test_image.format.fourcc) {
571  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n");
572  ctx->derive_works = 1;
573  } else {
574  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
575  "derived image format %08x does not match "
576  "expected format %08x.\n",
577  expected_format->fourcc, test_image.format.fourcc);
578  }
579  vaDestroyImage(hwctx->display, test_image.image_id);
580  } else {
581  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
582  "deriving image does not work: "
583  "%d (%s).\n", vas, vaErrorStr(vas));
584  }
585  } else {
586  av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
587  "image format is not supported.\n");
588  }
589 
590  av_buffer_unref(&test_surface);
591  return 0;
592 
593 fail:
594  av_buffer_unref(&test_surface);
595  av_freep(&avfc->surface_ids);
596  av_freep(&ctx->attributes);
597  return err;
598 }
599 
601 {
602  AVVAAPIFramesContext *avfc = hwfc->hwctx;
604 
605  av_freep(&avfc->surface_ids);
606  av_freep(&ctx->attributes);
607 }
608 
610 {
611  frame->buf[0] = av_buffer_pool_get(hwfc->pool);
612  if (!frame->buf[0])
613  return AVERROR(ENOMEM);
614 
615  frame->data[3] = frame->buf[0]->data;
616  frame->format = AV_PIX_FMT_VAAPI;
617  frame->width = hwfc->width;
618  frame->height = hwfc->height;
619 
620  return 0;
621 }
622 
625  enum AVPixelFormat **formats)
626 {
628  enum AVPixelFormat *pix_fmts, preferred_format;
629  int i, k;
630 
631  preferred_format = hwfc->sw_format;
632 
633  pix_fmts = av_malloc((ctx->nb_formats + 1) * sizeof(*pix_fmts));
634  if (!pix_fmts)
635  return AVERROR(ENOMEM);
636 
637  pix_fmts[0] = preferred_format;
638  k = 1;
639  for (i = 0; i < ctx->nb_formats; i++) {
640  if (ctx->formats[i].pix_fmt == preferred_format)
641  continue;
642  av_assert0(k < ctx->nb_formats);
643  pix_fmts[k++] = ctx->formats[i].pix_fmt;
644  }
645  av_assert0(k == ctx->nb_formats);
646  pix_fmts[k] = AV_PIX_FMT_NONE;
647 
648  *formats = pix_fmts;
649  return 0;
650 }
651 
653  HWMapDescriptor *hwmap)
654 {
655  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
656  VAAPIMapping *map = hwmap->priv;
657  VASurfaceID surface_id;
658  VAStatus vas;
659 
660  surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
661  av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id);
662 
663  vas = vaUnmapBuffer(hwctx->display, map->image.buf);
664  if (vas != VA_STATUS_SUCCESS) {
665  av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface "
666  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
667  }
668 
669  if ((map->flags & AV_HWFRAME_MAP_WRITE) &&
670  !(map->flags & AV_HWFRAME_MAP_DIRECT)) {
671  vas = vaPutImage(hwctx->display, surface_id, map->image.image_id,
672  0, 0, hwfc->width, hwfc->height,
673  0, 0, hwfc->width, hwfc->height);
674  if (vas != VA_STATUS_SUCCESS) {
675  av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface "
676  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
677  }
678  }
679 
680  vas = vaDestroyImage(hwctx->display, map->image.image_id);
681  if (vas != VA_STATUS_SUCCESS) {
682  av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface "
683  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
684  }
685 
686  av_free(map);
687 }
688 
690  AVFrame *dst, const AVFrame *src, int flags)
691 {
692  AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
694  VASurfaceID surface_id;
695  VAImageFormat *image_format;
696  VAAPIMapping *map;
697  VAStatus vas;
698  void *address = NULL;
699  int err, i;
700 
701  surface_id = (VASurfaceID)(uintptr_t)src->data[3];
702  av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id);
703 
704  if (!ctx->derive_works && (flags & AV_HWFRAME_MAP_DIRECT)) {
705  // Requested direct mapping but it is not possible.
706  return AVERROR(EINVAL);
707  }
708  if (dst->format == AV_PIX_FMT_NONE)
709  dst->format = hwfc->sw_format;
710  if (dst->format != hwfc->sw_format && (flags & AV_HWFRAME_MAP_DIRECT)) {
711  // Requested direct mapping but the formats do not match.
712  return AVERROR(EINVAL);
713  }
714 
715  err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format);
716  if (err < 0) {
717  // Requested format is not a valid output format.
718  return AVERROR(EINVAL);
719  }
720 
721  map = av_malloc(sizeof(*map));
722  if (!map)
723  return AVERROR(ENOMEM);
724  map->flags = flags;
725  map->image.image_id = VA_INVALID_ID;
726 
727  vas = vaSyncSurface(hwctx->display, surface_id);
728  if (vas != VA_STATUS_SUCCESS) {
729  av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
730  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
731  err = AVERROR(EIO);
732  goto fail;
733  }
734 
735  // The memory which we map using derive need not be connected to the CPU
736  // in a way conducive to fast access. On Gen7-Gen9 Intel graphics, the
737  // memory is mappable but not cached, so normal memcpy()-like access is
738  // very slow to read it (but writing is ok). It is possible to read much
739  // faster with a copy routine which is aware of the limitation, but we
740  // assume for now that the user is not aware of that and would therefore
741  // prefer not to be given direct-mapped memory if they request read access.
742  if (ctx->derive_works && dst->format == hwfc->sw_format &&
743  ((flags & AV_HWFRAME_MAP_DIRECT) || !(flags & AV_HWFRAME_MAP_READ))) {
744  vas = vaDeriveImage(hwctx->display, surface_id, &map->image);
745  if (vas != VA_STATUS_SUCCESS) {
746  av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
747  "surface %#x: %d (%s).\n",
748  surface_id, vas, vaErrorStr(vas));
749  err = AVERROR(EIO);
750  goto fail;
751  }
752  if (map->image.format.fourcc != image_format->fourcc) {
753  av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x "
754  "is in wrong format: expected %#08x, got %#08x.\n",
755  surface_id, image_format->fourcc, map->image.format.fourcc);
756  err = AVERROR(EIO);
757  goto fail;
758  }
760  } else {
761  vas = vaCreateImage(hwctx->display, image_format,
762  hwfc->width, hwfc->height, &map->image);
763  if (vas != VA_STATUS_SUCCESS) {
764  av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
765  "surface %#x: %d (%s).\n",
766  surface_id, vas, vaErrorStr(vas));
767  err = AVERROR(EIO);
768  goto fail;
769  }
770  if (!(flags & AV_HWFRAME_MAP_OVERWRITE)) {
771  vas = vaGetImage(hwctx->display, surface_id, 0, 0,
772  hwfc->width, hwfc->height, map->image.image_id);
773  if (vas != VA_STATUS_SUCCESS) {
774  av_log(hwfc, AV_LOG_ERROR, "Failed to read image from "
775  "surface %#x: %d (%s).\n",
776  surface_id, vas, vaErrorStr(vas));
777  err = AVERROR(EIO);
778  goto fail;
779  }
780  }
781  }
782 
783  vas = vaMapBuffer(hwctx->display, map->image.buf, &address);
784  if (vas != VA_STATUS_SUCCESS) {
785  av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface "
786  "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
787  err = AVERROR(EIO);
788  goto fail;
789  }
790 
792  dst, src, &vaapi_unmap_frame, map);
793  if (err < 0)
794  goto fail;
795 
796  dst->width = src->width;
797  dst->height = src->height;
798 
799  for (i = 0; i < map->image.num_planes; i++) {
800  dst->data[i] = (uint8_t*)address + map->image.offsets[i];
801  dst->linesize[i] = map->image.pitches[i];
802  }
803  if (
804 #ifdef VA_FOURCC_YV16
805  map->image.format.fourcc == VA_FOURCC_YV16 ||
806 #endif
807  map->image.format.fourcc == VA_FOURCC_YV12) {
808  // Chroma planes are YVU rather than YUV, so swap them.
809  FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
810  }
811 
812  return 0;
813 
814 fail:
815  if (map) {
816  if (address)
817  vaUnmapBuffer(hwctx->display, map->image.buf);
818  if (map->image.image_id != VA_INVALID_ID)
819  vaDestroyImage(hwctx->display, map->image.image_id);
820  av_free(map);
821  }
822  return err;
823 }
824 
826  AVFrame *dst, const AVFrame *src)
827 {
828  AVFrame *map;
829  int err;
830 
831  if (dst->width > hwfc->width || dst->height > hwfc->height)
832  return AVERROR(EINVAL);
833 
834  map = av_frame_alloc();
835  if (!map)
836  return AVERROR(ENOMEM);
837  map->format = dst->format;
838 
839  err = vaapi_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ);
840  if (err)
841  goto fail;
842 
843  map->width = dst->width;
844  map->height = dst->height;
845 
846  err = av_frame_copy(dst, map);
847  if (err)
848  goto fail;
849 
850  err = 0;
851 fail:
852  av_frame_free(&map);
853  return err;
854 }
855 
857  AVFrame *dst, const AVFrame *src)
858 {
859  AVFrame *map;
860  int err;
861 
862  if (src->width > hwfc->width || src->height > hwfc->height)
863  return AVERROR(EINVAL);
864 
865  map = av_frame_alloc();
866  if (!map)
867  return AVERROR(ENOMEM);
868  map->format = src->format;
869 
871  if (err)
872  goto fail;
873 
874  map->width = src->width;
875  map->height = src->height;
876 
877  err = av_frame_copy(map, src);
878  if (err)
879  goto fail;
880 
881  err = 0;
882 fail:
883  av_frame_free(&map);
884  return err;
885 }
886 
888  const AVFrame *src, int flags)
889 {
890  int err;
891 
892  if (dst->format != AV_PIX_FMT_NONE) {
893  err = vaapi_get_image_format(hwfc->device_ctx, dst->format, NULL);
894  if (err < 0)
895  return AVERROR(ENOSYS);
896  }
897 
898  err = vaapi_map_frame(hwfc, dst, src, flags);
899  if (err)
900  return err;
901 
902  err = av_frame_copy_props(dst, src);
903  if (err)
904  return err;
905 
906  return 0;
907 }
908 
909 #if CONFIG_LIBDRM
910 
911 #define DRM_MAP(va, layers, ...) { \
912  VA_FOURCC_ ## va, \
913  layers, \
914  { __VA_ARGS__ } \
915  }
916 static const struct {
917  uint32_t va_fourcc;
918  int nb_layer_formats;
919  uint32_t layer_formats[AV_DRM_MAX_PLANES];
920 } vaapi_drm_format_map[] = {
921 #ifdef DRM_FORMAT_R8
922  DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
923 #endif
924  DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
925 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
926  DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
927 #endif
928  DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
929  DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
930  DRM_MAP(RGBA, 1, DRM_FORMAT_ABGR8888),
931  DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
932 #ifdef VA_FOURCC_ABGR
933  DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
934  DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
935 #endif
936  DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
937  DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
938 };
939 #undef DRM_MAP
940 
941 static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc,
942  HWMapDescriptor *hwmap)
943 {
944  AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
945 
946  VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->priv;
947 
948  av_log(dst_fc, AV_LOG_DEBUG, "Destroy surface %#x.\n", surface_id);
949 
950  vaDestroySurfaces(dst_dev->display, &surface_id, 1);
951 }
952 
953 static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
954  const AVFrame *src, int flags)
955 {
956  AVHWFramesContext *dst_fc =
958  AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
959  const AVDRMFrameDescriptor *desc;
960  VASurfaceID surface_id;
961  VAStatus vas;
962  uint32_t va_fourcc, va_rt_format;
963  int err, i, j, k;
964 
965  unsigned long buffer_handle;
966  VASurfaceAttribExternalBuffers buffer_desc;
967  VASurfaceAttrib attrs[2] = {
968  {
969  .type = VASurfaceAttribMemoryType,
970  .flags = VA_SURFACE_ATTRIB_SETTABLE,
971  .value.type = VAGenericValueTypeInteger,
972  .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
973  },
974  {
975  .type = VASurfaceAttribExternalBufferDescriptor,
976  .flags = VA_SURFACE_ATTRIB_SETTABLE,
977  .value.type = VAGenericValueTypePointer,
978  .value.value.p = &buffer_desc,
979  }
980  };
981 
982  desc = (AVDRMFrameDescriptor*)src->data[0];
983 
984  if (desc->nb_objects != 1) {
985  av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames "
986  "made from a single DRM object.\n");
987  return AVERROR(EINVAL);
988  }
989 
990  va_fourcc = 0;
991  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
992  if (desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats)
993  continue;
994  for (j = 0; j < desc->nb_layers; j++) {
995  if (desc->layers[j].format !=
996  vaapi_drm_format_map[i].layer_formats[j])
997  break;
998  }
999  if (j != desc->nb_layers)
1000  continue;
1001  va_fourcc = vaapi_drm_format_map[i].va_fourcc;
1002  break;
1003  }
1004  if (!va_fourcc) {
1005  av_log(dst_fc, AV_LOG_ERROR, "DRM format not supported "
1006  "by VAAPI.\n");
1007  return AVERROR(EINVAL);
1008  }
1009 
1010  av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as "
1011  "%08x.\n", desc->objects[0].fd, va_fourcc);
1012 
1013  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
1014  if (vaapi_format_map[i].fourcc == va_fourcc)
1015  va_rt_format = vaapi_format_map[i].rt_format;
1016  }
1017 
1018  buffer_handle = desc->objects[0].fd;
1019  buffer_desc.pixel_format = va_fourcc;
1020  buffer_desc.width = src_fc->width;
1021  buffer_desc.height = src_fc->height;
1022  buffer_desc.data_size = desc->objects[0].size;
1023  buffer_desc.buffers = &buffer_handle;
1024  buffer_desc.num_buffers = 1;
1025  buffer_desc.flags = 0;
1026 
1027  k = 0;
1028  for (i = 0; i < desc->nb_layers; i++) {
1029  for (j = 0; j < desc->layers[i].nb_planes; j++) {
1030  buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch;
1031  buffer_desc.offsets[k] = desc->layers[i].planes[j].offset;
1032  ++k;
1033  }
1034  }
1035  buffer_desc.num_planes = k;
1036 
1037  vas = vaCreateSurfaces(dst_dev->display, va_rt_format,
1038  src->width, src->height,
1039  &surface_id, 1,
1040  attrs, FF_ARRAY_ELEMS(attrs));
1041  if (vas != VA_STATUS_SUCCESS) {
1042  av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM "
1043  "object: %d (%s).\n", vas, vaErrorStr(vas));
1044  return AVERROR(EIO);
1045  }
1046  av_log(dst_fc, AV_LOG_DEBUG, "Create surface %#x.\n", surface_id);
1047 
1048  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
1049  &vaapi_unmap_from_drm,
1050  (void*)(uintptr_t)surface_id);
1051  if (err < 0)
1052  return err;
1053 
1054  dst->width = src->width;
1055  dst->height = src->height;
1056  dst->data[3] = (uint8_t*)(uintptr_t)surface_id;
1057 
1058  av_log(dst_fc, AV_LOG_DEBUG, "Mapped DRM object %d to "
1059  "surface %#x.\n", desc->objects[0].fd, surface_id);
1060 
1061  return 0;
1062 }
1063 
1064 static void vaapi_unmap_to_drm(AVHWFramesContext *dst_fc,
1065  HWMapDescriptor *hwmap)
1066 {
1067  AVDRMFrameDescriptor *drm_desc = hwmap->priv;
1068  int i;
1069 
1070  for (i = 0; i < drm_desc->nb_objects; i++)
1071  close(drm_desc->objects[i].fd);
1072 
1073  av_freep(&drm_desc);
1074 }
1075 
1076 static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
1077  const AVFrame *src, int flags)
1078 {
1079  // Older versions without vaExportSurfaceHandle() are not supported -
1080  // in theory this is possible with a combination of vaDeriveImage()
1081  // and vaAcquireBufferHandle(), but it doesn't carry enough metadata
1082  // to actually use the result in a generic way.
1083  return AVERROR(ENOSYS);
1084 }
1085 #endif
1086 
1087 static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
1088  const AVFrame *src, int flags)
1089 {
1090  switch (src->format) {
1091 #if CONFIG_LIBDRM
1092  case AV_PIX_FMT_DRM_PRIME:
1093  return vaapi_map_from_drm(hwfc, dst, src, flags);
1094 #endif
1095  default:
1096  return AVERROR(ENOSYS);
1097  }
1098 }
1099 
1101  const AVFrame *src, int flags)
1102 {
1103  switch (dst->format) {
1104 #if CONFIG_LIBDRM
1105  case AV_PIX_FMT_DRM_PRIME:
1106  return vaapi_map_to_drm(hwfc, dst, src, flags);
1107 #endif
1108  default:
1109  return vaapi_map_to_memory(hwfc, dst, src, flags);
1110  }
1111 }
1112 
1114 {
1115  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1116  VAAPIDevicePriv *priv = ctx->user_opaque;
1117 
1118  if (hwctx->display)
1119  vaTerminate(hwctx->display);
1120 
1121 #if HAVE_VAAPI_X11
1122  if (priv->x11_display)
1123  XCloseDisplay(priv->x11_display);
1124 #endif
1125 
1126  if (priv->drm_fd >= 0)
1127  close(priv->drm_fd);
1128 
1129  av_freep(&priv);
1130 }
1131 
1132 #if CONFIG_VAAPI_1
1133 static void vaapi_device_log_error(void *context, const char *message)
1134 {
1135  AVHWDeviceContext *ctx = context;
1136 
1137  av_log(ctx, AV_LOG_ERROR, "libva: %s", message);
1138 }
1139 
1140 static void vaapi_device_log_info(void *context, const char *message)
1141 {
1142  AVHWDeviceContext *ctx = context;
1143 
1144  av_log(ctx, AV_LOG_VERBOSE, "libva: %s", message);
1145 }
1146 #endif
1147 
1149  VADisplay display)
1150 {
1151  AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1152  int major, minor;
1153  VAStatus vas;
1154 
1155 #if CONFIG_VAAPI_1
1156  vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
1157  vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
1158 #endif
1159 
1160  hwctx->display = display;
1161 
1162  vas = vaInitialize(display, &major, &minor);
1163  if (vas != VA_STATUS_SUCCESS) {
1164  av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
1165  "connection: %d (%s).\n", vas, vaErrorStr(vas));
1166  return AVERROR(EIO);
1167  }
1168  av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
1169  "version %d.%d\n", major, minor);
1170 
1171  return 0;
1172 }
1173 
1174 static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
1175  AVDictionary *opts, int flags)
1176 {
1177  VAAPIDevicePriv *priv;
1178  VADisplay display = NULL;
1179 
1180  priv = av_mallocz(sizeof(*priv));
1181  if (!priv)
1182  return AVERROR(ENOMEM);
1183 
1184  priv->drm_fd = -1;
1185 
1186  ctx->user_opaque = priv;
1187  ctx->free = vaapi_device_free;
1188 
1189 #if HAVE_VAAPI_X11
1190  if (!display && !(device && device[0] == '/')) {
1191  // Try to open the device as an X11 display.
1192  priv->x11_display = XOpenDisplay(device);
1193  if (!priv->x11_display) {
1194  av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
1195  "%s.\n", XDisplayName(device));
1196  } else {
1197  display = vaGetDisplay(priv->x11_display);
1198  if (!display) {
1199  av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1200  "from X11 display %s.\n", XDisplayName(device));
1201  return AVERROR_UNKNOWN;
1202  }
1203 
1204  av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1205  "X11 display %s.\n", XDisplayName(device));
1206  }
1207  }
1208 #endif
1209 
1210 #if HAVE_VAAPI_DRM
1211  if (!display) {
1212  // Try to open the device as a DRM path.
1213  // Default to using the first render node if the user did not
1214  // supply a path.
1215  const char *path = device ? device : "/dev/dri/renderD128";
1216  priv->drm_fd = open(path, O_RDWR);
1217  if (priv->drm_fd < 0) {
1218  av_log(ctx, AV_LOG_VERBOSE, "Cannot open DRM device %s.\n",
1219  path);
1220  } else {
1221  display = vaGetDisplayDRM(priv->drm_fd);
1222  if (!display) {
1223  av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1224  "from DRM device %s.\n", path);
1225  return AVERROR_UNKNOWN;
1226  }
1227 
1228  av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1229  "DRM device %s.\n", path);
1230  }
1231  }
1232 #endif
1233 
1234  if (!display) {
1235  av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1236  "device: %s.\n", device ? device : "");
1237  return AVERROR(EINVAL);
1238  }
1239 
1240  return vaapi_device_connect(ctx, display);
1241 }
1242 
1244  AVHWDeviceContext *src_ctx, int flags)
1245 {
1246 #if CONFIG_LIBDRM
1247  if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
1248  AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
1249  VADisplay *display;
1250  VAAPIDevicePriv *priv;
1251 
1252  if (src_hwctx->fd < 0) {
1253  av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated "
1254  "device to derive a VA display from.\n");
1255  return AVERROR(EINVAL);
1256  }
1257 
1258  priv = av_mallocz(sizeof(*priv));
1259  if (!priv)
1260  return AVERROR(ENOMEM);
1261 
1262  // Inherits the fd from the source context, which will close it.
1263  priv->drm_fd = -1;
1264 
1265  ctx->user_opaque = priv;
1266  ctx->free = &vaapi_device_free;
1267 
1268  display = vaGetDisplayDRM(src_hwctx->fd);
1269  if (!display) {
1270  av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
1271  "DRM device.\n");
1272  return AVERROR(EIO);
1273  }
1274 
1275  return vaapi_device_connect(ctx, display);
1276  }
1277 #endif
1278  return AVERROR(ENOSYS);
1279 }
1280 
1283  .name = "VAAPI",
1284 
1285  .device_hwctx_size = sizeof(AVVAAPIDeviceContext),
1286  .device_priv_size = sizeof(VAAPIDeviceContext),
1287  .device_hwconfig_size = sizeof(AVVAAPIHWConfig),
1288  .frames_hwctx_size = sizeof(AVVAAPIFramesContext),
1289  .frames_priv_size = sizeof(VAAPIFramesContext),
1290 
1291  .device_create = &vaapi_device_create,
1292  .device_derive = &vaapi_device_derive,
1294  .device_uninit = &vaapi_device_uninit,
1295  .frames_get_constraints = &vaapi_frames_get_constraints,
1296  .frames_init = &vaapi_frames_init,
1297  .frames_uninit = &vaapi_frames_uninit,
1298  .frames_get_buffer = &vaapi_get_buffer,
1299  .transfer_get_formats = &vaapi_transfer_get_formats,
1300  .transfer_data_to = &vaapi_transfer_data_to,
1301  .transfer_data_from = &vaapi_transfer_data_from,
1302  .map_to = &vaapi_map_to,
1303  .map_from = &vaapi_map_from,
1304 
1305  .pix_fmts = (const enum AVPixelFormat[]) {
1308  },
1309 };
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:58
#define NULL
Definition: coverity.c:32
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:201
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static void vaapi_device_free(AVHWDeviceContext *ctx)
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pixelformat)
Definition: v4l2.c:188
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:393
const char * desc
Definition: nvenc.c:60
static FFServerConfig config
Definition: ffserver.c:193
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:226
static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
unsigned int rt_format
#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:222
#define src
Definition: vp8dsp.c:254
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:455
int nb_objects
Number of DRM objects making up this frame.
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
The mapping must be readable.
Definition: hwcontext.h:501
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:538
static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vaapi_device_init(AVHWDeviceContext *hwdev)
DRM frame descriptor.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AVBufferPool * pool_internal
enum AVHWDeviceType type
The driver does not support the VASurfaceAttribMemoryType attribute, so the surface allocation code w...
uint8_t
#define av_malloc(s)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:150
static void vaapi_buffer_free(void *opaque, uint8_t *data)
static int vaapi_device_connect(AVHWDeviceContext *ctx, VADisplay display)
static void vaapi_frames_uninit(AVHWFramesContext *hwfc)
static AVFrame * frame
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:89
static int flags
Definition: log.c:57
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:113
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
ptrdiff_t size
Definition: opengl_enc.c:101
static int vaapi_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, int flags)
#define av_log(a,...)
static int vaapi_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
int fd
DRM PRIME fd for the object.
Definition: hwcontext_drm.h:52
The quirks field has been set by the user and should not be detected automatically by av_hwdevice_ctx...
int width
Definition: frame.h:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
The mapping must be direct.
Definition: hwcontext.h:517
VAAPI hardware pipeline configuration details.
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
Definition: hwcontext.h:101
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:163
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
simple assert() macros that are a bit more flexible than ISO C assert().
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:28
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:76
VASurfaceAttrib * attributes
#define fail()
Definition: checkasm.h:109
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:740
const char * match_string
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:196
AVDictionary * opts
Definition: movenc.c:50
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.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:146
enum AVPixelFormat pix_fmt
AVFormatContext * ctx
Definition: movenc.c:48
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)
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)
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:274
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:448
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:430
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:232
static const struct @247 vaapi_format_map[]
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:159
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
GLint GLenum type
Definition: opengl_enc.c:105
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition: hwcontext.c:681
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:342
#define MAP(va, rt, av)
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:121
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:435
const VDPAUPixFmtMap * map
static int vaapi_get_image_format(AVHWDeviceContext *hwdev, enum AVPixelFormat pix_fmt, VAImageFormat **image_format)
API-specific header for AV_HWDEVICE_TYPE_DRM.
AVHWFramesInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:131
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
static void vaapi_device_uninit(AVHWDeviceContext *hwdev)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:215
void * user_opaque
Arbitrary user data, to be used e.g.
Definition: hwcontext.h:106
VAImageFormat image_format
enum AVPixelFormat pix_fmt
static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
A reference to a data buffer.
Definition: buffer.h:81
common internal and external API header
if(ret< 0)
Definition: vf_mcdeint.c:279
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
int fd
File descriptor of DRM device.
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:511
static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, const void *hwconfig, AVHWFramesConstraints *constraints)
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
AVHWFrameTransferDirection
Definition: hwcontext.h:392
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:187
#define av_free(p)
The mapping must be writeable.
Definition: hwcontext.h:505
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:442
#define H
Definition: pixlet.c:37
unsigned int quirks
VAAPI connection details.
VAConfigID config_id
ID of a VAAPI pipeline configuration.
int height
Definition: frame.h:259
const HWContextType ff_hwcontext_type_vaapi
#define av_freep(p)
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:334
#define av_malloc_array(a, b)
formats
Definition: signature.h:48
#define FFSWAP(type, a, b)
Definition: common.h:99
AVHWDeviceInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:68
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:2335
unsigned int rt_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:219
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
unsigned int fourcc
The driver does not support surface attributes at all.
static const struct @248 vaapi_driver_quirks_table[]
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:603