2 * This file is part of FFmpeg.
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.
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.
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
19 #include "config_components.h"
21 #include "libavutil/avassert.h"
22 #include "libavutil/common.h"
23 #include "libavutil/mem.h"
24 #include "libavutil/pixdesc.h"
27 #include "codec_desc.h"
30 #include "vaapi_decode.h"
31 #include "vaapi_hevc.h"
34 int ff_vaapi_decode_make_param_buffer(AVCodecContext
*avctx
,
35 VAAPIDecodePicture
*pic
,
40 VAAPIDecodeContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
43 av_assert0(pic
->nb_param_buffers
<= pic
->nb_param_buffers_allocated
);
44 if (pic
->nb_param_buffers
== pic
->nb_param_buffers_allocated
) {
46 av_realloc_array(pic
->param_buffers
,
47 pic
->nb_param_buffers_allocated
+ 16,
48 sizeof(*pic
->param_buffers
));
50 return AVERROR(ENOMEM
);
52 pic
->param_buffers
= tmp
;
53 pic
->nb_param_buffers_allocated
+= 16;
55 av_assert0(pic
->nb_param_buffers
+ 1 <= pic
->nb_param_buffers_allocated
);
57 vas
= vaCreateBuffer(ctx
->hwctx
->display
, ctx
->va_context
,
58 type
, size
, 1, (void*)data
,
59 &pic
->param_buffers
[pic
->nb_param_buffers
]);
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
));
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
]);
70 ++pic
->nb_param_buffers
;
75 int ff_vaapi_decode_make_slice_buffer(AVCodecContext
*avctx
,
76 VAAPIDecodePicture
*pic
,
77 const void *params_data
,
80 const void *slice_data
,
83 VAAPIDecodeContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
87 av_assert0(pic
->nb_slices
<= pic
->nb_slice_buffers_allocated
);
88 if (pic
->nb_slices
== pic
->nb_slice_buffers_allocated
) {
90 av_realloc_array(pic
->slice_buffers
,
91 pic
->nb_slice_buffers_allocated
? pic
->nb_slice_buffers_allocated
* 2 : 64,
92 2 * sizeof(*pic
->slice_buffers
));
94 return AVERROR(ENOMEM
);
96 pic
->slice_buffers
= tmp
;
97 pic
->nb_slice_buffers_allocated
= pic
->nb_slice_buffers_allocated
? pic
->nb_slice_buffers_allocated
* 2 : 64;
99 av_assert0(pic
->nb_slices
+ 1 <= pic
->nb_slice_buffers_allocated
);
101 index
= 2 * pic
->nb_slices
;
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
));
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
]);
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
]);
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]);
138 static void ff_vaapi_decode_destroy_buffers(AVCodecContext
*avctx
,
139 VAAPIDecodePicture
*pic
)
141 VAAPIDecodeContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
145 for (i
= 0; i
< pic
->nb_param_buffers
; i
++) {
146 vas
= vaDestroyBuffer(ctx
->hwctx
->display
,
147 pic
->param_buffers
[i
]);
148 if (vas
!= VA_STATUS_SUCCESS
) {
149 av_log(avctx
, AV_LOG_ERROR
, "Failed to destroy "
150 "parameter buffer %#x: %d (%s).\n",
151 pic
->param_buffers
[i
], vas
, vaErrorStr(vas
));
155 for (i
= 0; i
< 2 * pic
->nb_slices
; i
++) {
156 vas
= vaDestroyBuffer(ctx
->hwctx
->display
,
157 pic
->slice_buffers
[i
]);
158 if (vas
!= VA_STATUS_SUCCESS
) {
159 av_log(avctx
, AV_LOG_ERROR
, "Failed to destroy slice "
160 "slice buffer %#x: %d (%s).\n",
161 pic
->slice_buffers
[i
], vas
, vaErrorStr(vas
));
166 int ff_vaapi_decode_issue(AVCodecContext
*avctx
,
167 VAAPIDecodePicture
*pic
)
169 VAAPIDecodeContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
173 if (pic
->nb_slices
<= 0) {
174 err
= AVERROR(EINVAL
);
178 av_log(avctx
, AV_LOG_DEBUG
, "Decode to surface %#x.\n",
179 pic
->output_surface
);
181 vas
= vaBeginPicture(ctx
->hwctx
->display
, ctx
->va_context
,
182 pic
->output_surface
);
183 if (vas
!= VA_STATUS_SUCCESS
) {
184 av_log(avctx
, AV_LOG_ERROR
, "Failed to begin picture decode "
185 "issue: %d (%s).\n", vas
, vaErrorStr(vas
));
187 goto fail_with_picture
;
190 vas
= vaRenderPicture(ctx
->hwctx
->display
, ctx
->va_context
,
191 pic
->param_buffers
, pic
->nb_param_buffers
);
192 if (vas
!= VA_STATUS_SUCCESS
) {
193 av_log(avctx
, AV_LOG_ERROR
, "Failed to upload decode "
194 "parameters: %d (%s).\n", vas
, vaErrorStr(vas
));
196 goto fail_with_picture
;
199 vas
= vaRenderPicture(ctx
->hwctx
->display
, ctx
->va_context
,
200 pic
->slice_buffers
, 2 * pic
->nb_slices
);
201 if (vas
!= VA_STATUS_SUCCESS
) {
202 av_log(avctx
, AV_LOG_ERROR
, "Failed to upload slices: "
203 "%d (%s).\n", vas
, vaErrorStr(vas
));
205 goto 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 "issue: %d (%s).\n", vas
, vaErrorStr(vas
));
213 if (CONFIG_VAAPI_1
|| ctx
->hwctx
->driver_quirks
&
214 AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS
)
220 if (CONFIG_VAAPI_1
|| ctx
->hwctx
->driver_quirks
&
221 AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS
)
222 ff_vaapi_decode_destroy_buffers(avctx
, pic
);
228 vas
= vaEndPicture(ctx
->hwctx
->display
, ctx
->va_context
);
229 if (vas
!= VA_STATUS_SUCCESS
) {
230 av_log(avctx
, AV_LOG_ERROR
, "Failed to end picture decode "
231 "after error: %d (%s).\n", vas
, vaErrorStr(vas
));
234 ff_vaapi_decode_destroy_buffers(avctx
, pic
);
237 pic
->nb_param_buffers
= 0;
238 pic
->nb_param_buffers_allocated
= 0;
239 av_freep(&pic
->param_buffers
);
241 pic
->nb_slice_buffers_allocated
= 0;
242 av_freep(&pic
->slice_buffers
);
247 int ff_vaapi_decode_cancel(AVCodecContext
*avctx
,
248 VAAPIDecodePicture
*pic
)
250 ff_vaapi_decode_destroy_buffers(avctx
, pic
);
252 pic
->nb_param_buffers
= 0;
253 pic
->nb_param_buffers_allocated
= 0;
254 av_freep(&pic
->param_buffers
);
256 pic
->nb_slice_buffers_allocated
= 0;
257 av_freep(&pic
->slice_buffers
);
262 static const struct {
264 enum AVPixelFormat pix_fmt
;
265 } vaapi_format_map
[] = {
266 #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
273 #ifdef VA_FOURCC_I420
281 #ifdef VA_FOURCC_YV16
285 #ifdef VA_FOURCC_Y210
288 #ifdef VA_FOURCC_Y212
295 #ifdef VA_FOURCC_XYUV
298 #ifdef VA_FOURCC_Y410
301 #ifdef VA_FOURCC_Y412
305 #ifdef VA_FOURCC_P010
308 #ifdef VA_FOURCC_P012
311 #ifdef VA_FOURCC_I010
312 MAP(I010
, YUV420P10
),
317 static int vaapi_decode_find_best_format(AVCodecContext
*avctx
,
318 AVHWDeviceContext
*device
,
319 VAConfigID config_id
,
320 AVHWFramesContext
*frames
)
322 AVVAAPIDeviceContext
*hwctx
= device
->hwctx
;
324 VASurfaceAttrib
*attr
;
325 enum AVPixelFormat source_format
, best_format
, format
;
326 uint32_t best_fourcc
, fourcc
;
329 source_format
= avctx
->sw_pix_fmt
;
330 av_assert0(source_format
!= AV_PIX_FMT_NONE
);
332 vas
= vaQuerySurfaceAttributes(hwctx
->display
, config_id
,
334 if (vas
!= VA_STATUS_SUCCESS
) {
335 av_log(avctx
, AV_LOG_ERROR
, "Failed to query surface attributes: "
336 "%d (%s).\n", vas
, vaErrorStr(vas
));
337 return AVERROR(ENOSYS
);
340 attr
= av_malloc_array(nb_attr
, sizeof(*attr
));
342 return AVERROR(ENOMEM
);
344 vas
= vaQuerySurfaceAttributes(hwctx
->display
, config_id
,
346 if (vas
!= VA_STATUS_SUCCESS
) {
347 av_log(avctx
, AV_LOG_ERROR
, "Failed to query surface attributes: "
348 "%d (%s).\n", vas
, vaErrorStr(vas
));
350 return AVERROR(ENOSYS
);
353 best_format
= AV_PIX_FMT_NONE
;
355 for (i
= 0; i
< nb_attr
; i
++) {
356 if (attr
[i
].type
!= VASurfaceAttribPixelFormat
)
359 fourcc
= attr
[i
].value
.value
.i
;
360 for (j
= 0; j
< FF_ARRAY_ELEMS(vaapi_format_map
); j
++) {
361 if (fourcc
== vaapi_format_map
[j
].fourcc
)
364 if (j
>= FF_ARRAY_ELEMS(vaapi_format_map
)) {
365 av_log(avctx
, AV_LOG_DEBUG
, "Ignoring unknown format %#x.\n",
369 format
= vaapi_format_map
[j
].pix_fmt
;
370 av_log(avctx
, AV_LOG_DEBUG
, "Considering format %#x -> %s.\n",
371 fourcc
, av_get_pix_fmt_name(format
));
373 best_format
= av_find_best_pix_fmt_of_2(format
, best_format
,
374 source_format
, 0, NULL
);
375 if (format
== best_format
)
376 best_fourcc
= fourcc
;
381 if (best_format
== AV_PIX_FMT_NONE
) {
382 av_log(avctx
, AV_LOG_ERROR
, "No usable formats for decoding!\n");
383 return AVERROR(EINVAL
);
386 av_log(avctx
, AV_LOG_DEBUG
, "Picked %s (%#x) as best match for %s.\n",
387 av_get_pix_fmt_name(best_format
), best_fourcc
,
388 av_get_pix_fmt_name(source_format
));
390 frames
->sw_format
= best_format
;
391 if (avctx
->internal
->hwaccel_priv_data
) {
392 VAAPIDecodeContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
393 AVVAAPIFramesContext
*avfc
= frames
->hwctx
;
395 ctx
->pixel_format_attribute
= (VASurfaceAttrib
) {
396 .type
= VASurfaceAttribPixelFormat
,
397 .flags
= VA_SURFACE_ATTRIB_SETTABLE
,
398 .value
.type
= VAGenericValueTypeInteger
,
399 .value
.value
.i
= best_fourcc
,
402 avfc
->attributes
= &ctx
->pixel_format_attribute
;
403 avfc
->nb_attributes
= 1;
409 static const struct {
410 enum AVCodecID codec_id
;
412 VAProfile va_profile
;
413 VAProfile (*profile_parser
)(AVCodecContext
*avctx
);
414 } vaapi_profile_map
[] = {
415 #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, AV_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ }
416 MAP(MPEG2VIDEO
, MPEG2_SIMPLE
, MPEG2Simple
),
417 MAP(MPEG2VIDEO
, MPEG2_MAIN
, MPEG2Main
),
418 MAP(H263
, UNKNOWN
, H263Baseline
),
419 MAP(MPEG4
, MPEG4_SIMPLE
, MPEG4Simple
),
420 MAP(MPEG4
, MPEG4_ADVANCED_SIMPLE
,
421 MPEG4AdvancedSimple
),
422 MAP(MPEG4
, MPEG4_MAIN
, MPEG4Main
),
423 #if VA_CHECK_VERSION(1, 18, 0)
424 MAP(H264
, H264_HIGH_10_INTRA
,
426 MAP(H264
, H264_HIGH_10
, H264High10
),
428 MAP(H264
, H264_CONSTRAINED_BASELINE
,
429 H264ConstrainedBaseline
),
430 MAP(H264
, H264_MAIN
, H264Main
),
431 MAP(H264
, H264_HIGH
, H264High
),
432 #if VA_CHECK_VERSION(0, 37, 0)
433 MAP(HEVC
, HEVC_MAIN
, HEVCMain
),
434 MAP(HEVC
, HEVC_MAIN_10
, HEVCMain10
),
435 MAP(HEVC
, HEVC_MAIN_STILL_PICTURE
,
438 #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
439 MAP(HEVC
, HEVC_REXT
, None
,
440 ff_vaapi_parse_hevc_rext_scc_profile
),
441 MAP(HEVC
, HEVC_SCC
, None
,
442 ff_vaapi_parse_hevc_rext_scc_profile
),
444 MAP(MJPEG
, MJPEG_HUFFMAN_BASELINE_DCT
,
446 MAP(WMV3
, VC1_SIMPLE
, VC1Simple
),
447 MAP(WMV3
, VC1_MAIN
, VC1Main
),
448 MAP(WMV3
, VC1_COMPLEX
, VC1Advanced
),
449 MAP(WMV3
, VC1_ADVANCED
, VC1Advanced
),
450 MAP(VC1
, VC1_SIMPLE
, VC1Simple
),
451 MAP(VC1
, VC1_MAIN
, VC1Main
),
452 MAP(VC1
, VC1_COMPLEX
, VC1Advanced
),
453 MAP(VC1
, VC1_ADVANCED
, VC1Advanced
),
454 MAP(VP8
, UNKNOWN
, VP8Version0_3
),
455 #if VA_CHECK_VERSION(0, 38, 0)
456 MAP(VP9
, VP9_0
, VP9Profile0
),
458 #if VA_CHECK_VERSION(0, 39, 0)
459 MAP(VP9
, VP9_1
, VP9Profile1
),
460 MAP(VP9
, VP9_2
, VP9Profile2
),
461 MAP(VP9
, VP9_3
, VP9Profile3
),
463 #if VA_CHECK_VERSION(1, 8, 0)
464 MAP(AV1
, AV1_MAIN
, AV1Profile0
),
465 MAP(AV1
, AV1_HIGH
, AV1Profile1
),
467 #if VA_CHECK_VERSION(1, 22, 0)
468 MAP(H266
, VVC_MAIN_10
, VVCMain10
),
475 * Set *va_config and the frames_ref fields from the current codec parameters
478 static int vaapi_decode_make_config(AVCodecContext
*avctx
,
479 AVBufferRef
*device_ref
,
480 VAConfigID
*va_config
,
481 AVBufferRef
*frames_ref
)
483 AVVAAPIHWConfig
*hwconfig
= NULL
;
484 AVHWFramesConstraints
*constraints
= NULL
;
487 const AVCodecDescriptor
*codec_desc
;
488 VAProfile
*profile_list
= NULL
, matched_va_profile
, va_profile
;
489 int profile_count
, exact_match
, matched_ff_profile
, codec_profile
;
491 AVHWDeviceContext
*device
= (AVHWDeviceContext
*)device_ref
->data
;
492 AVVAAPIDeviceContext
*hwctx
= device
->hwctx
;
494 codec_desc
= avcodec_descriptor_get(avctx
->codec_id
);
496 err
= AVERROR(EINVAL
);
500 profile_count
= vaMaxNumProfiles(hwctx
->display
);
501 profile_list
= av_malloc_array(profile_count
,
504 err
= AVERROR(ENOMEM
);
508 vas
= vaQueryConfigProfiles(hwctx
->display
,
509 profile_list
, &profile_count
);
510 if (vas
!= VA_STATUS_SUCCESS
) {
511 av_log(avctx
, AV_LOG_ERROR
, "Failed to query profiles: "
512 "%d (%s).\n", vas
, vaErrorStr(vas
));
513 err
= AVERROR(ENOSYS
);
517 matched_va_profile
= VAProfileNone
;
520 for (i
= 0; i
< FF_ARRAY_ELEMS(vaapi_profile_map
); i
++) {
521 int profile_match
= 0;
522 if (avctx
->codec_id
!= vaapi_profile_map
[i
].codec_id
)
524 if (avctx
->profile
== vaapi_profile_map
[i
].codec_profile
||
525 vaapi_profile_map
[i
].codec_profile
== AV_PROFILE_UNKNOWN
)
528 va_profile
= vaapi_profile_map
[i
].profile_parser
?
529 vaapi_profile_map
[i
].profile_parser(avctx
) :
530 vaapi_profile_map
[i
].va_profile
;
531 codec_profile
= vaapi_profile_map
[i
].codec_profile
;
533 for (j
= 0; j
< profile_count
; j
++) {
534 if (va_profile
== profile_list
[j
]) {
535 exact_match
= profile_match
;
539 if (j
< profile_count
) {
540 matched_va_profile
= va_profile
;
541 matched_ff_profile
= codec_profile
;
546 av_freep(&profile_list
);
548 if (matched_va_profile
== VAProfileNone
) {
549 av_log(avctx
, AV_LOG_ERROR
, "No support for codec %s "
550 "profile %d.\n", codec_desc
->name
, avctx
->profile
);
551 err
= AVERROR(ENOSYS
);
555 if (avctx
->hwaccel_flags
&
556 AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH
) {
557 av_log(avctx
, AV_LOG_VERBOSE
, "Codec %s profile %d not "
558 "supported for hardware decode.\n",
559 codec_desc
->name
, avctx
->profile
);
560 av_log(avctx
, AV_LOG_WARNING
, "Using possibly-"
561 "incompatible profile %d instead.\n",
564 av_log(avctx
, AV_LOG_VERBOSE
, "Codec %s profile %d not "
565 "supported for hardware decode.\n",
566 codec_desc
->name
, avctx
->profile
);
567 err
= AVERROR(EINVAL
);
572 vas
= vaCreateConfig(hwctx
->display
, matched_va_profile
,
573 VAEntrypointVLD
, NULL
, 0,
575 if (vas
!= VA_STATUS_SUCCESS
) {
576 av_log(avctx
, AV_LOG_ERROR
, "Failed to create decode "
577 "configuration: %d (%s).\n", vas
, vaErrorStr(vas
));
582 hwconfig
= av_hwdevice_hwconfig_alloc(device_ref
);
584 err
= AVERROR(ENOMEM
);
587 hwconfig
->config_id
= *va_config
;
590 av_hwdevice_get_hwframe_constraints(device_ref
, hwconfig
);
592 err
= AVERROR(ENOMEM
);
596 if (avctx
->coded_width
< constraints
->min_width
||
597 avctx
->coded_height
< constraints
->min_height
||
598 avctx
->coded_width
> constraints
->max_width
||
599 avctx
->coded_height
> constraints
->max_height
) {
600 av_log(avctx
, AV_LOG_ERROR
, "Hardware does not support image "
601 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
602 avctx
->coded_width
, avctx
->coded_height
,
603 constraints
->min_width
, constraints
->max_width
,
604 constraints
->min_height
, constraints
->max_height
);
605 err
= AVERROR(EINVAL
);
608 if (!constraints
->valid_sw_formats
||
609 constraints
->valid_sw_formats
[0] == AV_PIX_FMT_NONE
) {
610 av_log(avctx
, AV_LOG_ERROR
, "Hardware does not offer any "
611 "usable surface formats.\n");
612 err
= AVERROR(EINVAL
);
617 AVHWFramesContext
*frames
= (AVHWFramesContext
*)frames_ref
->data
;
619 frames
->format
= AV_PIX_FMT_VAAPI
;
620 frames
->width
= avctx
->coded_width
;
621 frames
->height
= avctx
->coded_height
;
623 err
= vaapi_decode_find_best_format(avctx
, device
,
629 frames
->initial_pool_size
= 0;
631 frames
->initial_pool_size
= 1;
632 // Add per-codec number of surfaces used for storing reference frames.
633 switch (avctx
->codec_id
) {
634 case AV_CODEC_ID_H264
:
635 case AV_CODEC_ID_H266
:
636 case AV_CODEC_ID_HEVC
:
637 case AV_CODEC_ID_AV1
:
638 frames
->initial_pool_size
+= 16;
640 case AV_CODEC_ID_VP9
:
641 frames
->initial_pool_size
+= 8;
643 case AV_CODEC_ID_VP8
:
644 frames
->initial_pool_size
+= 3;
647 frames
->initial_pool_size
+= 2;
652 av_hwframe_constraints_free(&constraints
);
658 av_hwframe_constraints_free(&constraints
);
660 if (*va_config
!= VA_INVALID_ID
) {
661 vaDestroyConfig(hwctx
->display
, *va_config
);
662 *va_config
= VA_INVALID_ID
;
664 av_freep(&profile_list
);
668 int ff_vaapi_common_frame_params(AVCodecContext
*avctx
,
669 AVBufferRef
*hw_frames_ctx
)
671 AVHWFramesContext
*hw_frames
= (AVHWFramesContext
*)hw_frames_ctx
->data
;
672 AVHWDeviceContext
*device_ctx
= hw_frames
->device_ctx
;
673 AVVAAPIDeviceContext
*hwctx
;
674 VAConfigID va_config
= VA_INVALID_ID
;
677 if (device_ctx
->type
!= AV_HWDEVICE_TYPE_VAAPI
)
678 return AVERROR(EINVAL
);
679 hwctx
= device_ctx
->hwctx
;
681 err
= vaapi_decode_make_config(avctx
, hw_frames
->device_ref
, &va_config
,
686 if (va_config
!= VA_INVALID_ID
)
687 vaDestroyConfig(hwctx
->display
, va_config
);
692 int ff_vaapi_decode_init(AVCodecContext
*avctx
)
694 VAAPIDecodeContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
698 ctx
->va_config
= VA_INVALID_ID
;
699 ctx
->va_context
= VA_INVALID_ID
;
701 err
= ff_decode_get_hw_frames_ctx(avctx
, AV_HWDEVICE_TYPE_VAAPI
);
705 ctx
->frames
= (AVHWFramesContext
*)avctx
->hw_frames_ctx
->data
;
706 ctx
->hwfc
= ctx
->frames
->hwctx
;
707 ctx
->device
= ctx
->frames
->device_ctx
;
708 ctx
->hwctx
= ctx
->device
->hwctx
;
710 err
= vaapi_decode_make_config(avctx
, ctx
->frames
->device_ref
,
711 &ctx
->va_config
, NULL
);
715 vas
= vaCreateContext(ctx
->hwctx
->display
, ctx
->va_config
,
716 avctx
->coded_width
, avctx
->coded_height
,
718 ctx
->hwfc
->surface_ids
,
719 ctx
->hwfc
->nb_surfaces
,
721 if (vas
!= VA_STATUS_SUCCESS
) {
722 av_log(avctx
, AV_LOG_ERROR
, "Failed to create decode "
723 "context: %d (%s).\n", vas
, vaErrorStr(vas
));
728 av_log(avctx
, AV_LOG_DEBUG
, "Decode context initialised: "
729 "%#x/%#x.\n", ctx
->va_config
, ctx
->va_context
);
734 ff_vaapi_decode_uninit(avctx
);
738 int ff_vaapi_decode_uninit(AVCodecContext
*avctx
)
740 VAAPIDecodeContext
*ctx
= avctx
->internal
->hwaccel_priv_data
;
743 if (ctx
->va_context
!= VA_INVALID_ID
) {
744 vas
= vaDestroyContext(ctx
->hwctx
->display
, ctx
->va_context
);
745 if (vas
!= VA_STATUS_SUCCESS
) {
746 av_log(avctx
, AV_LOG_ERROR
, "Failed to destroy decode "
747 "context %#x: %d (%s).\n",
748 ctx
->va_context
, vas
, vaErrorStr(vas
));
751 if (ctx
->va_config
!= VA_INVALID_ID
) {
752 vas
= vaDestroyConfig(ctx
->hwctx
->display
, ctx
->va_config
);
753 if (vas
!= VA_STATUS_SUCCESS
) {
754 av_log(avctx
, AV_LOG_ERROR
, "Failed to destroy decode "
755 "configuration %#x: %d (%s).\n",
756 ctx
->va_config
, vas
, vaErrorStr(vas
));