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