FFmpeg
Loading...
Searching...
No Matches
vf_libvmaf.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 Ronald S. Bultje <rsbultje@gmail.com>
3 * Copyright (c) 2017 Ashish Pratap Singh <ashk43712@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23 * @file
24 * Calculate the VMAF between two input videos.
25 */
26
27#include "config_components.h"
28
29#include <libvmaf.h>
30
31#include "libavutil/avstring.h"
32#include "libavutil/mem.h"
33#include "libavutil/opt.h"
34#include "libavutil/pixdesc.h"
35#include "avfilter.h"
36#include "drawutils.h"
37#include "filters.h"
38#include "formats.h"
39#include "framesync.h"
40#include "video.h"
41
42#if CONFIG_LIBVMAF_CUDA_FILTER
43#include <libvmaf_cuda.h>
44
45#include "libavutil/hwcontext.h"
47#endif
48
49typedef struct LIBVMAFContext {
50 const AVClass *class;
52 char *log_path;
53 char *log_fmt;
54 char *pool;
57 char *model_cfg;
59 VmafContext *vmaf;
60 VmafModel **model;
61 unsigned model_cnt;
62 unsigned frame_cnt;
63 unsigned bpc;
64#if CONFIG_LIBVMAF_CUDA_FILTER
65 VmafCudaState *cu_state;
66#endif
68
69#define OFFSET(x) offsetof(LIBVMAFContext, x)
70#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
71
72static const AVOption libvmaf_options[] = {
73 {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS},
74 {"log_fmt", "Set the format of the log (csv, json, xml, or sub).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str="xml"}, 0, 1, FLAGS},
75 {"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS},
76 {"n_threads", "Set number of threads to be used when computing vmaf.", OFFSET(n_threads), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT_MAX, FLAGS},
77 {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS},
78 {"model", "Set the model to be used for computing vmaf.", OFFSET(model_cfg), AV_OPT_TYPE_STRING, {.str="version=vmaf_v0.6.1"}, 0, 1, FLAGS},
79 {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS},
80 { NULL }
81};
82
84
85static enum VmafPixelFormat pix_fmt_map(enum AVPixelFormat av_pix_fmt)
86{
87 switch (av_pix_fmt) {
92 return VMAF_PIX_FMT_YUV420P;
97 return VMAF_PIX_FMT_YUV422P;
102 return VMAF_PIX_FMT_YUV444P;
103 default:
104 return VMAF_PIX_FMT_UNKNOWN;
105 }
106}
107
108static int copy_picture_data(AVFrame *src, VmafPicture *dst, unsigned bpc)
109{
110 const int bytes_per_value = bpc > 8 ? 2 : 1;
111 int err = vmaf_picture_alloc(dst, pix_fmt_map(src->format), bpc,
112 src->width, src->height);
113 if (err)
114 return AVERROR(ENOMEM);
115
116 for (unsigned i = 0; i < 3; i++) {
117 uint8_t *src_data = src->data[i];
118 uint8_t *dst_data = dst->data[i];
119 for (unsigned j = 0; j < dst->h[i]; j++) {
120 memcpy(dst_data, src_data, bytes_per_value * dst->w[i]);
121 src_data += src->linesize[i];
122 dst_data += dst->stride[i];
123 }
124 }
125
126 return 0;
127}
128
130{
131 AVFilterContext *ctx = fs->parent;
132 LIBVMAFContext *s = ctx->priv;
133 VmafPicture pic_ref, pic_dist;
134 AVFrame *ref, *dist;
135 int err = 0;
136
137 int ret = ff_framesync_dualinput_get(fs, &dist, &ref);
138 if (ret < 0)
139 return ret;
140 if (ctx->is_disabled || !ref)
141 return ff_filter_frame(ctx->outputs[0], dist);
142
143 if (dist->color_range != ref->color_range) {
144 av_log(ctx, AV_LOG_WARNING, "distorted and reference "
145 "frames use different color ranges (%s != %s)\n",
147 av_color_range_name(ref->color_range));
148 }
149
150 err = copy_picture_data(ref, &pic_ref, s->bpc);
151 if (err) {
152 av_log(ctx, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n");
153 return AVERROR(ENOMEM);
154 }
155
156 err = copy_picture_data(dist, &pic_dist, s->bpc);
157 if (err) {
158 av_log(ctx, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n");
159 vmaf_picture_unref(&pic_ref);
160 return AVERROR(ENOMEM);
161 }
162
163 err = vmaf_read_pictures(s->vmaf, &pic_ref, &pic_dist, s->frame_cnt++);
164 if (err) {
165 av_log(ctx, AV_LOG_ERROR, "problem during vmaf_read_pictures.\n");
166 return AVERROR(EINVAL);
167 }
168
169 return ff_filter_frame(ctx->outputs[0], dist);
170}
171
172static AVDictionary **delimited_dict_parse(char *str, unsigned *cnt)
173{
174 AVDictionary **dict = NULL;
175 char *str_copy = NULL;
176 char *saveptr = NULL;
177 unsigned cnt2;
178 int err = 0;
179
180 if (!str)
181 return NULL;
182
183 cnt2 = 1;
184 for (char *p = str; *p; p++) {
185 if (*p == '|')
186 cnt2++;
187 }
188
189 dict = av_calloc(cnt2, sizeof(*dict));
190 if (!dict)
191 goto fail;
192
193 str_copy = av_strdup(str);
194 if (!str_copy)
195 goto fail;
196
197 *cnt = 0;
198 for (unsigned i = 0; i < cnt2; i++) {
199 char *s = av_strtok(i == 0 ? str_copy : NULL, "|", &saveptr);
200 if (!s)
201 continue;
202 err = av_dict_parse_string(&dict[(*cnt)++], s, "=", ":", 0);
203 if (err)
204 goto fail;
205 }
206
207 av_free(str_copy);
208 return dict;
209
210fail:
211 if (dict) {
212 for (unsigned i = 0; i < *cnt; i++) {
213 if (dict[i])
214 av_dict_free(&dict[i]);
215 }
216 av_free(dict);
217 }
218
219 av_free(str_copy);
220 *cnt = 0;
221 return NULL;
222}
223
225{
226 LIBVMAFContext *s = ctx->priv;
227 AVDictionary **dict = NULL;
228 unsigned dict_cnt;
229 int err = 0;
230
231 if (!s->feature_cfg)
232 return 0;
233
234 dict = delimited_dict_parse(s->feature_cfg, &dict_cnt);
235 if (!dict) {
237 "could not parse feature config: %s\n", s->feature_cfg);
238 return AVERROR(EINVAL);
239 }
240
241 for (unsigned i = 0; i < dict_cnt; i++) {
242 char *feature_name = NULL;
243 VmafFeatureDictionary *feature_opts_dict = NULL;
244 const AVDictionaryEntry *e = NULL;
245
246 while (e = av_dict_iterate(dict[i], e)) {
247 if (!strcmp(e->key, "name")) {
248 feature_name = e->value;
249 continue;
250 }
251
252 err = vmaf_feature_dictionary_set(&feature_opts_dict, e->key,
253 e->value);
254 if (err) {
256 "could not set feature option: %s.%s=%s\n",
257 feature_name, e->key, e->value);
258 goto exit;
259 }
260 }
261
262 err = vmaf_use_feature(s->vmaf, feature_name, feature_opts_dict);
263 if (err) {
265 "problem during vmaf_use_feature: %s\n", feature_name);
266 goto exit;
267 }
268 }
269
270exit:
271 for (unsigned i = 0; i < dict_cnt; i++) {
272 if (dict[i])
273 av_dict_free(&dict[i]);
274 }
275 av_free(dict);
276 return err;
277}
278
280{
281 LIBVMAFContext *s = ctx->priv;
282 AVDictionary **dict;
283 unsigned dict_cnt;
284 int err = 0;
285
286 if (!s->model_cfg) return 0;
287
288 dict_cnt = 0;
289 dict = delimited_dict_parse(s->model_cfg, &dict_cnt);
290 if (!dict) {
292 "could not parse model config: %s\n", s->model_cfg);
293 return AVERROR(EINVAL);
294 }
295
296 s->model_cnt = dict_cnt;
297 s->model = av_calloc(s->model_cnt, sizeof(*s->model));
298 if (!s->model)
299 return AVERROR(ENOMEM);
300
301 for (unsigned i = 0; i < dict_cnt; i++) {
302 VmafModelConfig model_cfg = { 0 };
303 const AVDictionaryEntry *e = NULL;
304 char *version = NULL;
305 char *path = NULL;
306
307 while (e = av_dict_iterate(dict[i], e)) {
308 if (!strcmp(e->key, "disable_clip")) {
309 model_cfg.flags |= !strcmp(e->value, "true") ?
310 VMAF_MODEL_FLAG_DISABLE_CLIP : 0;
311 continue;
312 }
313
314 if (!strcmp(e->key, "enable_transform")) {
315 model_cfg.flags |= !strcmp(e->value, "true") ?
316 VMAF_MODEL_FLAG_ENABLE_TRANSFORM : 0;
317 continue;
318 }
319
320 if (!strcmp(e->key, "name")) {
321 model_cfg.name = e->value;
322 continue;
323 }
324
325 if (!strcmp(e->key, "version")) {
326 version = e->value;
327 continue;
328 }
329
330 if (!strcmp(e->key, "path")) {
331 path = e->value;
332 continue;
333 }
334 }
335
336 if (version) {
337 err = vmaf_model_load(&s->model[i], &model_cfg, version);
338 if (err) {
340 "could not load libvmaf model with version: %s\n",
341 version);
342 goto exit;
343 }
344 }
345
346 if (path && !s->model[i]) {
347 err = vmaf_model_load_from_path(&s->model[i], &model_cfg, path);
348 if (err) {
350 "could not load libvmaf model with path: %s\n",
351 path);
352 goto exit;
353 }
354 }
355
356 if (!s->model[i]) {
358 "could not load libvmaf model with config: %s\n",
359 s->model_cfg);
360 goto exit;
361 }
362
363 while (e = av_dict_iterate(dict[i], e)) {
364 VmafFeatureDictionary *feature_opts_dict = NULL;
365 char *feature_opt = NULL;
366
367 char *feature_name = av_strtok(e->key, ".", &feature_opt);
368 if (!feature_opt)
369 continue;
370
371 err = vmaf_feature_dictionary_set(&feature_opts_dict,
372 feature_opt, e->value);
373 if (err) {
375 "could not set feature option: %s.%s=%s\n",
376 feature_name, feature_opt, e->value);
377 err = AVERROR(EINVAL);
378 goto exit;
379 }
380
381 err = vmaf_model_feature_overload(s->model[i], feature_name,
382 feature_opts_dict);
383 if (err) {
385 "could not overload feature: %s\n", feature_name);
386 err = AVERROR(EINVAL);
387 goto exit;
388 }
389 }
390 }
391
392 for (unsigned i = 0; i < s->model_cnt; i++) {
393 err = vmaf_use_features_from_model(s->vmaf, s->model[i]);
394 if (err) {
396 "problem during vmaf_use_features_from_model\n");
397 err = AVERROR(EINVAL);
398 goto exit;
399 }
400 }
401
402exit:
403 for (unsigned i = 0; i < dict_cnt; i++) {
404 if (dict[i])
405 av_dict_free(&dict[i]);
406 }
407 av_free(dict);
408 return err;
409}
410
411static enum VmafLogLevel log_level_map(int log_level)
412{
413 switch (log_level) {
414 case AV_LOG_QUIET:
415 return VMAF_LOG_LEVEL_NONE;
416 case AV_LOG_ERROR:
417 return VMAF_LOG_LEVEL_ERROR;
418 case AV_LOG_WARNING:
419 return VMAF_LOG_LEVEL_WARNING;
420 case AV_LOG_INFO:
421 return VMAF_LOG_LEVEL_INFO;
422 case AV_LOG_DEBUG:
423 return VMAF_LOG_LEVEL_DEBUG;
424 default:
425 return VMAF_LOG_LEVEL_INFO;
426 }
427}
428
430{
431 LIBVMAFContext *s = ctx->priv;
432 int err = 0;
433
434 VmafConfiguration cfg = {
435 .log_level = log_level_map(av_log_get_level()),
436 .n_subsample = s->n_subsample,
437 .n_threads = s->n_threads,
438 };
439
440 err = vmaf_init(&s->vmaf, cfg);
441 if (err)
442 return AVERROR(EINVAL);
443
444 err = parse_models(ctx);
445 if (err)
446 return err;
447
448 err = parse_features(ctx);
449 if (err)
450 return err;
451
452 s->fs.on_event = do_vmaf;
453 return 0;
454}
455
463
465{
466 AVFilterContext *ctx = inlink->dst;
467 LIBVMAFContext *s = ctx->priv;
469 int err = 0;
470
471 if (ctx->inputs[0]->w != ctx->inputs[1]->w) {
472 av_log(ctx, AV_LOG_ERROR, "input width must match.\n");
473 err |= AVERROR(EINVAL);
474 }
475
476 if (ctx->inputs[0]->h != ctx->inputs[1]->h) {
477 av_log(ctx, AV_LOG_ERROR, "input height must match.\n");
478 err |= AVERROR(EINVAL);
479 }
480
481 if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
482 av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n");
483 err |= AVERROR(EINVAL);
484 }
485
486 if (err)
487 return err;
488
490 s->bpc = desc->comp[0].depth;
491
492 return 0;
493}
494
495static int config_output(AVFilterLink *outlink)
496{
497 AVFilterContext *ctx = outlink->src;
498 LIBVMAFContext *s = ctx->priv;
499 AVFilterLink *mainlink = ctx->inputs[0];
500 FilterLink *il = ff_filter_link(mainlink);
501 FilterLink *ol = ff_filter_link(outlink);
502 int ret;
503
504 ret = ff_framesync_init_dualinput(&s->fs, ctx);
505 if (ret < 0)
506 return ret;
507 outlink->w = mainlink->w;
508 outlink->h = mainlink->h;
509 outlink->time_base = mainlink->time_base;
510 outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
511 ol->frame_rate = il->frame_rate;
512 if ((ret = ff_framesync_configure(&s->fs)) < 0)
513 return ret;
514
515 return 0;
516}
517
519{
520 LIBVMAFContext *s = ctx->priv;
521 return ff_framesync_activate(&s->fs);
522}
523
524static enum VmafOutputFormat log_fmt_map(const char *log_fmt)
525{
526 if (log_fmt) {
527 if (!strcmp(log_fmt, "xml"))
528 return VMAF_OUTPUT_FORMAT_XML;
529 if (!strcmp(log_fmt, "json"))
530 return VMAF_OUTPUT_FORMAT_JSON;
531 if (!strcmp(log_fmt, "csv"))
532 return VMAF_OUTPUT_FORMAT_CSV;
533 if (!strcmp(log_fmt, "sub"))
534 return VMAF_OUTPUT_FORMAT_SUB;
535 }
536
537 return VMAF_OUTPUT_FORMAT_XML;
538}
539
540static enum VmafPoolingMethod pool_method_map(const char *pool_method)
541{
542 if (pool_method) {
543 if (!strcmp(pool_method, "min"))
544 return VMAF_POOL_METHOD_MIN;
545 if (!strcmp(pool_method, "mean"))
546 return VMAF_POOL_METHOD_MEAN;
547 if (!strcmp(pool_method, "harmonic_mean"))
548 return VMAF_POOL_METHOD_HARMONIC_MEAN;
549 }
550
551 return VMAF_POOL_METHOD_MEAN;
552}
553
555{
556 LIBVMAFContext *s = ctx->priv;
557 int err = 0;
558
560
561 if (!s->frame_cnt)
562 goto clean_up;
563
564 err = vmaf_read_pictures(s->vmaf, NULL, NULL, 0);
565 if (err) {
567 "problem flushing libvmaf context.\n");
568 }
569
570 for (unsigned i = 0; i < s->model_cnt; i++) {
571 double vmaf_score;
572 err = vmaf_score_pooled(s->vmaf, s->model[i], pool_method_map(s->pool),
573 &vmaf_score, 0, s->frame_cnt - 1);
574 if (err) {
576 "problem getting pooled vmaf score.\n");
577 }
578
579 av_log(ctx, AV_LOG_INFO, "VMAF score: %f\n", vmaf_score);
580 }
581
582 if (s->vmaf) {
583 if (s->log_path && !err)
584 vmaf_write_output(s->vmaf, s->log_path, log_fmt_map(s->log_fmt));
585 }
586
587clean_up:
588 if (s->model) {
589 for (unsigned i = 0; i < s->model_cnt; i++) {
590 if (s->model[i])
591 vmaf_model_destroy(s->model[i]);
592 }
593 av_free(s->model);
594 }
595
596 if (s->vmaf)
597 vmaf_close(s->vmaf);
598}
599
600static const AVFilterPad libvmaf_inputs[] = {
601 {
602 .name = "main",
603 .type = AVMEDIA_TYPE_VIDEO,
604 },
605 {
606 .name = "reference",
607 .type = AVMEDIA_TYPE_VIDEO,
608 .config_props = config_input_ref,
609 },
610};
611
612static const AVFilterPad libvmaf_outputs[] = {
613 {
614 .name = "default",
615 .type = AVMEDIA_TYPE_VIDEO,
616 .config_props = config_output,
617 },
618};
619
621 .p.name = "libvmaf",
622 .p.description = NULL_IF_CONFIG_SMALL("Calculate the VMAF between two video streams."),
623 .p.priv_class = &libvmaf_class,
624 .preinit = libvmaf_framesync_preinit,
625 .init = init,
626 .uninit = uninit,
627 .activate = activate,
628 .priv_size = sizeof(LIBVMAFContext),
632};
633
634#if CONFIG_LIBVMAF_CUDA_FILTER
635static const enum AVPixelFormat supported_formats[] = {
638};
639
640static int format_is_supported(enum AVPixelFormat fmt)
641{
642 int i;
643
644 for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
645 if (supported_formats[i] == fmt)
646 return 1;
647 return 0;
648}
649
650static int config_props_cuda(AVFilterLink *outlink)
651{
652 int err;
653 AVFilterContext *ctx = outlink->src;
654 LIBVMAFContext *s = ctx->priv;
655 AVFilterLink *inlink = ctx->inputs[0];
656 FilterLink *inl = ff_filter_link(inlink);
658 AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
659 CUcontext cu_ctx = device_hwctx->cuda_ctx;
660 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frames_ctx->sw_format);
661
662 VmafConfiguration cfg = {
663 .log_level = log_level_map(av_log_get_level()),
664 .n_subsample = s->n_subsample,
665 .n_threads = s->n_threads,
666 };
667
668 VmafCudaPictureConfiguration cuda_pic_cfg = {
669 .pic_params = {
670 .bpc = desc->comp[0].depth,
671 .w = inlink->w,
672 .h = inlink->h,
673 .pix_fmt = pix_fmt_map(frames_ctx->sw_format),
674 },
675 .pic_prealloc_method = VMAF_CUDA_PICTURE_PREALLOCATION_METHOD_DEVICE,
676 };
677
678 VmafCudaConfiguration cuda_cfg = {
679 .cu_ctx = cu_ctx,
680 };
681
682 if (!format_is_supported(frames_ctx->sw_format)) {
684 "Unsupported input format: %s\n", desc->name);
685 return AVERROR(EINVAL);
686 }
687
688 err = vmaf_init(&s->vmaf, cfg);
689 if (err)
690 return AVERROR(EINVAL);
691
692 err = vmaf_cuda_state_init(&s->cu_state, cuda_cfg);
693 if (err)
694 return AVERROR(EINVAL);
695
696 err = vmaf_cuda_import_state(s->vmaf, s->cu_state);
697 if (err)
698 return AVERROR(EINVAL);
699
700 err = vmaf_cuda_preallocate_pictures(s->vmaf, cuda_pic_cfg);
701 if (err < 0)
702 return err;
703
704 err = parse_models(ctx);
705 if (err)
706 return err;
707
708 err = parse_features(ctx);
709 if (err)
710 return err;
711
712 return config_output(outlink);
713}
714
715static int copy_picture_data_cuda(VmafContext* vmaf,
716 AVCUDADeviceContext* device_hwctx,
717 AVFrame* src, VmafPicture* dst,
719{
721 CudaFunctions *cu = device_hwctx->internal->cuda_dl;
722
723 CUDA_MEMCPY2D m = {
724 .srcMemoryType = CU_MEMORYTYPE_DEVICE,
725 .dstMemoryType = CU_MEMORYTYPE_DEVICE,
726 };
727
728 int err = vmaf_cuda_fetch_preallocated_picture(vmaf, dst);
729 if (err)
730 return AVERROR(ENOMEM);
731
732 err = cu->cuCtxPushCurrent(device_hwctx->cuda_ctx);
733 if (err)
734 return AVERROR_EXTERNAL;
735
736 for (unsigned i = 0; i < pix_desc->nb_components; i++) {
737 m.srcDevice = (CUdeviceptr) src->data[i];
738 m.srcPitch = src->linesize[i];
739 m.dstDevice = (CUdeviceptr) dst->data[i];
740 m.dstPitch = dst->stride[i];
741 m.WidthInBytes = dst->w[i] * ((dst->bpc + 7) / 8);
742 m.Height = dst->h[i];
743
744 err = cu->cuMemcpy2D(&m);
745 if (err)
746 return AVERROR_EXTERNAL;
747 break;
748 }
749
750 err = cu->cuCtxPopCurrent(NULL);
751 if (err)
752 return AVERROR_EXTERNAL;
753
754 return 0;
755}
756
757static int do_vmaf_cuda(FFFrameSync* fs)
758{
759 AVFilterContext* ctx = fs->parent;
760 LIBVMAFContext* s = ctx->priv;
761 AVFilterLink *inlink = ctx->inputs[0];
762 FilterLink *inl = ff_filter_link(inlink);
764 AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
765 VmafPicture pic_ref, pic_dist;
766 AVFrame *ref, *dist;
767
768 int err = 0;
769
770 err = ff_framesync_dualinput_get(fs, &dist, &ref);
771 if (err < 0)
772 return err;
773 if (ctx->is_disabled || !ref)
774 return ff_filter_frame(ctx->outputs[0], dist);
775
776 err = copy_picture_data_cuda(s->vmaf, device_hwctx, ref, &pic_ref,
777 frames_ctx->sw_format);
778 if (err) {
779 av_log(ctx, AV_LOG_ERROR, "problem during copy_picture_data_cuda.\n");
780 return AVERROR(ENOMEM);
781 }
782
783 err = copy_picture_data_cuda(s->vmaf, device_hwctx, dist, &pic_dist,
784 frames_ctx->sw_format);
785 if (err) {
786 av_log(ctx, AV_LOG_ERROR, "problem during copy_picture_data_cuda.\n");
787 return AVERROR(ENOMEM);
788 }
789
790 err = vmaf_read_pictures(s->vmaf, &pic_ref, &pic_dist, s->frame_cnt++);
791 if (err) {
792 av_log(ctx, AV_LOG_ERROR, "problem during vmaf_read_pictures.\n");
793 return AVERROR(EINVAL);
794 }
795
796 return ff_filter_frame(ctx->outputs[0], dist);
797}
798
799static av_cold int init_cuda(AVFilterContext *ctx)
800{
801 LIBVMAFContext *s = ctx->priv;
802 s->fs.on_event = do_vmaf_cuda;
803 return 0;
804}
805
806static const AVFilterPad libvmaf_outputs_cuda[] = {
807 {
808 .name = "default",
809 .type = AVMEDIA_TYPE_VIDEO,
810 .config_props = config_props_cuda,
811 },
812};
813
815 .p.name = "libvmaf_cuda",
816 .p.description = NULL_IF_CONFIG_SMALL("Calculate the VMAF between two video streams."),
817 .p.priv_class = &libvmaf_class,
818 .preinit = libvmaf_framesync_preinit,
819 .init = init_cuda,
820 .uninit = uninit,
821 .activate = activate,
822 .priv_size = sizeof(LIBVMAFContext),
824 FILTER_OUTPUTS(libvmaf_outputs_cuda),
826 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
827};
828#endif
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
const FFFilter ff_vf_libvmaf
Definition vf_libvmaf.c:620
const FFFilter ff_vf_libvmaf_cuda
static AVFormatContext * ctx
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define fs(width, name, subs,...)
Definition cbs_vp9.c:200
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
static enum AVPixelFormat pix_fmt
misc drawing utilities
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static CheckasmConfig cfg
Definition checkasm.c:74
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition framesync.c:137
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition framesync.c:390
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition framesync.c:352
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition framesync.c:372
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition framesync.c:301
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
Definition framesync.h:352
#define fail
Definition test.h:479
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:42
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition dict.c:210
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_QUIET
Print no output.
Definition log.h:192
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int av_log_get_level(void)
Get the current log level.
Definition log.c:471
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition avstring.c:179
FFmpeg internal API for CUDA.
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
Definition filters.h:208
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition filters.h:254
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
version
Definition libkvazaar.c:313
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
const char * desc
Definition libsvtav1.c:83
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
#define av_strdup(s)
Definition ops_static.c:55
AVOptions.
const char * av_color_range_name(enum AVColorRange range)
Definition pixdesc.c:3776
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition pixfmt.h:260
@ AV_PIX_FMT_YUV420P10LE
planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition pixfmt.h:156
@ AV_PIX_FMT_YUV422P16LE
planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition pixfmt.h:130
@ AV_PIX_FMT_YUV422P12LE
planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition pixfmt.h:272
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUV420P12LE
planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition pixfmt.h:268
@ AV_PIX_FMT_YUV422P10LE
planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition pixfmt.h:158
@ AV_PIX_FMT_YUV444P16LE
planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition pixfmt.h:132
@ AV_PIX_FMT_YUV444P10LE
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition pixfmt.h:162
@ AV_PIX_FMT_YUV420P16LE
planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition pixfmt.h:128
@ AV_PIX_FMT_YUV444P12LE
planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition pixfmt.h:276
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:558
#define FF_ARRAY_ELEMS(a)
uint8_t * data
The data buffer.
Definition buffer.h:90
This struct is allocated as AVHWDeviceContext.hwctx.
AVCUDADeviceContextInternal * internal
Describe the class of an AVClass context structure.
Definition log.h:76
char * key
Definition dict.h:91
char * value
Definition dict.h:92
An instance of a filter.
Definition avfilter.h:273
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition frame.h:723
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition pixdesc.h:71
Frame sync structure.
Definition framesync.h:168
unsigned frame_cnt
Definition vf_libvmaf.c:62
FFFrameSync fs
Definition vf_libvmaf.c:51
char * model_cfg
Definition vf_libvmaf.c:57
unsigned model_cnt
Definition vf_libvmaf.c:61
char * log_path
Definition vf_libvmaf.c:52
VmafModel ** model
Definition vf_libvmaf.c:60
char * feature_cfg
Definition vf_libvmaf.c:58
unsigned bpc
Definition vf_libvmaf.c:63
VmafContext * vmaf
Definition vf_libvmaf.c:59
#define av_free(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static int ref[MAX_W *MAX_W]
static enum AVPixelFormat supported_formats[]
static int format_is_supported(enum AVPixelFormat fmt)
static int config_input_ref(AVFilterLink *inlink)
Definition vf_corr.c:287
static enum VmafPoolingMethod pool_method_map(const char *pool_method)
Definition vf_libvmaf.c:540
static int copy_picture_data(AVFrame *src, VmafPicture *dst, unsigned bpc)
Definition vf_libvmaf.c:108
static const AVFilterPad libvmaf_inputs[]
Definition vf_libvmaf.c:600
static int parse_models(AVFilterContext *ctx)
Definition vf_libvmaf.c:279
static int do_vmaf(FFFrameSync *fs)
Definition vf_libvmaf.c:129
static AVDictionary ** delimited_dict_parse(char *str, unsigned *cnt)
Definition vf_libvmaf.c:172
static enum VmafPixelFormat pix_fmt_map(enum AVPixelFormat av_pix_fmt)
Definition vf_libvmaf.c:85
static int config_input_ref(AVFilterLink *inlink)
Definition vf_libvmaf.c:464
static const AVOption libvmaf_options[]
Definition vf_libvmaf.c:72
static enum VmafLogLevel log_level_map(int log_level)
Definition vf_libvmaf.c:411
static int activate(AVFilterContext *ctx)
Definition vf_libvmaf.c:518
static av_cold void uninit(AVFilterContext *ctx)
Definition vf_libvmaf.c:554
static int parse_features(AVFilterContext *ctx)
Definition vf_libvmaf.c:224
#define OFFSET(x)
Definition vf_libvmaf.c:69
static int config_output(AVFilterLink *outlink)
Definition vf_libvmaf.c:495
static enum VmafOutputFormat log_fmt_map(const char *log_fmt)
Definition vf_libvmaf.c:524
static const AVFilterPad libvmaf_outputs[]
Definition vf_libvmaf.c:612