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
30
31
37 {
39 VAStatus vas;
41
43
44 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
46 if (vas != VA_STATUS_SUCCESS) {
48 "buffer (type %d): %d (%s).\n",
49 type, vas, vaErrorStr(vas));
51 }
52
54
57 return 0;
58 }
59
60
63 const void *params_data,
64 size_t params_size,
65 const void *slice_data,
66 size_t slice_size)
67 {
69 VAStatus vas;
71
76 else
78
85 }
87
89
90 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
91 VASliceParameterBufferType,
92 params_size, 1, (void*)params_data,
94 if (vas != VA_STATUS_SUCCESS) {
96 "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
98 }
99
101 "is %#x.\n", pic->
nb_slices, params_size,
103
104 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
105 VASliceDataBufferType,
106 slice_size, 1, (void*)slice_data,
108 if (vas != VA_STATUS_SUCCESS) {
110 "data buffer (size %zu): %d (%s).\n",
111 slice_size, vas, vaErrorStr(vas));
112 vaDestroyBuffer(
ctx->hwctx->display,
115 }
116
120
122 return 0;
123 }
124
127 {
129 VAStatus vas;
131
133 vas = vaDestroyBuffer(
ctx->hwctx->display,
135 if (vas != VA_STATUS_SUCCESS) {
137 "parameter buffer %#x: %d (%s).\n",
139 }
140 }
141
143 vas = vaDestroyBuffer(
ctx->hwctx->display,
145 if (vas != VA_STATUS_SUCCESS) {
147 "slice buffer %#x: %d (%s).\n",
149 }
150 }
151 }
152
155 {
157 VAStatus vas;
158 int err;
159
162
163 vas = vaBeginPicture(
ctx->hwctx->display,
ctx->va_context,
165 if (vas != VA_STATUS_SUCCESS) {
167 "issue: %d (%s).\n", vas, vaErrorStr(vas));
169 goto fail_with_picture;
170 }
171
172 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
174 if (vas != VA_STATUS_SUCCESS) {
176 "parameters: %d (%s).\n", vas, vaErrorStr(vas));
178 goto fail_with_picture;
179 }
180
181 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
183 if (vas != VA_STATUS_SUCCESS) {
185 "%d (%s).\n", vas, vaErrorStr(vas));
187 goto fail_with_picture;
188 }
189
190 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
191 if (vas != VA_STATUS_SUCCESS) {
193 "issue: %d (%s).\n", vas, vaErrorStr(vas));
195 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
198 else
199 goto fail_at_end;
200 }
201
202 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
205
206 err = 0;
207 goto exit;
208
209 fail_with_picture:
210 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
211 if (vas != VA_STATUS_SUCCESS) {
213 "after error: %d (%s).\n", vas, vaErrorStr(vas));
214 }
217 fail_at_end:
218 exit:
223
224 return err;
225 }
226
229 {
231
236
237 return 0;
238 }
239
240 static const struct {
244 #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
245 // 4:0:0
247 // 4:2:0
251 #ifdef VA_FOURCC_I420
253 #endif
255 // 4:1:1
257 // 4:2:2
259 #ifdef VA_FOURCC_YV16
261 #endif
263 #ifdef VA_FOURCC_Y210
265 #endif
266 #ifdef VA_FOURCC_Y212
268 #endif
269 // 4:4:0
271 // 4:4:4
273 #ifdef VA_FOURCC_XYUV
275 #endif
276 #ifdef VA_FOURCC_Y410
278 #endif
279 #ifdef VA_FOURCC_Y412
281 #endif
282 // 4:2:0 10-bit
283 #ifdef VA_FOURCC_P010
285 #endif
286 #ifdef VA_FOURCC_P012
288 #endif
289 #ifdef VA_FOURCC_I010
290 MAP(I010, YUV420P10),
291 #endif
292 #undef MAP
293 };
294
297 VAConfigID config_id,
299 {
301 VAStatus vas;
302 VASurfaceAttrib *attr;
304 uint32_t best_fourcc,
fourcc;
306
309
310 vas = vaQuerySurfaceAttributes(hwctx->
display, config_id,
312 if (vas != VA_STATUS_SUCCESS) {
314 "%d (%s).\n", vas, vaErrorStr(vas));
316 }
317
319 if (!attr)
321
322 vas = vaQuerySurfaceAttributes(hwctx->
display, config_id,
323 attr, &nb_attr);
324 if (vas != VA_STATUS_SUCCESS) {
326 "%d (%s).\n", vas, vaErrorStr(vas));
329 }
330
332
333 for (
i = 0;
i < nb_attr;
i++) {
334 if (attr[
i].
type != VASurfaceAttribPixelFormat)
335 continue;
336
337 fourcc = attr[
i].value.value.i;
340 break;
341 }
345 continue;
346 }
350
352 source_format, 0,
NULL);
353 if (
format == best_format)
355 }
356
358
362 }
363
367
368 frames->sw_format = best_format;
372
373 ctx->pixel_format_attribute = (VASurfaceAttrib) {
374 .type = VASurfaceAttribPixelFormat,
375 .
flags = VA_SURFACE_ATTRIB_SETTABLE,
376 .value.type = VAGenericValueTypeInteger,
377 .value.value.i = best_fourcc,
378 };
379
382 }
383
384 return 0;
385 }
386
387 static const struct {
393 #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ }
394 MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ),
395 MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ),
397 MAP(MPEG4, MPEG4_SIMPLE, MPEG4Simple ),
398 MAP(MPEG4, MPEG4_ADVANCED_SIMPLE,
399 MPEG4AdvancedSimple),
400 MAP(MPEG4, MPEG4_MAIN, MPEG4Main ),
401 MAP(H264, H264_CONSTRAINED_BASELINE,
402 H264ConstrainedBaseline),
403 MAP(H264, H264_MAIN, H264Main ),
404 MAP(H264, H264_HIGH, H264High ),
405 #if VA_CHECK_VERSION(0, 37, 0)
406 MAP(HEVC, HEVC_MAIN, HEVCMain ),
407 MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ),
408 MAP(HEVC, HEVC_MAIN_STILL_PICTURE,
409 HEVCMain ),
410 #endif
411 #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
412 MAP(HEVC, HEVC_REXT, None,
414 #endif
415 MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT,
416 JPEGBaseline),
417 MAP(WMV3, VC1_SIMPLE, VC1Simple ),
418 MAP(WMV3, VC1_MAIN, VC1Main ),
419 MAP(WMV3, VC1_COMPLEX, VC1Advanced ),
420 MAP(WMV3, VC1_ADVANCED, VC1Advanced ),
421 MAP(VC1, VC1_SIMPLE, VC1Simple ),
422 MAP(VC1, VC1_MAIN, VC1Main ),
423 MAP(VC1, VC1_COMPLEX, VC1Advanced ),
424 MAP(VC1, VC1_ADVANCED, VC1Advanced ),
426 #if VA_CHECK_VERSION(0, 38, 0)
427 MAP(VP9, VP9_0, VP9Profile0 ),
428 #endif
429 #if VA_CHECK_VERSION(0, 39, 0)
430 MAP(VP9, VP9_1, VP9Profile1 ),
431 MAP(VP9, VP9_2, VP9Profile2 ),
432 MAP(VP9, VP9_3, VP9Profile3 ),
433 #endif
434 #if VA_CHECK_VERSION(1, 8, 0)
435 MAP(AV1, AV1_MAIN, AV1Profile0),
436 MAP(AV1, AV1_HIGH, AV1Profile1),
437 #endif
438
439 #undef MAP
440 };
441
442 /*
443 * Set *va_config and the frames_ref fields from the current codec parameters
444 * in avctx.
445 */
448 VAConfigID *va_config,
450 {
453 VAStatus vas;
457 int profile_count, exact_match, matched_ff_profile,
codec_profile;
458
461
463 if (!codec_desc) {
466 }
467
468 profile_count = vaMaxNumProfiles(hwctx->display);
470 sizeof(VAProfile));
471 if (!profile_list) {
474 }
475
476 vas = vaQueryConfigProfiles(hwctx->display,
477 profile_list, &profile_count);
478 if (vas != VA_STATUS_SUCCESS) {
480 "%d (%s).\n", vas, vaErrorStr(vas));
483 }
484
485 matched_va_profile = VAProfileNone;
486 exact_match = 0;
487
489 int profile_match = 0;
491 continue;
494 profile_match = 1;
495
500
501 for (j = 0; j < profile_count; j++) {
503 exact_match = profile_match;
504 break;
505 }
506 }
507 if (j < profile_count) {
510 if (exact_match)
511 break;
512 }
513 }
515
516 if (matched_va_profile == VAProfileNone) {
518 "profile %d.\n", codec_desc->
name, avctx->
profile);
521 }
522 if (!exact_match) {
526 "supported for hardware decode.\n",
529 "incompatible profile %d instead.\n",
530 matched_ff_profile);
531 } else {
533 "supported for hardware decode.\n",
537 }
538 }
539
540 vas = vaCreateConfig(hwctx->display, matched_va_profile,
541 VAEntrypointVLD,
NULL, 0,
542 va_config);
543 if (vas != VA_STATUS_SUCCESS) {
545 "configuration: %d (%s).\n", vas, vaErrorStr(vas));
548 }
549
551 if (!hwconfig) {
554 }
556
557 constraints =
559 if (!constraints) {
562 }
563
569 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
575 }
579 "usable surface formats.\n");
582 }
583
584 if (frames_ref) {
586
590
593 if (err < 0)
595
596 frames->initial_pool_size = 1;
597 // Add per-codec number of surfaces used for storing reference frames.
602 frames->initial_pool_size += 16;
603 break;
605 frames->initial_pool_size += 8;
606 break;
608 frames->initial_pool_size += 3;
609 break;
610 default:
611 frames->initial_pool_size += 2;
612 }
613 }
614
617
618 return 0;
619
623 if (*va_config != VA_INVALID_ID) {
624 vaDestroyConfig(hwctx->display, *va_config);
625 *va_config = VA_INVALID_ID;
626 }
628 return err;
629 }
630
633 {
637 VAConfigID va_config = VA_INVALID_ID;
638 int err;
639
642 hwctx = device_ctx->hwctx;
643
645 hw_frames_ctx);
646 if (err)
647 return err;
648
649 if (va_config != VA_INVALID_ID)
650 vaDestroyConfig(hwctx->display, va_config);
651
652 return 0;
653 }
654
656 {
658 VAStatus vas;
659 int err;
660
661 ctx->va_config = VA_INVALID_ID;
662 ctx->va_context = VA_INVALID_ID;
663
665 if (err < 0)
667
669 ctx->hwfc =
ctx->frames->hwctx;
670 ctx->device =
ctx->frames->device_ctx;
671 ctx->hwctx =
ctx->device->hwctx;
672
675 if (err)
677
678 vas = vaCreateContext(
ctx->hwctx->display,
ctx->va_config,
680 VA_PROGRESSIVE,
681 ctx->hwfc->surface_ids,
682 ctx->hwfc->nb_surfaces,
684 if (vas != VA_STATUS_SUCCESS) {
686 "context: %d (%s).\n", vas, vaErrorStr(vas));
689 }
690
692 "%#x/%#x.\n",
ctx->va_config,
ctx->va_context);
693
694 return 0;
695
698 return err;
699 }
700
702 {
704 VAStatus vas;
705
706 if (
ctx->va_context != VA_INVALID_ID) {
707 vas = vaDestroyContext(
ctx->hwctx->display,
ctx->va_context);
708 if (vas != VA_STATUS_SUCCESS) {
710 "context %#x: %d (%s).\n",
711 ctx->va_context, vas, vaErrorStr(vas));
712 }
713 }
714 if (
ctx->va_config != VA_INVALID_ID) {
715 vas = vaDestroyConfig(
ctx->hwctx->display,
ctx->va_config);
716 if (vas != VA_STATUS_SUCCESS) {
718 "configuration %#x: %d (%s).\n",
719 ctx->va_config, vas, vaErrorStr(vas));
720 }
721 }
722
723 return 0;
724 }