FFmpeg
vaapi_decode.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 "libavutil/avassert.h"
20 #include "libavutil/common.h"
21 #include "libavutil/pixdesc.h"
22 
23 #include "avcodec.h"
24 #include "decode.h"
25 #include "internal.h"
26 #include "vaapi_decode.h"
27 #include "vaapi_hevc.h"
28 
29 
31  VAAPIDecodePicture *pic,
32  int type,
33  const void *data,
34  size_t size)
35 {
37  VAStatus vas;
38  VABufferID buffer;
39 
41 
42  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
43  type, size, 1, (void*)data, &buffer);
44  if (vas != VA_STATUS_SUCCESS) {
45  av_log(avctx, AV_LOG_ERROR, "Failed to create parameter "
46  "buffer (type %d): %d (%s).\n",
47  type, vas, vaErrorStr(vas));
48  return AVERROR(EIO);
49  }
50 
51  pic->param_buffers[pic->nb_param_buffers++] = buffer;
52 
53  av_log(avctx, AV_LOG_DEBUG, "Param buffer (type %d, %zu bytes) "
54  "is %#x.\n", type, size, buffer);
55  return 0;
56 }
57 
58 
60  VAAPIDecodePicture *pic,
61  const void *params_data,
62  size_t params_size,
63  const void *slice_data,
64  size_t slice_size)
65 {
67  VAStatus vas;
68  int index;
69 
71  if (pic->nb_slices == pic->slices_allocated) {
72  if (pic->slices_allocated > 0)
73  pic->slices_allocated *= 2;
74  else
75  pic->slices_allocated = 64;
76 
77  pic->slice_buffers =
79  pic->slices_allocated,
80  2 * sizeof(*pic->slice_buffers));
81  if (!pic->slice_buffers)
82  return AVERROR(ENOMEM);
83  }
84  av_assert0(pic->nb_slices + 1 <= pic->slices_allocated);
85 
86  index = 2 * pic->nb_slices;
87 
88  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
89  VASliceParameterBufferType,
90  params_size, 1, (void*)params_data,
91  &pic->slice_buffers[index]);
92  if (vas != VA_STATUS_SUCCESS) {
93  av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
94  "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
95  return AVERROR(EIO);
96  }
97 
98  av_log(avctx, AV_LOG_DEBUG, "Slice %d param buffer (%zu bytes) "
99  "is %#x.\n", pic->nb_slices, params_size,
100  pic->slice_buffers[index]);
101 
102  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
103  VASliceDataBufferType,
104  slice_size, 1, (void*)slice_data,
105  &pic->slice_buffers[index + 1]);
106  if (vas != VA_STATUS_SUCCESS) {
107  av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
108  "data buffer (size %zu): %d (%s).\n",
109  slice_size, vas, vaErrorStr(vas));
110  vaDestroyBuffer(ctx->hwctx->display,
111  pic->slice_buffers[index]);
112  return AVERROR(EIO);
113  }
114 
115  av_log(avctx, AV_LOG_DEBUG, "Slice %d data buffer (%zu bytes) "
116  "is %#x.\n", pic->nb_slices, slice_size,
117  pic->slice_buffers[index + 1]);
118 
119  ++pic->nb_slices;
120  return 0;
121 }
122 
124  VAAPIDecodePicture *pic)
125 {
127  VAStatus vas;
128  int i;
129 
130  for (i = 0; i < pic->nb_param_buffers; i++) {
131  vas = vaDestroyBuffer(ctx->hwctx->display,
132  pic->param_buffers[i]);
133  if (vas != VA_STATUS_SUCCESS) {
134  av_log(avctx, AV_LOG_ERROR, "Failed to destroy "
135  "parameter buffer %#x: %d (%s).\n",
136  pic->param_buffers[i], vas, vaErrorStr(vas));
137  }
138  }
139 
140  for (i = 0; i < 2 * pic->nb_slices; i++) {
141  vas = vaDestroyBuffer(ctx->hwctx->display,
142  pic->slice_buffers[i]);
143  if (vas != VA_STATUS_SUCCESS) {
144  av_log(avctx, AV_LOG_ERROR, "Failed to destroy slice "
145  "slice buffer %#x: %d (%s).\n",
146  pic->slice_buffers[i], vas, vaErrorStr(vas));
147  }
148  }
149 }
150 
152  VAAPIDecodePicture *pic)
153 {
155  VAStatus vas;
156  int err;
157 
158  av_log(avctx, AV_LOG_DEBUG, "Decode to surface %#x.\n",
159  pic->output_surface);
160 
161  vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
162  pic->output_surface);
163  if (vas != VA_STATUS_SUCCESS) {
164  av_log(avctx, AV_LOG_ERROR, "Failed to begin picture decode "
165  "issue: %d (%s).\n", vas, vaErrorStr(vas));
166  err = AVERROR(EIO);
167  goto fail_with_picture;
168  }
169 
170  vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
171  pic->param_buffers, pic->nb_param_buffers);
172  if (vas != VA_STATUS_SUCCESS) {
173  av_log(avctx, AV_LOG_ERROR, "Failed to upload decode "
174  "parameters: %d (%s).\n", vas, vaErrorStr(vas));
175  err = AVERROR(EIO);
176  goto fail_with_picture;
177  }
178 
179  vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
180  pic->slice_buffers, 2 * pic->nb_slices);
181  if (vas != VA_STATUS_SUCCESS) {
182  av_log(avctx, AV_LOG_ERROR, "Failed to upload slices: "
183  "%d (%s).\n", vas, vaErrorStr(vas));
184  err = AVERROR(EIO);
185  goto fail_with_picture;
186  }
187 
188  vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
189  if (vas != VA_STATUS_SUCCESS) {
190  av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
191  "issue: %d (%s).\n", vas, vaErrorStr(vas));
192  err = AVERROR(EIO);
193  if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
195  goto fail;
196  else
197  goto fail_at_end;
198  }
199 
200  if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
203 
204  err = 0;
205  goto exit;
206 
207 fail_with_picture:
208  vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
209  if (vas != VA_STATUS_SUCCESS) {
210  av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
211  "after error: %d (%s).\n", vas, vaErrorStr(vas));
212  }
213 fail:
215 fail_at_end:
216 exit:
217  pic->nb_param_buffers = 0;
218  pic->nb_slices = 0;
219  pic->slices_allocated = 0;
220  av_freep(&pic->slice_buffers);
221 
222  return err;
223 }
224 
226  VAAPIDecodePicture *pic)
227 {
229 
230  pic->nb_param_buffers = 0;
231  pic->nb_slices = 0;
232  pic->slices_allocated = 0;
233  av_freep(&pic->slice_buffers);
234 
235  return 0;
236 }
237 
238 static const struct {
239  uint32_t fourcc;
241 } vaapi_format_map[] = {
242 #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
243  // 4:0:0
244  MAP(Y800, GRAY8),
245  // 4:2:0
246  MAP(NV12, NV12),
247  MAP(YV12, YUV420P),
248  MAP(IYUV, YUV420P),
249 #ifdef VA_FOURCC_I420
250  MAP(I420, YUV420P),
251 #endif
252  MAP(IMC3, YUV420P),
253  // 4:1:1
254  MAP(411P, YUV411P),
255  // 4:2:2
256  MAP(422H, YUV422P),
257 #ifdef VA_FOURCC_YV16
258  MAP(YV16, YUV422P),
259 #endif
260  MAP(YUY2, YUYV422),
261 #ifdef VA_FOURCC_Y210
262  MAP(Y210, Y210),
263 #endif
264  // 4:4:0
265  MAP(422V, YUV440P),
266  // 4:4:4
267  MAP(444P, YUV444P),
268  // 4:2:0 10-bit
269 #ifdef VA_FOURCC_P010
270  MAP(P010, P010),
271 #endif
272 #ifdef VA_FOURCC_I010
273  MAP(I010, YUV420P10),
274 #endif
275 #undef MAP
276 };
277 
279  AVHWDeviceContext *device,
280  VAConfigID config_id,
282 {
283  AVVAAPIDeviceContext *hwctx = device->hwctx;
284  VAStatus vas;
285  VASurfaceAttrib *attr;
286  enum AVPixelFormat source_format, best_format, format;
287  uint32_t best_fourcc, fourcc;
288  int i, j, nb_attr;
289 
290  source_format = avctx->sw_pix_fmt;
291  av_assert0(source_format != AV_PIX_FMT_NONE);
292 
293  vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
294  NULL, &nb_attr);
295  if (vas != VA_STATUS_SUCCESS) {
296  av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
297  "%d (%s).\n", vas, vaErrorStr(vas));
298  return AVERROR(ENOSYS);
299  }
300 
301  attr = av_malloc_array(nb_attr, sizeof(*attr));
302  if (!attr)
303  return AVERROR(ENOMEM);
304 
305  vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
306  attr, &nb_attr);
307  if (vas != VA_STATUS_SUCCESS) {
308  av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
309  "%d (%s).\n", vas, vaErrorStr(vas));
310  av_freep(&attr);
311  return AVERROR(ENOSYS);
312  }
313 
314  best_format = AV_PIX_FMT_NONE;
315 
316  for (i = 0; i < nb_attr; i++) {
317  if (attr[i].type != VASurfaceAttribPixelFormat)
318  continue;
319 
320  fourcc = attr[i].value.value.i;
321  for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map); j++) {
322  if (fourcc == vaapi_format_map[j].fourcc)
323  break;
324  }
325  if (j >= FF_ARRAY_ELEMS(vaapi_format_map)) {
326  av_log(avctx, AV_LOG_DEBUG, "Ignoring unknown format %#x.\n",
327  fourcc);
328  continue;
329  }
330  format = vaapi_format_map[j].pix_fmt;
331  av_log(avctx, AV_LOG_DEBUG, "Considering format %#x -> %s.\n",
332  fourcc, av_get_pix_fmt_name(format));
333 
334  best_format = av_find_best_pix_fmt_of_2(format, best_format,
335  source_format, 0, NULL);
336  if (format == best_format)
337  best_fourcc = fourcc;
338  }
339 
340  av_freep(&attr);
341 
342  if (best_format == AV_PIX_FMT_NONE) {
343  av_log(avctx, AV_LOG_ERROR, "No usable formats for decoding!\n");
344  return AVERROR(EINVAL);
345  }
346 
347  av_log(avctx, AV_LOG_DEBUG, "Picked %s (%#x) as best match for %s.\n",
348  av_get_pix_fmt_name(best_format), best_fourcc,
349  av_get_pix_fmt_name(source_format));
350 
351  frames->sw_format = best_format;
352  if (avctx->internal->hwaccel_priv_data) {
354  AVVAAPIFramesContext *avfc = frames->hwctx;
355 
356  ctx->pixel_format_attribute = (VASurfaceAttrib) {
357  .type = VASurfaceAttribPixelFormat,
358  .value.value.i = best_fourcc,
359  };
360 
361  avfc->attributes = &ctx->pixel_format_attribute;
362  avfc->nb_attributes = 1;
363  }
364 
365  return 0;
366 }
367 
368 static const struct {
371  VAProfile va_profile;
372  VAProfile (*profile_parser)(AVCodecContext *avctx);
373 } vaapi_profile_map[] = {
374 #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ }
375  MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ),
376  MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ),
377  MAP(H263, UNKNOWN, H263Baseline),
378  MAP(MPEG4, MPEG4_SIMPLE, MPEG4Simple ),
379  MAP(MPEG4, MPEG4_ADVANCED_SIMPLE,
380  MPEG4AdvancedSimple),
381  MAP(MPEG4, MPEG4_MAIN, MPEG4Main ),
382  MAP(H264, H264_CONSTRAINED_BASELINE,
383  H264ConstrainedBaseline),
384  MAP(H264, H264_MAIN, H264Main ),
385  MAP(H264, H264_HIGH, H264High ),
386 #if VA_CHECK_VERSION(0, 37, 0)
387  MAP(HEVC, HEVC_MAIN, HEVCMain ),
388  MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ),
389  MAP(HEVC, HEVC_MAIN_STILL_PICTURE,
390  HEVCMain ),
391 #endif
392 #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
393  MAP(HEVC, HEVC_REXT, None,
395 #endif
396  MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT,
397  JPEGBaseline),
398  MAP(WMV3, VC1_SIMPLE, VC1Simple ),
399  MAP(WMV3, VC1_MAIN, VC1Main ),
400  MAP(WMV3, VC1_COMPLEX, VC1Advanced ),
401  MAP(WMV3, VC1_ADVANCED, VC1Advanced ),
402  MAP(VC1, VC1_SIMPLE, VC1Simple ),
403  MAP(VC1, VC1_MAIN, VC1Main ),
404  MAP(VC1, VC1_COMPLEX, VC1Advanced ),
405  MAP(VC1, VC1_ADVANCED, VC1Advanced ),
406  MAP(VP8, UNKNOWN, VP8Version0_3 ),
407 #if VA_CHECK_VERSION(0, 38, 0)
408  MAP(VP9, VP9_0, VP9Profile0 ),
409 #endif
410 #if VA_CHECK_VERSION(0, 39, 0)
411  MAP(VP9, VP9_2, VP9Profile2 ),
412 #endif
413 #undef MAP
414 };
415 
416 /*
417  * Set *va_config and the frames_ref fields from the current codec parameters
418  * in avctx.
419  */
421  AVBufferRef *device_ref,
422  VAConfigID *va_config,
423  AVBufferRef *frames_ref)
424 {
425  AVVAAPIHWConfig *hwconfig = NULL;
426  AVHWFramesConstraints *constraints = NULL;
427  VAStatus vas;
428  int err, i, j;
429  const AVCodecDescriptor *codec_desc;
430  VAProfile *profile_list = NULL, matched_va_profile, va_profile;
431  int profile_count, exact_match, matched_ff_profile, codec_profile;
432 
433  AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data;
434  AVVAAPIDeviceContext *hwctx = device->hwctx;
435 
436  codec_desc = avcodec_descriptor_get(avctx->codec_id);
437  if (!codec_desc) {
438  err = AVERROR(EINVAL);
439  goto fail;
440  }
441 
442  profile_count = vaMaxNumProfiles(hwctx->display);
443  profile_list = av_malloc_array(profile_count,
444  sizeof(VAProfile));
445  if (!profile_list) {
446  err = AVERROR(ENOMEM);
447  goto fail;
448  }
449 
450  vas = vaQueryConfigProfiles(hwctx->display,
451  profile_list, &profile_count);
452  if (vas != VA_STATUS_SUCCESS) {
453  av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: "
454  "%d (%s).\n", vas, vaErrorStr(vas));
455  err = AVERROR(ENOSYS);
456  goto fail;
457  }
458 
459  matched_va_profile = VAProfileNone;
460  exact_match = 0;
461 
462  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) {
463  int profile_match = 0;
464  if (avctx->codec_id != vaapi_profile_map[i].codec_id)
465  continue;
466  if (avctx->profile == vaapi_profile_map[i].codec_profile ||
467  vaapi_profile_map[i].codec_profile == FF_PROFILE_UNKNOWN)
468  profile_match = 1;
469 
470  va_profile = vaapi_profile_map[i].profile_parser ?
471  vaapi_profile_map[i].profile_parser(avctx) :
472  vaapi_profile_map[i].va_profile;
473  codec_profile = vaapi_profile_map[i].codec_profile;
474 
475  for (j = 0; j < profile_count; j++) {
476  if (va_profile == profile_list[j]) {
477  exact_match = profile_match;
478  break;
479  }
480  }
481  if (j < profile_count) {
482  matched_va_profile = va_profile;
483  matched_ff_profile = codec_profile;
484  if (exact_match)
485  break;
486  }
487  }
488  av_freep(&profile_list);
489 
490  if (matched_va_profile == VAProfileNone) {
491  av_log(avctx, AV_LOG_ERROR, "No support for codec %s "
492  "profile %d.\n", codec_desc->name, avctx->profile);
493  err = AVERROR(ENOSYS);
494  goto fail;
495  }
496  if (!exact_match) {
497  if (avctx->hwaccel_flags &
499  av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
500  "supported for hardware decode.\n",
501  codec_desc->name, avctx->profile);
502  av_log(avctx, AV_LOG_WARNING, "Using possibly-"
503  "incompatible profile %d instead.\n",
504  matched_ff_profile);
505  } else {
506  av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
507  "supported for hardware decode.\n",
508  codec_desc->name, avctx->profile);
509  err = AVERROR(EINVAL);
510  goto fail;
511  }
512  }
513 
514  vas = vaCreateConfig(hwctx->display, matched_va_profile,
515  VAEntrypointVLD, NULL, 0,
516  va_config);
517  if (vas != VA_STATUS_SUCCESS) {
518  av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
519  "configuration: %d (%s).\n", vas, vaErrorStr(vas));
520  err = AVERROR(EIO);
521  goto fail;
522  }
523 
524  hwconfig = av_hwdevice_hwconfig_alloc(device_ref);
525  if (!hwconfig) {
526  err = AVERROR(ENOMEM);
527  goto fail;
528  }
529  hwconfig->config_id = *va_config;
530 
531  constraints =
532  av_hwdevice_get_hwframe_constraints(device_ref, hwconfig);
533  if (!constraints) {
534  err = AVERROR(ENOMEM);
535  goto fail;
536  }
537 
538  if (avctx->coded_width < constraints->min_width ||
539  avctx->coded_height < constraints->min_height ||
540  avctx->coded_width > constraints->max_width ||
541  avctx->coded_height > constraints->max_height) {
542  av_log(avctx, AV_LOG_ERROR, "Hardware does not support image "
543  "size %dx%d (constraints: width %d-%d height %d-%d).\n",
544  avctx->coded_width, avctx->coded_height,
545  constraints->min_width, constraints->max_width,
546  constraints->min_height, constraints->max_height);
547  err = AVERROR(EINVAL);
548  goto fail;
549  }
550  if (!constraints->valid_sw_formats ||
551  constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) {
552  av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any "
553  "usable surface formats.\n");
554  err = AVERROR(EINVAL);
555  goto fail;
556  }
557 
558  if (frames_ref) {
560 
561  frames->format = AV_PIX_FMT_VAAPI;
562  frames->width = avctx->coded_width;
563  frames->height = avctx->coded_height;
564 
565  err = vaapi_decode_find_best_format(avctx, device,
566  *va_config, frames);
567  if (err < 0)
568  goto fail;
569 
570  frames->initial_pool_size = 1;
571  // Add per-codec number of surfaces used for storing reference frames.
572  switch (avctx->codec_id) {
573  case AV_CODEC_ID_H264:
574  case AV_CODEC_ID_HEVC:
575  frames->initial_pool_size += 16;
576  break;
577  case AV_CODEC_ID_VP9:
578  frames->initial_pool_size += 8;
579  break;
580  case AV_CODEC_ID_VP8:
581  frames->initial_pool_size += 3;
582  break;
583  default:
584  frames->initial_pool_size += 2;
585  }
586  }
587 
588  av_hwframe_constraints_free(&constraints);
589  av_freep(&hwconfig);
590 
591  return 0;
592 
593 fail:
594  av_hwframe_constraints_free(&constraints);
595  av_freep(&hwconfig);
596  if (*va_config != VA_INVALID_ID) {
597  vaDestroyConfig(hwctx->display, *va_config);
598  *va_config = VA_INVALID_ID;
599  }
600  av_freep(&profile_list);
601  return err;
602 }
603 
605  AVBufferRef *hw_frames_ctx)
606 {
607  AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data;
608  AVHWDeviceContext *device_ctx = hw_frames->device_ctx;
609  AVVAAPIDeviceContext *hwctx;
610  VAConfigID va_config = VA_INVALID_ID;
611  int err;
612 
613  if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI)
614  return AVERROR(EINVAL);
615  hwctx = device_ctx->hwctx;
616 
617  err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config,
618  hw_frames_ctx);
619  if (err)
620  return err;
621 
622  if (va_config != VA_INVALID_ID)
623  vaDestroyConfig(hwctx->display, va_config);
624 
625  return 0;
626 }
627 
629 {
631  VAStatus vas;
632  int err;
633 
634  ctx->va_config = VA_INVALID_ID;
635  ctx->va_context = VA_INVALID_ID;
636 
637 #if FF_API_STRUCT_VAAPI_CONTEXT
638  if (avctx->hwaccel_context) {
639  av_log(avctx, AV_LOG_WARNING, "Using deprecated struct "
640  "vaapi_context in decode.\n");
641 
642  ctx->have_old_context = 1;
643  ctx->old_context = avctx->hwaccel_context;
644 
645  // Really we only want the VAAPI device context, but this
646  // allocates a whole generic device context because we don't
647  // have any other way to determine how big it should be.
648  ctx->device_ref =
650  if (!ctx->device_ref) {
651  err = AVERROR(ENOMEM);
652  goto fail;
653  }
654  ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
655  ctx->hwctx = ctx->device->hwctx;
656 
657  ctx->hwctx->display = ctx->old_context->display;
658 
659  // The old VAAPI decode setup assumed this quirk was always
660  // present, so set it here to avoid the behaviour changing.
661  ctx->hwctx->driver_quirks =
663 
664  }
665 #endif
666 
667 #if FF_API_STRUCT_VAAPI_CONTEXT
668  if (ctx->have_old_context) {
669  ctx->va_config = ctx->old_context->config_id;
670  ctx->va_context = ctx->old_context->context_id;
671 
672  av_log(avctx, AV_LOG_DEBUG, "Using user-supplied decoder "
673  "context: %#x/%#x.\n", ctx->va_config, ctx->va_context);
674  } else {
675 #endif
676 
678  if (err < 0)
679  goto fail;
680 
681  ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
682  ctx->hwfc = ctx->frames->hwctx;
683  ctx->device = ctx->frames->device_ctx;
684  ctx->hwctx = ctx->device->hwctx;
685 
686  err = vaapi_decode_make_config(avctx, ctx->frames->device_ref,
687  &ctx->va_config, avctx->hw_frames_ctx);
688  if (err)
689  goto fail;
690 
691  vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
692  avctx->coded_width, avctx->coded_height,
693  VA_PROGRESSIVE,
694  ctx->hwfc->surface_ids,
695  ctx->hwfc->nb_surfaces,
696  &ctx->va_context);
697  if (vas != VA_STATUS_SUCCESS) {
698  av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
699  "context: %d (%s).\n", vas, vaErrorStr(vas));
700  err = AVERROR(EIO);
701  goto fail;
702  }
703 
704  av_log(avctx, AV_LOG_DEBUG, "Decode context initialised: "
705  "%#x/%#x.\n", ctx->va_config, ctx->va_context);
706 #if FF_API_STRUCT_VAAPI_CONTEXT
707  }
708 #endif
709 
710  return 0;
711 
712 fail:
713  ff_vaapi_decode_uninit(avctx);
714  return err;
715 }
716 
718 {
720  VAStatus vas;
721 
722 #if FF_API_STRUCT_VAAPI_CONTEXT
723  if (ctx->have_old_context) {
725  } else {
726 #endif
727 
728  if (ctx->va_context != VA_INVALID_ID) {
729  vas = vaDestroyContext(ctx->hwctx->display, ctx->va_context);
730  if (vas != VA_STATUS_SUCCESS) {
731  av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
732  "context %#x: %d (%s).\n",
733  ctx->va_context, vas, vaErrorStr(vas));
734  }
735  }
736  if (ctx->va_config != VA_INVALID_ID) {
737  vas = vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
738  if (vas != VA_STATUS_SUCCESS) {
739  av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
740  "configuration %#x: %d (%s).\n",
741  ctx->va_config, vas, vaErrorStr(vas));
742  }
743  }
744 
745 #if FF_API_STRUCT_VAAPI_CONTEXT
746  }
747 #endif
748 
749  return 0;
750 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
#define NULL
Definition: coverity.c:32
#define P
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
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.
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:714
VAProfile(* profile_parser)(AVCodecContext *avctx)
Definition: vaapi_decode.c:372
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
VASurfaceAttrib * attributes
Set by the user to apply surface attributes to all surfaces in the frame pool.
static void ff_vaapi_decode_destroy_buffers(AVCodecContext *avctx, VAAPIDecodePicture *pic)
Definition: vaapi_decode.c:123
int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx, VAAPIDecodePicture *pic, int type, const void *data, size_t size)
Definition: vaapi_decode.c:30
uint32_t fourcc
Definition: vaapi_decode.c:239
VASurfaceAttrib pixel_format_attribute
Definition: vaapi_decode.h:76
enum AVPixelFormat pix_fmt
Definition: vaapi_decode.c:240
uint32_t context_id
Context ID (video decode pipeline)
Definition: vaapi.h:79
FF_ENABLE_DEPRECATION_WARNINGS AVHWDeviceContext * device
Definition: vaapi_decode.h:67
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:229
void * av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
Allocate a HW-specific configuration structure for a given HW device.
Definition: hwcontext.c:565
GLint GLenum type
Definition: opengl_enc.c:104
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:209
int profile
profile
Definition: avcodec.h:1859
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 format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
if it could not because there are no more frames
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:478
Definition: ftp.c:37
int ff_vaapi_common_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
Definition: vaapi_decode.c:604
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition: hwcontext.c:601
static int vaapi_decode_find_best_format(AVCodecContext *avctx, AVHWDeviceContext *device, VAConfigID config_id, AVHWFramesContext *frames)
Definition: vaapi_decode.c:278
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_vaapi_decode_uninit(AVCodecContext *avctx)
Definition: vaapi_decode.c:717
void * hwaccel_context
Hardware accelerator context.
Definition: avcodec.h:1702
int ff_vaapi_decode_issue(AVCodecContext *avctx, VAAPIDecodePicture *pic)
Definition: vaapi_decode.c:151
AVHWFramesContext * frames
Definition: vaapi_decode.h:70
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
AVVAAPIDeviceContext * hwctx
Definition: vaapi_decode.h:68
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
ptrdiff_t size
Definition: opengl_enc.c:100
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:198
#define av_log(a,...)
int codec_profile
Definition: vaapi_decode.c:370
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
AVVAAPIFramesContext * hwfc
Definition: vaapi_decode.h:71
VAAPI hardware pipeline configuration details.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
simple assert() macros that are a bit more flexible than ISO C assert().
VAProfile va_profile
Definition: vaapi_decode.c:371
#define fail()
Definition: checkasm.h:123
FF_DISABLE_DEPRECATION_WARNINGS int have_old_context
Definition: vaapi_decode.h:61
static const struct @155 vaapi_format_map[]
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:199
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:149
int ff_vaapi_decode_init(AVCodecContext *avctx)
Definition: vaapi_decode.c:628
AVBufferRef * device_ref
Definition: vaapi_decode.h:63
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames...
Definition: avcodec.h:2226
#define FF_PROFILE_UNKNOWN
Definition: avcodec.h:1860
AVFormatContext * ctx
Definition: movenc.c:48
VABufferID * slice_buffers
Definition: vaapi_decode.h:51
enum AVCodecID codec_id
Definition: vaapi_decode.c:369
struct vaapi_context * old_context
Definition: vaapi_decode.h:62
#define FF_ARRAY_ELEMS(a)
VABufferID param_buffers[MAX_PARAM_BUFFERS]
Definition: vaapi_decode.h:48
if(ret)
VAProfile ff_vaapi_parse_hevc_rext_profile(AVCodecContext *avctx)
Definition: vaapi_hevc.c:526
VADisplay display
The VADisplay handle, to be filled by the user.
VASurfaceID output_surface
Definition: vaapi_decode.h:45
void * display
Window system dependent data.
Definition: vaapi.h:63
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:471
AVBufferRef * av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
Allocate an AVHWDeviceContext for a given hardware type.
Definition: hwcontext.c:142
Libavcodec external API header.
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:453
enum AVCodecID codec_id
Definition: avcodec.h:536
main external API structure.
Definition: avcodec.h:526
AVHWFramesConstraints * av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, const void *hwconfig)
Get the constraints on HW frames given a device and the HW-specific configuration to be used with tha...
Definition: hwcontext.c:576
uint8_t * data
The data buffer.
Definition: buffer.h:89
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:162
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
int coded_height
Definition: avcodec.h:714
int index
Definition: gxfenc.c:89
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
const char * name
Name of the codec described by this descriptor.
Definition: codec_desc.h:46
int ff_vaapi_decode_cancel(AVCodecContext *avctx, VAAPIDecodePicture *pic)
Definition: vaapi_decode.c:225
This struct describes the properties of a single codec described by an AVCodecID. ...
Definition: codec_desc.h:38
VAContextID va_context
Definition: vaapi_decode.h:57
int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, enum AVHWDeviceType dev_type)
Make sure avctx.hw_frames_ctx is set.
Definition: decode.c:1143
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:141
A reference to a data buffer.
Definition: buffer.h:81
common internal api header.
common internal and external API header
void * hwaccel_priv_data
hwaccel-specific private data
Definition: internal.h:169
enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
Compute what kind of losses will occur when converting from one specific pixel format to another...
Definition: pixdesc.c:2862
VAConfigID va_config
Definition: vaapi_decode.h:56
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:561
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:465
#define H
Definition: pixlet.c:39
VAAPI connection details.
const AVCodecDescriptor * avcodec_descriptor_get(enum AVCodecID id)
Definition: codec_desc.c:3436
#define MAP(va, av)
VAConfigID config_id
ID of a VAAPI pipeline configuration.
static int vaapi_decode_make_config(AVCodecContext *avctx, AVBufferRef *device_ref, VAConfigID *va_config, AVBufferRef *frames_ref)
Definition: vaapi_decode.c:420
#define av_freep(p)
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH
Hardware acceleration should still be attempted for decoding when the codec profile does not match th...
Definition: avcodec.h:2606
int hwaccel_flags
Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated decoding (if active)...
Definition: avcodec.h:2287
#define av_malloc_array(a, b)
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2489
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
static const struct @156 vaapi_profile_map[]
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:222
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, VAAPIDecodePicture *pic, const void *params_data, size_t params_size, const void *slice_data, size_t slice_size)
Definition: vaapi_decode.c:59
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:2076
int i
Definition: input.c:407
GLuint buffer
Definition: opengl_enc.c:101
uint32_t config_id
Configuration ID.
Definition: vaapi.h:71
#define V
Definition: avdct.c:30