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