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
25
32
33
39 {
41 VAStatus vas;
42
51
54 }
56
57 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
60 if (vas != VA_STATUS_SUCCESS) {
62 "buffer (type %d): %d (%s).\n",
63 type, vas, vaErrorStr(vas));
65 }
66
69
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;
86
95
98 }
100
102
103 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
104 VASliceParameterBufferType,
105 params_size, nb_params, (void*)params_data,
107 if (vas != VA_STATUS_SUCCESS) {
109 "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
111 }
112
114 "is %#x.\n", pic->
nb_slices, params_size,
116
117 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
118 VASliceDataBufferType,
119 slice_size, 1, (void*)slice_data,
121 if (vas != VA_STATUS_SUCCESS) {
123 "data buffer (size %zu): %d (%s).\n",
124 slice_size, vas, vaErrorStr(vas));
125 vaDestroyBuffer(
ctx->hwctx->display,
128 }
129
133
135 return 0;
136 }
137
140 {
142 VAStatus vas;
144
146 vas = vaDestroyBuffer(
ctx->hwctx->display,
148 if (vas != VA_STATUS_SUCCESS) {
150 "parameter buffer %#x: %d (%s).\n",
152 }
153 }
154
156 vas = vaDestroyBuffer(
ctx->hwctx->display,
158 if (vas != VA_STATUS_SUCCESS) {
160 "slice buffer %#x: %d (%s).\n",
162 }
163 }
164 }
165
168 {
170 VAStatus vas;
171 int err;
172
176 }
177
180
181 vas = vaBeginPicture(
ctx->hwctx->display,
ctx->va_context,
183 if (vas != VA_STATUS_SUCCESS) {
185 "issue: %d (%s).\n", vas, vaErrorStr(vas));
187 goto fail_with_picture;
188 }
189
190 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
192 if (vas != VA_STATUS_SUCCESS) {
194 "parameters: %d (%s).\n", vas, vaErrorStr(vas));
196 goto fail_with_picture;
197 }
198
199 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
201 if (vas != VA_STATUS_SUCCESS) {
203 "%d (%s).\n", vas, vaErrorStr(vas));
205 goto fail_with_picture;
206 }
207
208 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
209 if (vas != VA_STATUS_SUCCESS) {
211 "issue: %d (%s).\n", vas, vaErrorStr(vas));
213 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
216 else
217 goto fail_at_end;
218 }
219
220 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
223
224 err = 0;
225 goto exit;
226
227 fail_with_picture:
228 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
229 if (vas != VA_STATUS_SUCCESS) {
231 "after error: %d (%s).\n", vas, vaErrorStr(vas));
232 }
235 fail_at_end:
236 exit:
243
244 return err;
245 }
246
249 {
251
258
259 return 0;
260 }
261
262 static const struct {
266 #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
267 // 4:0:0
269 // 4:2:0
273 #ifdef VA_FOURCC_I420
275 #endif
277 // 4:1:1
279 // 4:2:2
281 #ifdef VA_FOURCC_YV16
283 #endif
285 #ifdef VA_FOURCC_Y210
287 #endif
288 #ifdef VA_FOURCC_Y212
290 #endif
291 // 4:4:0
293 // 4:4:4
295 #ifdef VA_FOURCC_XYUV
297 #endif
298 #ifdef VA_FOURCC_Y410
300 #endif
301 #ifdef VA_FOURCC_Y412
303 #endif
304 // 4:2:0 10-bit
305 #ifdef VA_FOURCC_P010
307 #endif
308 #ifdef VA_FOURCC_P012
310 #endif
311 #ifdef VA_FOURCC_I010
312 MAP(I010, YUV420P10),
313 #endif
314 #undef MAP
315 };
316
319 VAConfigID config_id,
321 {
323 VAStatus vas;
324 VASurfaceAttrib *attr;
326 uint32_t best_fourcc,
fourcc;
328
331
332 vas = vaQuerySurfaceAttributes(hwctx->
display, config_id,
334 if (vas != VA_STATUS_SUCCESS) {
336 "%d (%s).\n", vas, vaErrorStr(vas));
338 }
339
341 if (!attr)
343
344 vas = vaQuerySurfaceAttributes(hwctx->
display, config_id,
345 attr, &nb_attr);
346 if (vas != VA_STATUS_SUCCESS) {
348 "%d (%s).\n", vas, vaErrorStr(vas));
351 }
352
354
355 for (
i = 0;
i < nb_attr;
i++) {
356 if (attr[
i].
type != VASurfaceAttribPixelFormat)
357 continue;
358
359 fourcc = attr[
i].value.value.i;
362 break;
363 }
367 continue;
368 }
372
374 source_format, 0,
NULL);
375 if (
format == best_format)
377 }
378
380
384 }
385
389
390 frames->sw_format = best_format;
394
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,
400 };
401
404 }
405
406 return 0;
407 }
408
409 static const struct {
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 ),
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,
425 H264High10 ),
426 MAP(H264, H264_HIGH_10, H264High10 ),
427 #endif
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,
436 HEVCMain ),
437 #endif
438 #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
439 MAP(HEVC, HEVC_REXT, None,
441 MAP(HEVC, HEVC_SCC, None,
443 #endif
444 MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT,
445 JPEGBaseline),
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 ),
455 #if VA_CHECK_VERSION(0, 38, 0)
456 MAP(VP9, VP9_0, VP9Profile0 ),
457 #endif
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 ),
462 #endif
463 #if VA_CHECK_VERSION(1, 8, 0)
464 MAP(AV1, AV1_MAIN, AV1Profile0),
465 MAP(AV1, AV1_HIGH, AV1Profile1),
466 #endif
467 #if VA_CHECK_VERSION(1, 22, 0)
468 MAP(H266, VVC_MAIN_10, VVCMain10),
469 #endif
470
471 #undef MAP
472 };
473
474 /*
475 * Set *va_config and the frames_ref fields from the current codec parameters
476 * in avctx.
477 */
480 VAConfigID *va_config,
482 {
485 VAStatus vas;
489 int profile_count, exact_match, matched_ff_profile,
codec_profile;
490
493
495 if (!codec_desc) {
498 }
499
500 profile_count = vaMaxNumProfiles(hwctx->display);
502 sizeof(VAProfile));
503 if (!profile_list) {
506 }
507
508 vas = vaQueryConfigProfiles(hwctx->display,
509 profile_list, &profile_count);
510 if (vas != VA_STATUS_SUCCESS) {
512 "%d (%s).\n", vas, vaErrorStr(vas));
515 }
516
517 matched_va_profile = VAProfileNone;
518 exact_match = 0;
519
521 int profile_match = 0;
523 continue;
526 profile_match = 1;
527
532
533 for (j = 0; j < profile_count; j++) {
535 exact_match = profile_match;
536 break;
537 }
538 }
539 if (j < profile_count) {
542 if (exact_match)
543 break;
544 }
545 }
547
548 if (matched_va_profile == VAProfileNone) {
550 "profile %d.\n", codec_desc->
name, avctx->
profile);
553 }
554 if (!exact_match) {
558 "supported for hardware decode.\n",
561 "incompatible profile %d instead.\n",
562 matched_ff_profile);
563 } else {
565 "supported for hardware decode.\n",
569 }
570 }
571
572 vas = vaCreateConfig(hwctx->display, matched_va_profile,
573 VAEntrypointVLD,
NULL, 0,
574 va_config);
575 if (vas != VA_STATUS_SUCCESS) {
577 "configuration: %d (%s).\n", vas, vaErrorStr(vas));
580 }
581
583 if (!hwconfig) {
586 }
588
589 constraints =
591 if (!constraints) {
594 }
595
601 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
607 }
611 "usable surface formats.\n");
614 }
615
616 if (frames_ref) {
618
622
625 if (err < 0)
627
628 if (CONFIG_VAAPI_1)
629 frames->initial_pool_size = 0;
630 else {
631 frames->initial_pool_size = 1;
632 // Add per-codec number of surfaces used for storing reference frames.
638 frames->initial_pool_size += 16;
639 break;
641 frames->initial_pool_size += 8;
642 break;
644 frames->initial_pool_size += 3;
645 break;
646 default:
647 frames->initial_pool_size += 2;
648 }
649 }
650 }
651
654
655 return 0;
656
660 if (*va_config != VA_INVALID_ID) {
661 vaDestroyConfig(hwctx->display, *va_config);
662 *va_config = VA_INVALID_ID;
663 }
665 return err;
666 }
667
670 {
674 VAConfigID va_config = VA_INVALID_ID;
675 int err;
676
679 hwctx = device_ctx->hwctx;
680
682 hw_frames_ctx);
683 if (err)
684 return err;
685
686 if (va_config != VA_INVALID_ID)
687 vaDestroyConfig(hwctx->display, va_config);
688
689 return 0;
690 }
691
693 {
695 VAStatus vas;
696 int err;
697
698 ctx->va_config = VA_INVALID_ID;
699 ctx->va_context = VA_INVALID_ID;
700
702 if (err < 0)
704
706 ctx->hwfc =
ctx->frames->hwctx;
707 ctx->device =
ctx->frames->device_ctx;
708 ctx->hwctx =
ctx->device->hwctx;
709
712 if (err)
714
715 vas = vaCreateContext(
ctx->hwctx->display,
ctx->va_config,
717 VA_PROGRESSIVE,
718 ctx->hwfc->surface_ids,
719 ctx->hwfc->nb_surfaces,
721 if (vas != VA_STATUS_SUCCESS) {
723 "context: %d (%s).\n", vas, vaErrorStr(vas));
726 }
727
729 "%#x/%#x.\n",
ctx->va_config,
ctx->va_context);
730
731 return 0;
732
735 return err;
736 }
737
739 {
741 VAStatus vas;
742
743 if (
ctx->va_context != VA_INVALID_ID) {
744 vas = vaDestroyContext(
ctx->hwctx->display,
ctx->va_context);
745 if (vas != VA_STATUS_SUCCESS) {
747 "context %#x: %d (%s).\n",
748 ctx->va_context, vas, vaErrorStr(vas));
749 }
750 }
751 if (
ctx->va_config != VA_INVALID_ID) {
752 vas = vaDestroyConfig(
ctx->hwctx->display,
ctx->va_config);
753 if (vas != VA_STATUS_SUCCESS) {
755 "configuration %#x: %d (%s).\n",
756 ctx->va_config, vas, vaErrorStr(vas));
757 }
758 }
759
760 return 0;
761 }