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
24
31
32
38 {
40 VAStatus vas;
42
44
45 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
47 if (vas != VA_STATUS_SUCCESS) {
49 "buffer (type %d): %d (%s).\n",
50 type, vas, vaErrorStr(vas));
52 }
53
55
58 return 0;
59 }
60
61
64 const void *params_data,
65 int nb_params,
66 size_t params_size,
67 const void *slice_data,
68 size_t slice_size)
69 {
71 VAStatus vas;
73
82
84 }
86
88
89 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
90 VASliceParameterBufferType,
91 params_size, nb_params, (void*)params_data,
93 if (vas != VA_STATUS_SUCCESS) {
95 "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
97 }
98
100 "is %#x.\n", pic->
nb_slices, params_size,
102
103 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
104 VASliceDataBufferType,
105 slice_size, 1, (void*)slice_data,
107 if (vas != VA_STATUS_SUCCESS) {
109 "data buffer (size %zu): %d (%s).\n",
110 slice_size, vas, vaErrorStr(vas));
111 vaDestroyBuffer(
ctx->hwctx->display,
114 }
115
119
121 return 0;
122 }
123
126 {
128 VAStatus vas;
130
132 vas = vaDestroyBuffer(
ctx->hwctx->display,
134 if (vas != VA_STATUS_SUCCESS) {
136 "parameter buffer %#x: %d (%s).\n",
138 }
139 }
140
142 vas = vaDestroyBuffer(
ctx->hwctx->display,
144 if (vas != VA_STATUS_SUCCESS) {
146 "slice buffer %#x: %d (%s).\n",
148 }
149 }
150 }
151
154 {
156 VAStatus vas;
157 int err;
158
161
162 vas = vaBeginPicture(
ctx->hwctx->display,
ctx->va_context,
164 if (vas != VA_STATUS_SUCCESS) {
166 "issue: %d (%s).\n", vas, vaErrorStr(vas));
168 goto fail_with_picture;
169 }
170
171 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
173 if (vas != VA_STATUS_SUCCESS) {
175 "parameters: %d (%s).\n", vas, vaErrorStr(vas));
177 goto fail_with_picture;
178 }
179
180 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
182 if (vas != VA_STATUS_SUCCESS) {
184 "%d (%s).\n", vas, vaErrorStr(vas));
186 goto fail_with_picture;
187 }
188
189 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
190 if (vas != VA_STATUS_SUCCESS) {
192 "issue: %d (%s).\n", vas, vaErrorStr(vas));
194 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
197 else
198 goto fail_at_end;
199 }
200
201 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
204
205 err = 0;
206 goto exit;
207
208 fail_with_picture:
209 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
210 if (vas != VA_STATUS_SUCCESS) {
212 "after error: %d (%s).\n", vas, vaErrorStr(vas));
213 }
216 fail_at_end:
217 exit:
222
223 return err;
224 }
225
228 {
230
235
236 return 0;
237 }
238
239 static const struct {
243 #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
244 // 4:0:0
246 // 4:2:0
250 #ifdef VA_FOURCC_I420
252 #endif
254 // 4:1:1
256 // 4:2:2
258 #ifdef VA_FOURCC_YV16
260 #endif
262 #ifdef VA_FOURCC_Y210
264 #endif
265 #ifdef VA_FOURCC_Y212
267 #endif
268 // 4:4:0
270 // 4:4:4
272 #ifdef VA_FOURCC_XYUV
274 #endif
275 #ifdef VA_FOURCC_Y410
277 #endif
278 #ifdef VA_FOURCC_Y412
280 #endif
281 // 4:2:0 10-bit
282 #ifdef VA_FOURCC_P010
284 #endif
285 #ifdef VA_FOURCC_P012
287 #endif
288 #ifdef VA_FOURCC_I010
289 MAP(I010, YUV420P10),
290 #endif
291 #undef MAP
292 };
293
296 VAConfigID config_id,
298 {
300 VAStatus vas;
301 VASurfaceAttrib *attr;
303 uint32_t best_fourcc,
fourcc;
305
308
309 vas = vaQuerySurfaceAttributes(hwctx->
display, config_id,
311 if (vas != VA_STATUS_SUCCESS) {
313 "%d (%s).\n", vas, vaErrorStr(vas));
315 }
316
318 if (!attr)
320
321 vas = vaQuerySurfaceAttributes(hwctx->
display, config_id,
322 attr, &nb_attr);
323 if (vas != VA_STATUS_SUCCESS) {
325 "%d (%s).\n", vas, vaErrorStr(vas));
328 }
329
331
332 for (
i = 0;
i < nb_attr;
i++) {
333 if (attr[
i].
type != VASurfaceAttribPixelFormat)
334 continue;
335
336 fourcc = attr[
i].value.value.i;
339 break;
340 }
344 continue;
345 }
349
351 source_format, 0,
NULL);
352 if (
format == best_format)
354 }
355
357
361 }
362
366
367 frames->sw_format = best_format;
371
372 ctx->pixel_format_attribute = (VASurfaceAttrib) {
373 .type = VASurfaceAttribPixelFormat,
374 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
375 .value.type = VAGenericValueTypeInteger,
376 .value.value.i = best_fourcc,
377 };
378
381 }
382
383 return 0;
384 }
385
386 static const struct {
392 #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, AV_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ }
393 MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ),
394 MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ),
396 MAP(MPEG4, MPEG4_SIMPLE, MPEG4Simple ),
397 MAP(MPEG4, MPEG4_ADVANCED_SIMPLE,
398 MPEG4AdvancedSimple),
399 MAP(MPEG4, MPEG4_MAIN, MPEG4Main ),
400 #if VA_CHECK_VERSION(1, 18, 0)
401 MAP(H264, H264_HIGH_10_INTRA,
402 H264High10 ),
403 MAP(H264, H264_HIGH_10, H264High10 ),
404 #endif
405 MAP(H264, H264_CONSTRAINED_BASELINE,
406 H264ConstrainedBaseline),
407 MAP(H264, H264_MAIN, H264Main ),
408 MAP(H264, H264_HIGH, H264High ),
409 #if VA_CHECK_VERSION(0, 37, 0)
410 MAP(HEVC, HEVC_MAIN, HEVCMain ),
411 MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ),
412 MAP(HEVC, HEVC_MAIN_STILL_PICTURE,
413 HEVCMain ),
414 #endif
415 #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
416 MAP(HEVC, HEVC_REXT, None,
418 MAP(HEVC, HEVC_SCC, None,
420 #endif
421 MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT,
422 JPEGBaseline),
423 MAP(WMV3, VC1_SIMPLE, VC1Simple ),
424 MAP(WMV3, VC1_MAIN, VC1Main ),
425 MAP(WMV3, VC1_COMPLEX, VC1Advanced ),
426 MAP(WMV3, VC1_ADVANCED, VC1Advanced ),
427 MAP(VC1, VC1_SIMPLE, VC1Simple ),
428 MAP(VC1, VC1_MAIN, VC1Main ),
429 MAP(VC1, VC1_COMPLEX, VC1Advanced ),
430 MAP(VC1, VC1_ADVANCED, VC1Advanced ),
432 #if VA_CHECK_VERSION(0, 38, 0)
433 MAP(VP9, VP9_0, VP9Profile0 ),
434 #endif
435 #if VA_CHECK_VERSION(0, 39, 0)
436 MAP(VP9, VP9_1, VP9Profile1 ),
437 MAP(VP9, VP9_2, VP9Profile2 ),
438 MAP(VP9, VP9_3, VP9Profile3 ),
439 #endif
440 #if VA_CHECK_VERSION(1, 8, 0)
441 MAP(AV1, AV1_MAIN, AV1Profile0),
442 MAP(AV1, AV1_HIGH, AV1Profile1),
443 #endif
444
445 #undef MAP
446 };
447
448 /*
449 * Set *va_config and the frames_ref fields from the current codec parameters
450 * in avctx.
451 */
454 VAConfigID *va_config,
456 {
459 VAStatus vas;
463 int profile_count, exact_match, matched_ff_profile,
codec_profile;
464
467
469 if (!codec_desc) {
472 }
473
474 profile_count = vaMaxNumProfiles(hwctx->display);
476 sizeof(VAProfile));
477 if (!profile_list) {
480 }
481
482 vas = vaQueryConfigProfiles(hwctx->display,
483 profile_list, &profile_count);
484 if (vas != VA_STATUS_SUCCESS) {
486 "%d (%s).\n", vas, vaErrorStr(vas));
489 }
490
491 matched_va_profile = VAProfileNone;
492 exact_match = 0;
493
495 int profile_match = 0;
497 continue;
500 profile_match = 1;
501
506
507 for (j = 0; j < profile_count; j++) {
509 exact_match = profile_match;
510 break;
511 }
512 }
513 if (j < profile_count) {
516 if (exact_match)
517 break;
518 }
519 }
521
522 if (matched_va_profile == VAProfileNone) {
524 "profile %d.\n", codec_desc->
name, avctx->
profile);
527 }
528 if (!exact_match) {
532 "supported for hardware decode.\n",
535 "incompatible profile %d instead.\n",
536 matched_ff_profile);
537 } else {
539 "supported for hardware decode.\n",
543 }
544 }
545
546 vas = vaCreateConfig(hwctx->display, matched_va_profile,
547 VAEntrypointVLD,
NULL, 0,
548 va_config);
549 if (vas != VA_STATUS_SUCCESS) {
551 "configuration: %d (%s).\n", vas, vaErrorStr(vas));
554 }
555
557 if (!hwconfig) {
560 }
562
563 constraints =
565 if (!constraints) {
568 }
569
575 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
581 }
585 "usable surface formats.\n");
588 }
589
590 if (frames_ref) {
592
596
599 if (err < 0)
601
602 frames->initial_pool_size = 1;
603 // Add per-codec number of surfaces used for storing reference frames.
608 frames->initial_pool_size += 16;
609 break;
611 frames->initial_pool_size += 8;
612 break;
614 frames->initial_pool_size += 3;
615 break;
616 default:
617 frames->initial_pool_size += 2;
618 }
619 }
620
623
624 return 0;
625
629 if (*va_config != VA_INVALID_ID) {
630 vaDestroyConfig(hwctx->display, *va_config);
631 *va_config = VA_INVALID_ID;
632 }
634 return err;
635 }
636
639 {
643 VAConfigID va_config = VA_INVALID_ID;
644 int err;
645
648 hwctx = device_ctx->hwctx;
649
651 hw_frames_ctx);
652 if (err)
653 return err;
654
655 if (va_config != VA_INVALID_ID)
656 vaDestroyConfig(hwctx->display, va_config);
657
658 return 0;
659 }
660
662 {
664 VAStatus vas;
665 int err;
666
667 ctx->va_config = VA_INVALID_ID;
668 ctx->va_context = VA_INVALID_ID;
669
671 if (err < 0)
673
675 ctx->hwfc =
ctx->frames->hwctx;
676 ctx->device =
ctx->frames->device_ctx;
677 ctx->hwctx =
ctx->device->hwctx;
678
681 if (err)
683
684 vas = vaCreateContext(
ctx->hwctx->display,
ctx->va_config,
686 VA_PROGRESSIVE,
687 ctx->hwfc->surface_ids,
688 ctx->hwfc->nb_surfaces,
690 if (vas != VA_STATUS_SUCCESS) {
692 "context: %d (%s).\n", vas, vaErrorStr(vas));
695 }
696
698 "%#x/%#x.\n",
ctx->va_config,
ctx->va_context);
699
700 return 0;
701
704 return err;
705 }
706
708 {
710 VAStatus vas;
711
712 if (
ctx->va_context != VA_INVALID_ID) {
713 vas = vaDestroyContext(
ctx->hwctx->display,
ctx->va_context);
714 if (vas != VA_STATUS_SUCCESS) {
716 "context %#x: %d (%s).\n",
717 ctx->va_context, vas, vaErrorStr(vas));
718 }
719 }
720 if (
ctx->va_config != VA_INVALID_ID) {
721 vas = vaDestroyConfig(
ctx->hwctx->display,
ctx->va_config);
722 if (vas != VA_STATUS_SUCCESS) {
724 "configuration %#x: %d (%s).\n",
725 ctx->va_config, vas, vaErrorStr(vas));
726 }
727 }
728
729 return 0;
730 }