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 <string.h>
20
24
28
32 {
35 };
36 int err;
37
39 if (err < 0)
40 return err;
41
42 return 0;
43 }
44
46 {
49 for (
i = 0;
i <
ctx->nb_filter_buffers;
i++) {
50 if (
ctx->filter_buffers[
i] != VA_INVALID_ID) {
51 vaDestroyBuffer(
ctx->hwctx->display,
ctx->filter_buffers[
i]);
52 ctx->filter_buffers[
i] = VA_INVALID_ID;
53 }
54 }
55 ctx->nb_filter_buffers = 0;
56
57 if (
ctx->va_context != VA_INVALID_ID) {
58 vaDestroyContext(
ctx->hwctx->display,
ctx->va_context);
59 ctx->va_context = VA_INVALID_ID;
60 }
61
62 if (
ctx->va_config != VA_INVALID_ID) {
63 vaDestroyConfig(
ctx->hwctx->display,
ctx->va_config);
64 ctx->va_config = VA_INVALID_ID;
65 }
66
69 }
70
72 {
76
77 if (
ctx->pipeline_uninit)
78 ctx->pipeline_uninit(avctx);
79
82 "required to associate the processing device.\n");
84 }
85
87 if (!
ctx->input_frames_ref) {
89 "failed.\n");
91 }
93
94 return 0;
95 }
96
98 {
108 VAStatus vas;
110
111 if (
ctx->pipeline_uninit)
112 ctx->pipeline_uninit(avctx);
113
114 if (!
ctx->output_width)
116 if (!
ctx->output_height)
118
119 outlink->
w =
ctx->output_width;
120 outlink->
h =
ctx->output_height;
121
122 if (
ctx->passthrough) {
126
127 return 0;
128 }
129
132 if (!
ctx->device_ref) {
134 "failed.\n");
136 }
138
140 vas = vaCreateConfig(
ctx->hwctx->display, VAProfileNone,
141 VAEntrypointVideoProc,
NULL, 0, &
ctx->va_config);
142 if (vas != VA_STATUS_SUCCESS) {
144 "config: %d (%s).\n", vas, vaErrorStr(vas));
147 }
148
150 if (!hwconfig) {
153 }
155
157 hwconfig);
158 if (!constraints) {
161 }
162
164 ctx->output_format =
ctx->input_frames->sw_format;
168 break;
169 }
175 }
176 }
177
183 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
184 ctx->output_width,
ctx->output_height,
189 }
190
194 "for output.\n");
197 }
198
200
203 output_frames->
width =
ctx->output_width;
204 output_frames->
height =
ctx->output_height;
205
208 else
210
212 if (err < 0)
214
216 if (err < 0) {
218 "context for output: %d\n", err);
220 }
221
222 va_frames = output_frames->
hwctx;
223
227 vas = vaCreateContext(
ctx->hwctx->display,
ctx->va_config,
228 ctx->output_width,
ctx->output_height,
229 VA_PROGRESSIVE,
232 if (vas != VA_STATUS_SUCCESS) {
234 "context: %d (%s).\n", vas, vaErrorStr(vas));
236 }
237
238 if (
ctx->build_filter_params) {
239 err =
ctx->build_filter_params(avctx);
240 if (err < 0)
242 }
243
246 return 0;
247
252 return err;
253 }
254
257
261
264
268
270 { VAProcColorStandardBT601, 5, 6, 5 },
271 { VAProcColorStandardBT601, 6, 6, 6 },
272 { VAProcColorStandardBT709, 1, 1, 1 },
273 { VAProcColorStandardBT470M, 4, 4, 4 },
274 { VAProcColorStandardBT470BG, 5, 5, 5 },
275 { VAProcColorStandardSMPTE170M, 6, 6, 6 },
276 { VAProcColorStandardSMPTE240M, 7, 7, 7 },
277 { VAProcColorStandardGenericFilm, 8, 1, 1 },
278 #if VA_CHECK_VERSION(1, 1, 0)
279 { VAProcColorStandardSRGB, 1, 13, 0 },
280 { VAProcColorStandardXVYCC601, 1, 11, 5 },
281 { VAProcColorStandardXVYCC709, 1, 11, 1 },
282 { VAProcColorStandardBT2020, 9, 14, 9 },
283 #endif
284 };
285
287 VAProcColorStandardType *vacs,
288 int nb_vacs)
289 {
291 int i, j, score, best_score, worst_score;
292 VAProcColorStandardType best_standard;
293
294 #if VA_CHECK_VERSION(1, 3, 0)
295 // If the driver supports explicit use of the standard values then just
296 // use them and avoid doing any mapping. (The driver may not support
297 // some particular code point, but it still has enough information to
298 // make a better fallback choice than we do in that case.)
299 for (
i = 0;
i < nb_vacs;
i++) {
300 if (vacs[
i] == VAProcColorStandardExplicit) {
302 return;
303 }
304 }
305 #endif
306
307 // Give scores to the possible options and choose the lowest one.
308 // An exact match will score zero and therefore always be chosen, as
309 // will a partial match where all unmatched elements are explicitly
310 // unspecified. If no options match at all then just pass "none" to
311 // the driver and let it make its own choice.
312 best_standard = VAProcColorStandardNone;
313 best_score = -1;
318
319 if (worst_score == 0) {
320 // No properties are specified, so we aren't going to be able to
321 // make a useful choice.
323 return;
324 }
325
326 for (
i = 0;
i < nb_vacs;
i++) {
330 continue;
331
332 score = 0;
340
341 // Only include choices which matched something.
342 if (score < worst_score &&
343 (best_score == -1 || score < best_score)) {
344 best_score = score;
346 }
347 }
348 }
350 }
351
353 {
354 #if VA_CHECK_VERSION(1, 1, 0)
355 static const struct {
357 uint8_t va;
358 } csl_map[] = {
361 VA_CHROMA_SITING_HORIZONTAL_LEFT },
363 VA_CHROMA_SITING_HORIZONTAL_CENTER },
365 VA_CHROMA_SITING_HORIZONTAL_LEFT },
367 VA_CHROMA_SITING_HORIZONTAL_CENTER },
369 VA_CHROMA_SITING_HORIZONTAL_LEFT },
371 VA_CHROMA_SITING_HORIZONTAL_CENTER },
372 };
374
378 return;
379 }
380 }
382 #else
384 #endif
385 }
386
388 {
389 #if VA_CHECK_VERSION(1, 1, 0)
393 break;
396 break;
398 default:
400 }
401 #else
403 #endif
404 }
405
408 VAProcColorStandardType *vacs,
409 int nb_vacs)
410 {
414
416 "to VA standard %d chroma siting %#x range %#x.\n",
424 }
425
427 {
431 frame->hw_frames_ctx);
436 }
437
439 VAProcPipelineParameterBuffer *params,
442 {
445 VAProcPipelineCaps caps;
446 VAStatus vas;
447
448 vas = vaQueryVideoProcPipelineCaps(
ctx->hwctx->display,
ctx->va_context,
449 ctx->filter_buffers,
ctx->nb_filter_buffers,
450 &caps);
451 if (vas != VA_STATUS_SUCCESS) {
453 "colour standard support: %d (%s).\n", vas, vaErrorStr(vas));
455 }
456
464 };
465
467 caps.input_color_standards,
468 caps.num_input_color_standards);
469
476 .chroma_sample_location =
output_frame->chroma_location,
477 };
479 caps.output_color_standards,
480 caps.num_output_color_standards);
481
482 // If the properties weren't filled completely in the output frame and
483 // we chose a fixed standard then fill the known values in here.
484 #if VA_CHECK_VERSION(1, 3, 0)
486 #endif
487 {
490
495 break;
496 }
497 }
498 if (output_standard) {
503 }
504 }
505
508
509 #if VA_CHECK_VERSION(1, 1, 0)
510 params->input_color_properties = (VAProcColorProperties) {
513 #if VA_CHECK_VERSION(1, 3, 0)
515 .transfer_characteristics = input_props.
color_trc,
516 .matrix_coefficients = input_props.
colorspace,
517 #endif
518 };
519 params->output_color_properties = (VAProcColorProperties) {
522 #if VA_CHECK_VERSION(1, 3, 0)
524 .transfer_characteristics = output_props.
color_trc,
525 .matrix_coefficients = output_props.
colorspace,
526 #endif
527 };
528 #endif
529
530 return 0;
531 }
532
534 VAProcPipelineParameterBuffer *params,
537 {
539 int err;
540
541 ctx->input_region = (VARectangle) {
544 .width = input_frame->
width -
548 };
553
554 *params = (VAProcPipelineParameterBuffer) {
556 .surface_region = &
ctx->input_region,
557 .output_region =
NULL,
559 .pipeline_flags = 0,
560 .filter_flags = VA_FRAME_PICTURE,
561
562 // Filter and reference data filled by the filter itself.
563
564 #if VA_CHECK_VERSION(1, 1, 0)
565 .rotation_state = VA_ROTATION_NONE,
566 .mirror_state = VA_MIRROR_NONE,
567 #endif
568 };
569
572 if (err < 0)
573 return err;
574
578
579 return 0;
580 }
581
586 int count)
587 {
588 VAStatus vas;
591
593
594 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
596 if (vas != VA_STATUS_SUCCESS) {
598 "buffer (type %d): %d (%s).\n",
599 type, vas, vaErrorStr(vas));
601 }
602
604
607 return 0;
608 }
609
611 VAProcPipelineParameterBuffer *params,
612 VABufferID *params_id)
613 {
615 VAStatus vas;
616
617 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
618 VAProcPipelineParameterBufferType,
619 sizeof(*params), 1, params, params_id);
620 if (vas != VA_STATUS_SUCCESS) {
622 "%d (%s).\n", vas, vaErrorStr(vas));
623 *params_id = VA_INVALID_ID;
624
626 }
628
629 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context, params_id, 1);
630 if (vas != VA_STATUS_SUCCESS) {
632 "%d (%s).\n", vas, vaErrorStr(vas));
634 }
635
636 return 0;
637 }
638
640 VAProcPipelineParameterBuffer *params_list,
641 int cout,
643 {
645 VABufferID *params_ids;
646 VAStatus vas;
647 int err;
648
650 if (!params_ids)
652
653 for (
int i = 0;
i < cout;
i++)
654 params_ids[
i] = VA_INVALID_ID;
655
656 vas = vaBeginPicture(
ctx->hwctx->display,
658 if (vas != VA_STATUS_SUCCESS) {
660 "%d (%s).\n", vas, vaErrorStr(vas));
663 }
664
665 for (
int i = 0;
i < cout;
i++) {
667 if (err)
668 goto fail_after_begin;
669 }
670
671 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
672 if (vas != VA_STATUS_SUCCESS) {
674 "%d (%s).\n", vas, vaErrorStr(vas));
676 goto fail_after_render;
677 }
678
679 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
681 for (
int i = 0;
i < cout && params_ids[
i] != VA_INVALID_ID;
i++) {
682 vas = vaDestroyBuffer(
ctx->hwctx->display, params_ids[
i]);
683 if (vas != VA_STATUS_SUCCESS) {
685 "%d (%s).\n", vas, vaErrorStr(vas));
686 // And ignore.
687 }
688 }
689 }
690
692 return 0;
693
694 // We want to make sure that if vaBeginPicture has been called, we also
695 // call vaRenderPicture and vaEndPicture. These calls may well fail or
696 // do something else nasty, but once we're in this failure case there
697 // isn't much else we can do.
698 fail_after_begin:
699 vaRenderPicture(
ctx->hwctx->display,
ctx->va_context, ¶ms_ids[0], 1);
700 fail_after_render:
701 vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
704 return err;
705 }
706
708 VAProcPipelineParameterBuffer *params,
710 {
712 }
713
715 {
718
719 ctx->va_config = VA_INVALID_ID;
720 ctx->va_context = VA_INVALID_ID;
722
723 for (
i = 0;
i < VAProcFilterCount;
i++)
724 ctx->filter_buffers[
i] = VA_INVALID_ID;
725 ctx->nb_filter_buffers = 0;
726 }
727
729 {
731 if (
ctx->valid_ids &&
ctx->pipeline_uninit)
732 ctx->pipeline_uninit(avctx);
733
736 }