FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vaapi_decode.c
Date: 2024-07-16 12:46:59
Exec Total Coverage
Lines: 0 304 0.0%
Functions: 0 10 0.0%
Branches: 0 138 0.0%

Line Branch Exec Source
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
34 int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx,
35 VAAPIDecodePicture *pic,
36 int type,
37 const void *data,
38 size_t size)
39 {
40 VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
41 VAStatus vas;
42 VABufferID buffer;
43
44 av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS);
45
46 vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
47 type, size, 1, (void*)data, &buffer);
48 if (vas != VA_STATUS_SUCCESS) {
49 av_log(avctx, AV_LOG_ERROR, "Failed to create parameter "
50 "buffer (type %d): %d (%s).\n",
51 type, vas, vaErrorStr(vas));
52 return AVERROR(EIO);
53 }
54
55 pic->param_buffers[pic->nb_param_buffers++] = buffer;
56
57 av_log(avctx, AV_LOG_DEBUG, "Param buffer (type %d, %zu bytes) "
58 "is %#x.\n", type, size, buffer);
59 return 0;
60 }
61
62
63 int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx,
64 VAAPIDecodePicture *pic,
65 const void *params_data,
66 int nb_params,
67 size_t params_size,
68 const void *slice_data,
69 size_t slice_size)
70 {
71 VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
72 VAStatus vas;
73 int index;
74
75 av_assert0(pic->nb_slices <= pic->slices_allocated);
76 if (pic->nb_slices == pic->slices_allocated) {
77 VABufferID *tmp =
78 av_realloc_array(pic->slice_buffers,
79 pic->slices_allocated ? pic->slices_allocated * 2 : 64,
80 2 * sizeof(*pic->slice_buffers));
81 if (!tmp)
82 return AVERROR(ENOMEM);
83
84 pic->slice_buffers = tmp;
85 pic->slices_allocated = pic->slices_allocated ? pic->slices_allocated * 2 : 64;
86 }
87 av_assert0(pic->nb_slices + 1 <= pic->slices_allocated);
88
89 index = 2 * pic->nb_slices;
90
91 vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
92 VASliceParameterBufferType,
93 params_size, nb_params, (void*)params_data,
94 &pic->slice_buffers[index]);
95 if (vas != VA_STATUS_SUCCESS) {
96 av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
97 "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
98 return AVERROR(EIO);
99 }
100
101 av_log(avctx, AV_LOG_DEBUG, "Slice %d param buffer (%zu bytes) "
102 "is %#x.\n", pic->nb_slices, params_size,
103 pic->slice_buffers[index]);
104
105 vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
106 VASliceDataBufferType,
107 slice_size, 1, (void*)slice_data,
108 &pic->slice_buffers[index + 1]);
109 if (vas != VA_STATUS_SUCCESS) {
110 av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
111 "data buffer (size %zu): %d (%s).\n",
112 slice_size, vas, vaErrorStr(vas));
113 vaDestroyBuffer(ctx->hwctx->display,
114 pic->slice_buffers[index]);
115 return AVERROR(EIO);
116 }
117
118 av_log(avctx, AV_LOG_DEBUG, "Slice %d data buffer (%zu bytes) "
119 "is %#x.\n", pic->nb_slices, slice_size,
120 pic->slice_buffers[index + 1]);
121
122 ++pic->nb_slices;
123 return 0;
124 }
125
126 static void ff_vaapi_decode_destroy_buffers(AVCodecContext *avctx,
127 VAAPIDecodePicture *pic)
128 {
129 VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
130 VAStatus vas;
131 int i;
132
133 for (i = 0; i < pic->nb_param_buffers; i++) {
134 vas = vaDestroyBuffer(ctx->hwctx->display,
135 pic->param_buffers[i]);
136 if (vas != VA_STATUS_SUCCESS) {
137 av_log(avctx, AV_LOG_ERROR, "Failed to destroy "
138 "parameter buffer %#x: %d (%s).\n",
139 pic->param_buffers[i], vas, vaErrorStr(vas));
140 }
141 }
142
143 for (i = 0; i < 2 * pic->nb_slices; i++) {
144 vas = vaDestroyBuffer(ctx->hwctx->display,
145 pic->slice_buffers[i]);
146 if (vas != VA_STATUS_SUCCESS) {
147 av_log(avctx, AV_LOG_ERROR, "Failed to destroy slice "
148 "slice buffer %#x: %d (%s).\n",
149 pic->slice_buffers[i], vas, vaErrorStr(vas));
150 }
151 }
152 }
153
154 int ff_vaapi_decode_issue(AVCodecContext *avctx,
155 VAAPIDecodePicture *pic)
156 {
157 VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
158 VAStatus vas;
159 int err;
160
161 if (pic->nb_slices <= 0) {
162 err = AVERROR(EINVAL);
163 goto fail;
164 }
165
166 av_log(avctx, AV_LOG_DEBUG, "Decode to surface %#x.\n",
167 pic->output_surface);
168
169 vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
170 pic->output_surface);
171 if (vas != VA_STATUS_SUCCESS) {
172 av_log(avctx, AV_LOG_ERROR, "Failed to begin picture decode "
173 "issue: %d (%s).\n", vas, vaErrorStr(vas));
174 err = AVERROR(EIO);
175 goto fail_with_picture;
176 }
177
178 vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
179 pic->param_buffers, pic->nb_param_buffers);
180 if (vas != VA_STATUS_SUCCESS) {
181 av_log(avctx, AV_LOG_ERROR, "Failed to upload decode "
182 "parameters: %d (%s).\n", vas, vaErrorStr(vas));
183 err = AVERROR(EIO);
184 goto fail_with_picture;
185 }
186
187 vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
188 pic->slice_buffers, 2 * pic->nb_slices);
189 if (vas != VA_STATUS_SUCCESS) {
190 av_log(avctx, AV_LOG_ERROR, "Failed to upload slices: "
191 "%d (%s).\n", vas, vaErrorStr(vas));
192 err = AVERROR(EIO);
193 goto fail_with_picture;
194 }
195
196 vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
197 if (vas != VA_STATUS_SUCCESS) {
198 av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
199 "issue: %d (%s).\n", vas, vaErrorStr(vas));
200 err = AVERROR(EIO);
201 if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
202 AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS)
203 goto fail;
204 else
205 goto fail_at_end;
206 }
207
208 if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
209 AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS)
210 ff_vaapi_decode_destroy_buffers(avctx, pic);
211
212 err = 0;
213 goto exit;
214
215 fail_with_picture:
216 vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
217 if (vas != VA_STATUS_SUCCESS) {
218 av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
219 "after error: %d (%s).\n", vas, vaErrorStr(vas));
220 }
221 fail:
222 ff_vaapi_decode_destroy_buffers(avctx, pic);
223 fail_at_end:
224 exit:
225 pic->nb_param_buffers = 0;
226 pic->nb_slices = 0;
227 pic->slices_allocated = 0;
228 av_freep(&pic->slice_buffers);
229
230 return err;
231 }
232
233 int ff_vaapi_decode_cancel(AVCodecContext *avctx,
234 VAAPIDecodePicture *pic)
235 {
236 ff_vaapi_decode_destroy_buffers(avctx, pic);
237
238 pic->nb_param_buffers = 0;
239 pic->nb_slices = 0;
240 pic->slices_allocated = 0;
241 av_freep(&pic->slice_buffers);
242
243 return 0;
244 }
245
246 static const struct {
247 uint32_t fourcc;
248 enum AVPixelFormat pix_fmt;
249 } vaapi_format_map[] = {
250 #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
251 // 4:0:0
252 MAP(Y800, GRAY8),
253 // 4:2:0
254 MAP(NV12, NV12),
255 MAP(YV12, YUV420P),
256 MAP(IYUV, YUV420P),
257 #ifdef VA_FOURCC_I420
258 MAP(I420, YUV420P),
259 #endif
260 MAP(IMC3, YUV420P),
261 // 4:1:1
262 MAP(411P, YUV411P),
263 // 4:2:2
264 MAP(422H, YUV422P),
265 #ifdef VA_FOURCC_YV16
266 MAP(YV16, YUV422P),
267 #endif
268 MAP(YUY2, YUYV422),
269 #ifdef VA_FOURCC_Y210
270 MAP(Y210, Y210),
271 #endif
272 #ifdef VA_FOURCC_Y212
273 MAP(Y212, Y212),
274 #endif
275 // 4:4:0
276 MAP(422V, YUV440P),
277 // 4:4:4
278 MAP(444P, YUV444P),
279 #ifdef VA_FOURCC_XYUV
280 MAP(XYUV, VUYX),
281 #endif
282 #ifdef VA_FOURCC_Y410
283 MAP(Y410, XV30),
284 #endif
285 #ifdef VA_FOURCC_Y412
286 MAP(Y412, XV36),
287 #endif
288 // 4:2:0 10-bit
289 #ifdef VA_FOURCC_P010
290 MAP(P010, P010),
291 #endif
292 #ifdef VA_FOURCC_P012
293 MAP(P012, P012),
294 #endif
295 #ifdef VA_FOURCC_I010
296 MAP(I010, YUV420P10),
297 #endif
298 #undef MAP
299 };
300
301 static int vaapi_decode_find_best_format(AVCodecContext *avctx,
302 AVHWDeviceContext *device,
303 VAConfigID config_id,
304 AVHWFramesContext *frames)
305 {
306 AVVAAPIDeviceContext *hwctx = device->hwctx;
307 VAStatus vas;
308 VASurfaceAttrib *attr;
309 enum AVPixelFormat source_format, best_format, format;
310 uint32_t best_fourcc, fourcc;
311 int i, j, nb_attr;
312
313 source_format = avctx->sw_pix_fmt;
314 av_assert0(source_format != AV_PIX_FMT_NONE);
315
316 vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
317 NULL, &nb_attr);
318 if (vas != VA_STATUS_SUCCESS) {
319 av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
320 "%d (%s).\n", vas, vaErrorStr(vas));
321 return AVERROR(ENOSYS);
322 }
323
324 attr = av_malloc_array(nb_attr, sizeof(*attr));
325 if (!attr)
326 return AVERROR(ENOMEM);
327
328 vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
329 attr, &nb_attr);
330 if (vas != VA_STATUS_SUCCESS) {
331 av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
332 "%d (%s).\n", vas, vaErrorStr(vas));
333 av_freep(&attr);
334 return AVERROR(ENOSYS);
335 }
336
337 best_format = AV_PIX_FMT_NONE;
338
339 for (i = 0; i < nb_attr; i++) {
340 if (attr[i].type != VASurfaceAttribPixelFormat)
341 continue;
342
343 fourcc = attr[i].value.value.i;
344 for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map); j++) {
345 if (fourcc == vaapi_format_map[j].fourcc)
346 break;
347 }
348 if (j >= FF_ARRAY_ELEMS(vaapi_format_map)) {
349 av_log(avctx, AV_LOG_DEBUG, "Ignoring unknown format %#x.\n",
350 fourcc);
351 continue;
352 }
353 format = vaapi_format_map[j].pix_fmt;
354 av_log(avctx, AV_LOG_DEBUG, "Considering format %#x -> %s.\n",
355 fourcc, av_get_pix_fmt_name(format));
356
357 best_format = av_find_best_pix_fmt_of_2(format, best_format,
358 source_format, 0, NULL);
359 if (format == best_format)
360 best_fourcc = fourcc;
361 }
362
363 av_freep(&attr);
364
365 if (best_format == AV_PIX_FMT_NONE) {
366 av_log(avctx, AV_LOG_ERROR, "No usable formats for decoding!\n");
367 return AVERROR(EINVAL);
368 }
369
370 av_log(avctx, AV_LOG_DEBUG, "Picked %s (%#x) as best match for %s.\n",
371 av_get_pix_fmt_name(best_format), best_fourcc,
372 av_get_pix_fmt_name(source_format));
373
374 frames->sw_format = best_format;
375 if (avctx->internal->hwaccel_priv_data) {
376 VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
377 AVVAAPIFramesContext *avfc = frames->hwctx;
378
379 ctx->pixel_format_attribute = (VASurfaceAttrib) {
380 .type = VASurfaceAttribPixelFormat,
381 .flags = VA_SURFACE_ATTRIB_SETTABLE,
382 .value.type = VAGenericValueTypeInteger,
383 .value.value.i = best_fourcc,
384 };
385
386 avfc->attributes = &ctx->pixel_format_attribute;
387 avfc->nb_attributes = 1;
388 }
389
390 return 0;
391 }
392
393 static const struct {
394 enum AVCodecID codec_id;
395 int codec_profile;
396 VAProfile va_profile;
397 VAProfile (*profile_parser)(AVCodecContext *avctx);
398 } vaapi_profile_map[] = {
399 #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, AV_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ }
400 MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ),
401 MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ),
402 MAP(H263, UNKNOWN, H263Baseline),
403 MAP(MPEG4, MPEG4_SIMPLE, MPEG4Simple ),
404 MAP(MPEG4, MPEG4_ADVANCED_SIMPLE,
405 MPEG4AdvancedSimple),
406 MAP(MPEG4, MPEG4_MAIN, MPEG4Main ),
407 #if VA_CHECK_VERSION(1, 18, 0)
408 MAP(H264, H264_HIGH_10_INTRA,
409 H264High10 ),
410 MAP(H264, H264_HIGH_10, H264High10 ),
411 #endif
412 MAP(H264, H264_CONSTRAINED_BASELINE,
413 H264ConstrainedBaseline),
414 MAP(H264, H264_MAIN, H264Main ),
415 MAP(H264, H264_HIGH, H264High ),
416 #if VA_CHECK_VERSION(0, 37, 0)
417 MAP(HEVC, HEVC_MAIN, HEVCMain ),
418 MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ),
419 MAP(HEVC, HEVC_MAIN_STILL_PICTURE,
420 HEVCMain ),
421 #endif
422 #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
423 MAP(HEVC, HEVC_REXT, None,
424 ff_vaapi_parse_hevc_rext_scc_profile ),
425 MAP(HEVC, HEVC_SCC, None,
426 ff_vaapi_parse_hevc_rext_scc_profile ),
427 #endif
428 MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT,
429 JPEGBaseline),
430 MAP(WMV3, VC1_SIMPLE, VC1Simple ),
431 MAP(WMV3, VC1_MAIN, VC1Main ),
432 MAP(WMV3, VC1_COMPLEX, VC1Advanced ),
433 MAP(WMV3, VC1_ADVANCED, VC1Advanced ),
434 MAP(VC1, VC1_SIMPLE, VC1Simple ),
435 MAP(VC1, VC1_MAIN, VC1Main ),
436 MAP(VC1, VC1_COMPLEX, VC1Advanced ),
437 MAP(VC1, VC1_ADVANCED, VC1Advanced ),
438 MAP(VP8, UNKNOWN, VP8Version0_3 ),
439 #if VA_CHECK_VERSION(0, 38, 0)
440 MAP(VP9, VP9_0, VP9Profile0 ),
441 #endif
442 #if VA_CHECK_VERSION(0, 39, 0)
443 MAP(VP9, VP9_1, VP9Profile1 ),
444 MAP(VP9, VP9_2, VP9Profile2 ),
445 MAP(VP9, VP9_3, VP9Profile3 ),
446 #endif
447 #if VA_CHECK_VERSION(1, 8, 0)
448 MAP(AV1, AV1_MAIN, AV1Profile0),
449 MAP(AV1, AV1_HIGH, AV1Profile1),
450 #endif
451
452 #undef MAP
453 };
454
455 /*
456 * Set *va_config and the frames_ref fields from the current codec parameters
457 * in avctx.
458 */
459 static int vaapi_decode_make_config(AVCodecContext *avctx,
460 AVBufferRef *device_ref,
461 VAConfigID *va_config,
462 AVBufferRef *frames_ref)
463 {
464 AVVAAPIHWConfig *hwconfig = NULL;
465 AVHWFramesConstraints *constraints = NULL;
466 VAStatus vas;
467 int err, i, j;
468 const AVCodecDescriptor *codec_desc;
469 VAProfile *profile_list = NULL, matched_va_profile, va_profile;
470 int profile_count, exact_match, matched_ff_profile, codec_profile;
471
472 AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data;
473 AVVAAPIDeviceContext *hwctx = device->hwctx;
474
475 codec_desc = avcodec_descriptor_get(avctx->codec_id);
476 if (!codec_desc) {
477 err = AVERROR(EINVAL);
478 goto fail;
479 }
480
481 profile_count = vaMaxNumProfiles(hwctx->display);
482 profile_list = av_malloc_array(profile_count,
483 sizeof(VAProfile));
484 if (!profile_list) {
485 err = AVERROR(ENOMEM);
486 goto fail;
487 }
488
489 vas = vaQueryConfigProfiles(hwctx->display,
490 profile_list, &profile_count);
491 if (vas != VA_STATUS_SUCCESS) {
492 av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: "
493 "%d (%s).\n", vas, vaErrorStr(vas));
494 err = AVERROR(ENOSYS);
495 goto fail;
496 }
497
498 matched_va_profile = VAProfileNone;
499 exact_match = 0;
500
501 for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) {
502 int profile_match = 0;
503 if (avctx->codec_id != vaapi_profile_map[i].codec_id)
504 continue;
505 if (avctx->profile == vaapi_profile_map[i].codec_profile ||
506 vaapi_profile_map[i].codec_profile == AV_PROFILE_UNKNOWN)
507 profile_match = 1;
508
509 va_profile = vaapi_profile_map[i].profile_parser ?
510 vaapi_profile_map[i].profile_parser(avctx) :
511 vaapi_profile_map[i].va_profile;
512 codec_profile = vaapi_profile_map[i].codec_profile;
513
514 for (j = 0; j < profile_count; j++) {
515 if (va_profile == profile_list[j]) {
516 exact_match = profile_match;
517 break;
518 }
519 }
520 if (j < profile_count) {
521 matched_va_profile = va_profile;
522 matched_ff_profile = codec_profile;
523 if (exact_match)
524 break;
525 }
526 }
527 av_freep(&profile_list);
528
529 if (matched_va_profile == VAProfileNone) {
530 av_log(avctx, AV_LOG_ERROR, "No support for codec %s "
531 "profile %d.\n", codec_desc->name, avctx->profile);
532 err = AVERROR(ENOSYS);
533 goto fail;
534 }
535 if (!exact_match) {
536 if (avctx->hwaccel_flags &
537 AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) {
538 av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
539 "supported for hardware decode.\n",
540 codec_desc->name, avctx->profile);
541 av_log(avctx, AV_LOG_WARNING, "Using possibly-"
542 "incompatible profile %d instead.\n",
543 matched_ff_profile);
544 } else {
545 av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
546 "supported for hardware decode.\n",
547 codec_desc->name, avctx->profile);
548 err = AVERROR(EINVAL);
549 goto fail;
550 }
551 }
552
553 vas = vaCreateConfig(hwctx->display, matched_va_profile,
554 VAEntrypointVLD, NULL, 0,
555 va_config);
556 if (vas != VA_STATUS_SUCCESS) {
557 av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
558 "configuration: %d (%s).\n", vas, vaErrorStr(vas));
559 err = AVERROR(EIO);
560 goto fail;
561 }
562
563 hwconfig = av_hwdevice_hwconfig_alloc(device_ref);
564 if (!hwconfig) {
565 err = AVERROR(ENOMEM);
566 goto fail;
567 }
568 hwconfig->config_id = *va_config;
569
570 constraints =
571 av_hwdevice_get_hwframe_constraints(device_ref, hwconfig);
572 if (!constraints) {
573 err = AVERROR(ENOMEM);
574 goto fail;
575 }
576
577 if (avctx->coded_width < constraints->min_width ||
578 avctx->coded_height < constraints->min_height ||
579 avctx->coded_width > constraints->max_width ||
580 avctx->coded_height > constraints->max_height) {
581 av_log(avctx, AV_LOG_ERROR, "Hardware does not support image "
582 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
583 avctx->coded_width, avctx->coded_height,
584 constraints->min_width, constraints->max_width,
585 constraints->min_height, constraints->max_height);
586 err = AVERROR(EINVAL);
587 goto fail;
588 }
589 if (!constraints->valid_sw_formats ||
590 constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) {
591 av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any "
592 "usable surface formats.\n");
593 err = AVERROR(EINVAL);
594 goto fail;
595 }
596
597 if (frames_ref) {
598 AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
599
600 frames->format = AV_PIX_FMT_VAAPI;
601 frames->width = avctx->coded_width;
602 frames->height = avctx->coded_height;
603
604 err = vaapi_decode_find_best_format(avctx, device,
605 *va_config, frames);
606 if (err < 0)
607 goto fail;
608
609 if (CONFIG_VAAPI_1)
610 frames->initial_pool_size = 0;
611 else {
612 frames->initial_pool_size = 1;
613 // Add per-codec number of surfaces used for storing reference frames.
614 switch (avctx->codec_id) {
615 case AV_CODEC_ID_H264:
616 case AV_CODEC_ID_HEVC:
617 case AV_CODEC_ID_AV1:
618 frames->initial_pool_size += 16;
619 break;
620 case AV_CODEC_ID_VP9:
621 frames->initial_pool_size += 8;
622 break;
623 case AV_CODEC_ID_VP8:
624 frames->initial_pool_size += 3;
625 break;
626 default:
627 frames->initial_pool_size += 2;
628 }
629 }
630 }
631
632 av_hwframe_constraints_free(&constraints);
633 av_freep(&hwconfig);
634
635 return 0;
636
637 fail:
638 av_hwframe_constraints_free(&constraints);
639 av_freep(&hwconfig);
640 if (*va_config != VA_INVALID_ID) {
641 vaDestroyConfig(hwctx->display, *va_config);
642 *va_config = VA_INVALID_ID;
643 }
644 av_freep(&profile_list);
645 return err;
646 }
647
648 int ff_vaapi_common_frame_params(AVCodecContext *avctx,
649 AVBufferRef *hw_frames_ctx)
650 {
651 AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data;
652 AVHWDeviceContext *device_ctx = hw_frames->device_ctx;
653 AVVAAPIDeviceContext *hwctx;
654 VAConfigID va_config = VA_INVALID_ID;
655 int err;
656
657 if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI)
658 return AVERROR(EINVAL);
659 hwctx = device_ctx->hwctx;
660
661 err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config,
662 hw_frames_ctx);
663 if (err)
664 return err;
665
666 if (va_config != VA_INVALID_ID)
667 vaDestroyConfig(hwctx->display, va_config);
668
669 return 0;
670 }
671
672 int ff_vaapi_decode_init(AVCodecContext *avctx)
673 {
674 VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
675 VAStatus vas;
676 int err;
677
678 ctx->va_config = VA_INVALID_ID;
679 ctx->va_context = VA_INVALID_ID;
680
681 err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI);
682 if (err < 0)
683 goto fail;
684
685 ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
686 ctx->hwfc = ctx->frames->hwctx;
687 ctx->device = ctx->frames->device_ctx;
688 ctx->hwctx = ctx->device->hwctx;
689
690 err = vaapi_decode_make_config(avctx, ctx->frames->device_ref,
691 &ctx->va_config, NULL);
692 if (err)
693 goto fail;
694
695 vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
696 avctx->coded_width, avctx->coded_height,
697 VA_PROGRESSIVE,
698 ctx->hwfc->surface_ids,
699 ctx->hwfc->nb_surfaces,
700 &ctx->va_context);
701 if (vas != VA_STATUS_SUCCESS) {
702 av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
703 "context: %d (%s).\n", vas, vaErrorStr(vas));
704 err = AVERROR(EIO);
705 goto fail;
706 }
707
708 av_log(avctx, AV_LOG_DEBUG, "Decode context initialised: "
709 "%#x/%#x.\n", ctx->va_config, ctx->va_context);
710
711 return 0;
712
713 fail:
714 ff_vaapi_decode_uninit(avctx);
715 return err;
716 }
717
718 int ff_vaapi_decode_uninit(AVCodecContext *avctx)
719 {
720 VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
721 VAStatus vas;
722
723 if (ctx->va_context != VA_INVALID_ID) {
724 vas = vaDestroyContext(ctx->hwctx->display, ctx->va_context);
725 if (vas != VA_STATUS_SUCCESS) {
726 av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
727 "context %#x: %d (%s).\n",
728 ctx->va_context, vas, vaErrorStr(vas));
729 }
730 }
731 if (ctx->va_config != VA_INVALID_ID) {
732 vas = vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
733 if (vas != VA_STATUS_SUCCESS) {
734 av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
735 "configuration %#x: %d (%s).\n",
736 ctx->va_config, vas, vaErrorStr(vas));
737 }
738 }
739
740 return 0;
741 }
742