Lines 1-9
Link Here
|
1 |
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html |
1 |
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2022-January/291606.html |
2 |
|
2 |
|
3 |
--- configure.orig 2021-10-24 20:47:11 UTC |
3 |
--- configure.orig 2022-01-14 18:45:39 UTC |
4 |
+++ configure |
4 |
+++ configure |
5 |
@@ -3663,7 +3663,7 @@ uspp_filter_deps="gpl avcodec" |
5 |
@@ -3747,7 +3747,7 @@ vaguedenoiser_filter_deps="gpl" |
6 |
vaguedenoiser_filter_deps="gpl" |
6 |
vflip_vulkan_filter_deps="vulkan spirv_compiler" |
7 |
vidstabdetect_filter_deps="libvidstab" |
7 |
vidstabdetect_filter_deps="libvidstab" |
8 |
vidstabtransform_filter_deps="libvidstab" |
8 |
vidstabtransform_filter_deps="libvidstab" |
9 |
-libvmaf_filter_deps="libvmaf pthreads" |
9 |
-libvmaf_filter_deps="libvmaf pthreads" |
Lines 11-17
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
11 |
zmq_filter_deps="libzmq" |
11 |
zmq_filter_deps="libzmq" |
12 |
zoompan_filter_deps="swscale" |
12 |
zoompan_filter_deps="swscale" |
13 |
zscale_filter_deps="libzimg const_nan" |
13 |
zscale_filter_deps="libzimg const_nan" |
14 |
@@ -6441,7 +6441,7 @@ enabled libtwolame && require libtwolame twolam |
14 |
@@ -6615,7 +6615,7 @@ enabled libtwolame && require libtwolame twolam |
15 |
enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode |
15 |
enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode |
16 |
enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl |
16 |
enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl |
17 |
enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit |
17 |
enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit |
Lines 20-28
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
20 |
enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc |
20 |
enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc |
21 |
enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init && |
21 |
enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init && |
22 |
require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init |
22 |
require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init |
23 |
--- doc/filters.texi.orig 2021-10-24 20:47:07 UTC |
23 |
--- doc/filters.texi.orig 2022-01-14 18:45:39 UTC |
24 |
+++ doc/filters.texi |
24 |
+++ doc/filters.texi |
25 |
@@ -13867,66 +13867,37 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Cano |
25 |
@@ -14666,68 +14666,39 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Cano |
26 |
|
26 |
|
27 |
@section libvmaf |
27 |
@section libvmaf |
28 |
|
28 |
|
Lines 31-36
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
31 |
+Calulate the VMAF (Video Multi-Method Assessment Fusion) score for a |
31 |
+Calulate the VMAF (Video Multi-Method Assessment Fusion) score for a |
32 |
+reference/distorted pair of input videos. |
32 |
+reference/distorted pair of input videos. |
33 |
|
33 |
|
|
|
34 |
-The first input is the encoded video, and the second input is the reference video. |
35 |
+The first input is the distorted video, and the second input is the reference video. |
36 |
|
34 |
The obtained VMAF score is printed through the logging system. |
37 |
The obtained VMAF score is printed through the logging system. |
35 |
|
38 |
|
36 |
It requires Netflix's vmaf library (libvmaf) as a pre-requisite. |
39 |
It requires Netflix's vmaf library (libvmaf) as a pre-requisite. |
Lines 102-108
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
102 |
@end table |
105 |
@end table |
103 |
|
106 |
|
104 |
This filter also supports the @ref{framesync} options. |
107 |
This filter also supports the @ref{framesync} options. |
105 |
@@ -13934,23 +13905,31 @@ This filter also supports the @ref{framesync} options. |
108 |
@@ -14735,23 +14706,31 @@ This filter also supports the @ref{framesync} options. |
106 |
@subsection Examples |
109 |
@subsection Examples |
107 |
@itemize |
110 |
@itemize |
108 |
@item |
111 |
@item |
Lines 140-146
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
140 |
@end example |
143 |
@end example |
141 |
@end itemize |
144 |
@end itemize |
142 |
|
145 |
|
143 |
--- libavfilter/vf_libvmaf.c.orig 2021-10-24 20:47:07 UTC |
146 |
--- libavfilter/vf_libvmaf.c.orig 2022-01-14 18:45:40 UTC |
144 |
+++ libavfilter/vf_libvmaf.c |
147 |
+++ libavfilter/vf_libvmaf.c |
145 |
@@ -24,8 +24,8 @@ |
148 |
@@ -24,8 +24,8 @@ |
146 |
* Calculate the VMAF between two input videos. |
149 |
* Calculate the VMAF between two input videos. |
Lines 152-158
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
152 |
#include "libavutil/avstring.h" |
155 |
#include "libavutil/avstring.h" |
153 |
#include "libavutil/opt.h" |
156 |
#include "libavutil/opt.h" |
154 |
#include "libavutil/pixdesc.h" |
157 |
#include "libavutil/pixdesc.h" |
155 |
@@ -39,211 +39,372 @@ |
158 |
@@ -39,23 +39,9 @@ |
156 |
typedef struct LIBVMAFContext { |
159 |
typedef struct LIBVMAFContext { |
157 |
const AVClass *class; |
160 |
const AVClass *class; |
158 |
FFFrameSync fs; |
161 |
FFFrameSync fs; |
Lines 168-187
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
168 |
- AVFrame *gmain; |
171 |
- AVFrame *gmain; |
169 |
- AVFrame *gref; |
172 |
- AVFrame *gref; |
170 |
- int frame_set; |
173 |
- int frame_set; |
171 |
- char *model_path; |
174 |
char *model_path; |
172 |
char *log_path; |
175 |
char *log_path; |
173 |
char *log_fmt; |
176 |
char *log_fmt; |
174 |
- int disable_clip; |
177 |
- int disable_clip; |
175 |
- int disable_avx; |
178 |
- int disable_avx; |
176 |
- int enable_transform; |
179 |
int enable_transform; |
177 |
- int phone_model; |
180 |
int phone_model; |
178 |
- int psnr; |
181 |
int psnr; |
179 |
- int ssim; |
182 |
@@ -65,185 +51,483 @@ typedef struct LIBVMAFContext { |
180 |
- int ms_ssim; |
|
|
181 |
- char *pool; |
182 |
int n_threads; |
183 |
int n_threads; |
183 |
int n_subsample; |
184 |
int n_subsample; |
184 |
- int enable_conf_interval; |
185 |
int enable_conf_interval; |
185 |
- int error; |
186 |
- int error; |
186 |
+ char *model_cfg; |
187 |
+ char *model_cfg; |
187 |
+ char *feature_cfg; |
188 |
+ char *feature_cfg; |
Lines 204-219
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
204 |
- {"psnr", "Enables computing psnr along with vmaf.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
205 |
- {"psnr", "Enables computing psnr along with vmaf.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
205 |
- {"ssim", "Enables computing ssim along with vmaf.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
206 |
- {"ssim", "Enables computing ssim along with vmaf.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
206 |
- {"ms_ssim", "Enables computing ms-ssim along with vmaf.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
207 |
- {"ms_ssim", "Enables computing ms-ssim along with vmaf.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
207 |
- {"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, |
208 |
+ {"model_path", "use model='path=...'.", OFFSET(model_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, |
208 |
- {"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}, |
209 |
+ {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, |
209 |
- {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, |
210 |
+ {"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}, |
|
|
211 |
+ {"enable_transform", "use model='enable_transform=true'.", OFFSET(enable_transform), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, |
212 |
+ {"phone_model", "use model='enable_transform=true'.", OFFSET(phone_model), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, |
213 |
+ {"psnr", "use feature='name=psnr'.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, |
214 |
+ {"ssim", "use feature='name=ssim'.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, |
215 |
+ {"ms_ssim", "use feature='name=ms_ssim'.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, |
216 |
{"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, |
217 |
{"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}, |
218 |
{"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, |
210 |
- {"enable_conf_interval", "Enables confidence interval.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
219 |
- {"enable_conf_interval", "Enables confidence interval.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
211 |
+ {"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}, |
220 |
+ {"enable_conf_interval", "Enables confidence interval.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, |
212 |
+ {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, |
221 |
+ {"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}, |
213 |
+ {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, |
222 |
+ {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, |
214 |
+ {"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}, |
|
|
215 |
+ {"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}, |
216 |
+ {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, |
217 |
{ NULL } |
223 |
{ NULL } |
218 |
}; |
224 |
}; |
219 |
|
225 |
|
Lines 309-315
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
309 |
+{ |
315 |
+{ |
310 |
+ int err = vmaf_picture_alloc(dst, pix_fmt_map(src->format), bpc, |
316 |
+ int err = vmaf_picture_alloc(dst, pix_fmt_map(src->format), bpc, |
311 |
+ src->width, src->height); |
317 |
+ src->width, src->height); |
312 |
+ if (err) return AVERROR(ENOMEM); |
318 |
+ if (err) |
|
|
319 |
+ return AVERROR(ENOMEM); |
313 |
|
320 |
|
314 |
-static void compute_vmaf_score(LIBVMAFContext *s) |
321 |
-static void compute_vmaf_score(LIBVMAFContext *s) |
315 |
+ for (unsigned i = 0; i < 3; i++) { |
322 |
+ for (unsigned i = 0; i < 3; i++) { |
Lines 332-337
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
332 |
- char *format; |
339 |
- char *format; |
333 |
+ AVFilterContext *ctx = fs->parent; |
340 |
+ AVFilterContext *ctx = fs->parent; |
334 |
+ LIBVMAFContext *s = ctx->priv; |
341 |
+ LIBVMAFContext *s = ctx->priv; |
|
|
342 |
+ VmafPicture pic_ref, pic_dist; |
335 |
+ AVFrame *ref, *dist; |
343 |
+ AVFrame *ref, *dist; |
336 |
+ int err = 0; |
344 |
+ int err = 0; |
337 |
|
345 |
|
Lines 345-351
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
345 |
+ if (ctx->is_disabled || !ref) |
353 |
+ if (ctx->is_disabled || !ref) |
346 |
+ return ff_filter_frame(ctx->outputs[0], dist); |
354 |
+ return ff_filter_frame(ctx->outputs[0], dist); |
347 |
+ |
355 |
+ |
348 |
+ VmafPicture pic_ref; |
|
|
349 |
+ err = copy_picture_data(ref, &pic_ref, s->bpc); |
356 |
+ err = copy_picture_data(ref, &pic_ref, s->bpc); |
350 |
+ if (err) { |
357 |
+ if (err) { |
351 |
+ av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); |
358 |
+ av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); |
Lines 353-359
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
353 |
} |
360 |
} |
354 |
|
361 |
|
355 |
- format = (char *) s->desc->name; |
362 |
- format = (char *) s->desc->name; |
356 |
+ VmafPicture pic_dist; |
|
|
357 |
+ err = copy_picture_data(dist, &pic_dist, s->bpc); |
363 |
+ err = copy_picture_data(dist, &pic_dist, s->bpc); |
358 |
+ if (err) { |
364 |
+ if (err) { |
359 |
+ av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); |
365 |
+ av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); |
Lines 387-394
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
387 |
- pthread_mutex_lock(&s->lock); |
393 |
- pthread_mutex_lock(&s->lock); |
388 |
- pthread_cond_signal(&s->cond); |
394 |
- pthread_cond_signal(&s->cond); |
389 |
- pthread_mutex_unlock(&s->lock); |
395 |
- pthread_mutex_unlock(&s->lock); |
|
|
396 |
+ AVDictionary **dict = NULL; |
397 |
+ char *str_copy = NULL; |
398 |
+ char *saveptr = NULL; |
390 |
+ int err = 0; |
399 |
+ int err = 0; |
391 |
+ if (!str) return NULL; |
400 |
+ |
|
|
401 |
+ if (!str) |
402 |
+ return NULL; |
392 |
+ |
403 |
+ |
393 |
+ *cnt = 1; |
404 |
+ *cnt = 1; |
394 |
+ for (char *p = str; *p; p++) { |
405 |
+ for (char *p = str; *p; p++) { |
Lines 397-413
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
397 |
} |
408 |
} |
398 |
- pthread_exit(NULL); |
409 |
- pthread_exit(NULL); |
399 |
+ |
410 |
+ |
400 |
+ AVDictionary **dict = av_calloc(*cnt, sizeof(*dict)); |
411 |
+ dict = av_calloc(*cnt, sizeof(*dict)); |
401 |
+ if (!dict) goto fail; |
412 |
+ if (!dict) |
|
|
413 |
+ goto fail; |
402 |
+ |
414 |
+ |
403 |
+ char *str_copy = av_strdup(str); |
415 |
+ str_copy = av_strdup(str); |
404 |
+ if (!str_copy) goto fail; |
416 |
+ if (!str_copy) |
|
|
417 |
+ goto fail; |
405 |
+ |
418 |
+ |
406 |
+ char *saveptr = NULL; |
|
|
407 |
+ for (unsigned i = 0; i < *cnt; i++) { |
419 |
+ for (unsigned i = 0; i < *cnt; i++) { |
408 |
+ char *s = av_strtok(i == 0 ? str_copy : NULL, "|", &saveptr); |
420 |
+ char *s = av_strtok(i == 0 ? str_copy : NULL, "|", &saveptr); |
409 |
+ err = av_dict_parse_string(&dict[i], s, "=", ":", 0); |
421 |
+ err = av_dict_parse_string(&dict[i], s, "=", ":", 0); |
410 |
+ if (err) goto fail; |
422 |
+ if (err) |
|
|
423 |
+ goto fail; |
411 |
+ } |
424 |
+ } |
412 |
+ |
425 |
+ |
413 |
+ av_free(str_copy); |
426 |
+ av_free(str_copy); |
Lines 421-428
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
421 |
+ } |
434 |
+ } |
422 |
+ av_free(dict); |
435 |
+ av_free(dict); |
423 |
+ } |
436 |
+ } |
424 |
+ if (str_copy) |
437 |
+ |
425 |
+ av_free(str_copy); |
438 |
+ av_free(str_copy); |
426 |
+ *cnt = 0; |
439 |
+ *cnt = 0; |
427 |
return NULL; |
440 |
return NULL; |
428 |
} |
441 |
} |
Lines 434-451
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
434 |
LIBVMAFContext *s = ctx->priv; |
447 |
LIBVMAFContext *s = ctx->priv; |
435 |
- AVFrame *master, *ref; |
448 |
- AVFrame *master, *ref; |
436 |
- int ret; |
449 |
- int ret; |
437 |
+ if (!s->feature_cfg) return 0; |
450 |
+ AVDictionary **dict = NULL; |
|
|
451 |
+ unsigned dict_cnt; |
452 |
+ int err = 0; |
438 |
|
453 |
|
439 |
- ret = ff_framesync_dualinput_get(fs, &master, &ref); |
454 |
- ret = ff_framesync_dualinput_get(fs, &master, &ref); |
440 |
- if (ret < 0) |
455 |
- if (ret < 0) |
441 |
- return ret; |
456 |
- return ret; |
442 |
- if (!ref) |
457 |
- if (!ref) |
443 |
- return ff_filter_frame(ctx->outputs[0], master); |
458 |
- return ff_filter_frame(ctx->outputs[0], master); |
444 |
+ int err = 0; |
459 |
+ if (!s->feature_cfg) |
|
|
460 |
+ return 0; |
445 |
|
461 |
|
446 |
- pthread_mutex_lock(&s->lock); |
462 |
- pthread_mutex_lock(&s->lock); |
447 |
+ unsigned dict_cnt = 0; |
463 |
+ dict = delimited_dict_parse(s->feature_cfg, &dict_cnt); |
448 |
+ AVDictionary **dict = delimited_dict_parse(s->feature_cfg, &dict_cnt); |
|
|
449 |
+ if (!dict) { |
464 |
+ if (!dict) { |
450 |
+ av_log(ctx, AV_LOG_ERROR, |
465 |
+ av_log(ctx, AV_LOG_ERROR, |
451 |
+ "could not parse feature config: %s\n", s->feature_cfg); |
466 |
+ "could not parse feature config: %s\n", s->feature_cfg); |
Lines 496-507
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
496 |
+static int parse_models(AVFilterContext *ctx) |
511 |
+static int parse_models(AVFilterContext *ctx) |
497 |
+{ |
512 |
+{ |
498 |
+ LIBVMAFContext *s = ctx->priv; |
513 |
+ LIBVMAFContext *s = ctx->priv; |
499 |
+ if (!s->model_cfg) return 0; |
514 |
+ AVDictionary **dict; |
500 |
+ |
515 |
+ unsigned dict_cnt; |
501 |
+ int err = 0; |
516 |
+ int err = 0; |
502 |
+ |
517 |
+ |
503 |
+ unsigned dict_cnt = 0; |
518 |
+ if (!s->model_cfg) return 0; |
504 |
+ AVDictionary **dict = delimited_dict_parse(s->model_cfg, &dict_cnt); |
519 |
+ |
|
|
520 |
+ dict_cnt = 0; |
521 |
+ dict = delimited_dict_parse(s->model_cfg, &dict_cnt); |
505 |
+ if (!dict) { |
522 |
+ if (!dict) { |
506 |
av_log(ctx, AV_LOG_ERROR, |
523 |
av_log(ctx, AV_LOG_ERROR, |
507 |
- "libvmaf encountered an error, check log for details\n"); |
524 |
- "libvmaf encountered an error, check log for details\n"); |
Lines 514-526
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
514 |
- av_frame_ref(s->gmain, master); |
531 |
- av_frame_ref(s->gmain, master); |
515 |
+ s->model_cnt = dict_cnt; |
532 |
+ s->model_cnt = dict_cnt; |
516 |
+ s->model = av_calloc(s->model_cnt, sizeof(*s->model)); |
533 |
+ s->model = av_calloc(s->model_cnt, sizeof(*s->model)); |
517 |
+ if (!s->model) return AVERROR(ENOMEM); |
534 |
+ if (!s->model) |
|
|
535 |
+ return AVERROR(ENOMEM); |
518 |
|
536 |
|
519 |
- s->frame_set = 1; |
537 |
- s->frame_set = 1; |
520 |
+ for (unsigned i = 0; i < dict_cnt; i++) { |
538 |
+ for (unsigned i = 0; i < dict_cnt; i++) { |
521 |
+ VmafModelConfig model_cfg = {0}; |
539 |
+ VmafModelConfig model_cfg = { 0 }; |
522 |
+ AVDictionaryEntry *e = NULL; |
540 |
+ AVDictionaryEntry *e = NULL; |
523 |
+ char *version, *path; |
541 |
+ char *version = NULL; |
|
|
542 |
+ char *path = NULL; |
524 |
|
543 |
|
525 |
- pthread_cond_signal(&s->cond); |
544 |
- pthread_cond_signal(&s->cond); |
526 |
- pthread_mutex_unlock(&s->lock); |
545 |
- pthread_mutex_unlock(&s->lock); |
Lines 569-575
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
569 |
+ if (err) { |
588 |
+ if (err) { |
570 |
+ av_log(ctx, AV_LOG_ERROR, |
589 |
+ av_log(ctx, AV_LOG_ERROR, |
571 |
+ "could not load libvmaf model with path: %s\n", |
590 |
+ "could not load libvmaf model with path: %s\n", |
572 |
+ e->value); |
591 |
+ path); |
573 |
+ goto exit; |
592 |
+ goto exit; |
574 |
+ } |
593 |
+ } |
575 |
+ } |
594 |
+ } |
Lines 581-593
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
581 |
+ goto exit; |
600 |
+ goto exit; |
582 |
+ } |
601 |
+ } |
583 |
+ |
602 |
+ |
584 |
+ e = NULL; |
|
|
585 |
+ while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { |
603 |
+ while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { |
|
|
604 |
+ VmafFeatureDictionary *feature_opts_dict = NULL; |
586 |
+ char *feature_opt = NULL; |
605 |
+ char *feature_opt = NULL; |
|
|
606 |
+ |
587 |
+ char *feature_name = av_strtok(e->key, ".", &feature_opt); |
607 |
+ char *feature_name = av_strtok(e->key, ".", &feature_opt); |
588 |
+ if (!feature_opt) continue; |
608 |
+ if (!feature_opt) |
|
|
609 |
+ continue; |
589 |
+ |
610 |
+ |
590 |
+ VmafFeatureDictionary *feature_opts_dict = NULL; |
|
|
591 |
+ err = vmaf_feature_dictionary_set(&feature_opts_dict, |
611 |
+ err = vmaf_feature_dictionary_set(&feature_opts_dict, |
592 |
+ feature_opt, e->value); |
612 |
+ feature_opt, e->value); |
593 |
+ if (err) { |
613 |
+ if (err) { |
Lines 645-650
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
645 |
+ return VMAF_LOG_LEVEL_INFO; |
665 |
+ return VMAF_LOG_LEVEL_INFO; |
646 |
+ } |
666 |
+ } |
647 |
+} |
667 |
+} |
|
|
668 |
+ |
669 |
+static int parse_deprecated_options(AVFilterContext *ctx) |
670 |
+{ |
671 |
+ LIBVMAFContext *s = ctx->priv; |
672 |
+ VmafModel *model = NULL; |
673 |
+ VmafModelCollection *model_collection = NULL; |
674 |
+ enum VmafModelFlags flags = VMAF_MODEL_FLAGS_DEFAULT; |
675 |
+ int err = 0; |
676 |
+ |
677 |
+ VmafModelConfig model_cfg = { |
678 |
+ .name = "vmaf", |
679 |
+ .flags = flags, |
680 |
+ }; |
681 |
+ |
682 |
+ if (s->enable_transform || s->phone_model) |
683 |
+ flags |= VMAF_MODEL_FLAG_ENABLE_TRANSFORM; |
684 |
+ |
685 |
+ if (!s->model_path) |
686 |
+ goto extra_metrics_only; |
687 |
+ |
688 |
+ if (s->enable_conf_interval) { |
689 |
+ err = vmaf_model_collection_load_from_path(&model, &model_collection, |
690 |
+ &model_cfg, s->model_path); |
691 |
+ if (err) { |
692 |
+ av_log(ctx, AV_LOG_ERROR, |
693 |
+ "problem loading model file: %s\n", s->model_path); |
694 |
+ goto exit; |
695 |
+ } |
696 |
+ |
697 |
+ err = vmaf_use_features_from_model_collection(s->vmaf, model_collection); |
698 |
+ if (err) { |
699 |
+ av_log(ctx, AV_LOG_ERROR, |
700 |
+ "problem loading feature extractors from model file: %s\n", |
701 |
+ s->model_path); |
702 |
+ goto exit; |
703 |
+ } |
704 |
+ } else { |
705 |
+ err = vmaf_model_load_from_path(&model, &model_cfg, s->model_path); |
706 |
+ if (err) { |
707 |
+ av_log(ctx, AV_LOG_ERROR, |
708 |
+ "problem loading model file: %s\n", s->model_path); |
709 |
+ goto exit; |
710 |
+ } |
711 |
+ err = vmaf_use_features_from_model(s->vmaf, model); |
712 |
+ if (err) { |
713 |
+ av_log(ctx, AV_LOG_ERROR, |
714 |
+ "problem loading feature extractors from model file: %s\n", |
715 |
+ s->model_path); |
716 |
+ goto exit; |
717 |
+ } |
718 |
+ } |
719 |
+ |
720 |
+extra_metrics_only: |
721 |
+ if (s->psnr) { |
722 |
+ VmafFeatureDictionary *d = NULL; |
723 |
+ vmaf_feature_dictionary_set(&d, "enable_chroma", "false"); |
724 |
+ |
725 |
+ err = vmaf_use_feature(s->vmaf, "psnr", d); |
726 |
+ if (err) { |
727 |
+ av_log(ctx, AV_LOG_ERROR, |
728 |
+ "problem loading feature extractor: psnr\n"); |
729 |
+ goto exit; |
730 |
+ } |
731 |
+ } |
732 |
+ |
733 |
+ if (s->ssim) { |
734 |
+ err = vmaf_use_feature(s->vmaf, "float_ssim", NULL); |
735 |
+ if (err) { |
736 |
+ av_log(ctx, AV_LOG_ERROR, |
737 |
+ "problem loading feature extractor: ssim\n"); |
738 |
+ goto exit; |
739 |
+ } |
740 |
+ } |
741 |
+ |
742 |
+ if (s->ms_ssim) { |
743 |
+ err = vmaf_use_feature(s->vmaf, "float_ms_ssim", NULL); |
744 |
+ if (err) { |
745 |
+ av_log(ctx, AV_LOG_ERROR, |
746 |
+ "problem loading feature extractor: ms_ssim\n"); |
747 |
+ goto exit; |
748 |
+ } |
749 |
+ } |
750 |
+ |
751 |
+exit: |
752 |
+ return err; |
753 |
+} |
648 |
+ |
754 |
+ |
649 |
static av_cold int init(AVFilterContext *ctx) |
755 |
static av_cold int init(AVFilterContext *ctx) |
650 |
{ |
756 |
{ |
Lines 663-746
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
663 |
|
769 |
|
664 |
- s->error = 0; |
770 |
- s->error = 0; |
665 |
+ err = vmaf_init(&s->vmaf, cfg); |
771 |
+ err = vmaf_init(&s->vmaf, cfg); |
666 |
+ if (err) return AVERROR(EINVAL); |
772 |
+ if (err) |
|
|
773 |
+ return AVERROR(EINVAL); |
667 |
|
774 |
|
668 |
- s->vmaf_thread_created = 0; |
775 |
- s->vmaf_thread_created = 0; |
669 |
- pthread_mutex_init(&s->lock, NULL); |
776 |
- pthread_mutex_init(&s->lock, NULL); |
670 |
- pthread_cond_init (&s->cond, NULL); |
777 |
- pthread_cond_init (&s->cond, NULL); |
671 |
+ err = parse_models(ctx); |
778 |
+ err = parse_deprecated_options(ctx); |
672 |
+ if (err) return err; |
779 |
+ if (err) |
|
|
780 |
+ return err; |
673 |
|
781 |
|
|
|
782 |
+ err = parse_models(ctx); |
783 |
+ if (err) |
784 |
+ return err; |
785 |
+ |
674 |
+ err = parse_features(ctx); |
786 |
+ err = parse_features(ctx); |
675 |
+ if (err) return err; |
787 |
+ if (err) |
|
|
788 |
+ return err; |
676 |
+ |
789 |
+ |
677 |
s->fs.on_event = do_vmaf; |
790 |
s->fs.on_event = do_vmaf; |
678 |
return 0; |
791 |
return 0; |
679 |
} |
792 |
} |
680 |
@@ -251,8 +412,9 @@ static av_cold int init(AVFilterContext *ctx) |
793 |
@@ -256,27 +540,32 @@ static const enum AVPixelFormat pix_fmts[] = { |
681 |
static int query_formats(AVFilterContext *ctx) |
|
|
682 |
{ |
683 |
static const enum AVPixelFormat pix_fmts[] = { |
684 |
- AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, |
685 |
- AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUV420P10LE, |
686 |
+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16LE, |
687 |
+ AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P16LE, |
688 |
+ AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P16LE, |
689 |
AV_PIX_FMT_NONE |
690 |
}; |
691 |
|
692 |
@@ -262,33 +424,32 @@ static int query_formats(AVFilterContext *ctx) |
693 |
return ff_set_common_formats(ctx, fmts_list); |
694 |
} |
695 |
|
794 |
|
696 |
- |
|
|
697 |
static int config_input_ref(AVFilterLink *inlink) |
795 |
static int config_input_ref(AVFilterLink *inlink) |
698 |
{ |
796 |
{ |
699 |
- AVFilterContext *ctx = inlink->dst; |
797 |
- AVFilterContext *ctx = inlink->dst; |
700 |
+ AVFilterContext *ctx = inlink->dst; |
798 |
+ AVFilterContext *ctx = inlink->dst; |
701 |
LIBVMAFContext *s = ctx->priv; |
799 |
LIBVMAFContext *s = ctx->priv; |
702 |
- int th; |
800 |
- int th; |
|
|
801 |
+ const AVPixFmtDescriptor *desc; |
802 |
+ int err = 0; |
703 |
|
803 |
|
704 |
- if (ctx->inputs[0]->w != ctx->inputs[1]->w || |
804 |
- if (ctx->inputs[0]->w != ctx->inputs[1]->w || |
705 |
- ctx->inputs[0]->h != ctx->inputs[1]->h) { |
805 |
- ctx->inputs[0]->h != ctx->inputs[1]->h) { |
706 |
- av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n"); |
806 |
- av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n"); |
707 |
- return AVERROR(EINVAL); |
807 |
- return AVERROR(EINVAL); |
708 |
+ int err = 0; |
|
|
709 |
+ |
710 |
+ if (ctx->inputs[0]->w != ctx->inputs[1]->w) { |
808 |
+ if (ctx->inputs[0]->w != ctx->inputs[1]->w) { |
711 |
+ av_log(ctx, AV_LOG_ERROR, "input width must match.\n"); |
809 |
+ av_log(ctx, AV_LOG_ERROR, "input width must match.\n"); |
712 |
+ err |= AVERROR(EINVAL); |
|
|
713 |
} |
714 |
+ |
715 |
+ if (ctx->inputs[0]->h != ctx->inputs[1]->h) { |
716 |
+ av_log(ctx, AV_LOG_ERROR, "input height must match.\n"); |
717 |
+ err |= AVERROR(EINVAL); |
718 |
+ } |
719 |
+ |
720 |
if (ctx->inputs[0]->format != ctx->inputs[1]->format) { |
721 |
- av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n"); |
722 |
- return AVERROR(EINVAL); |
723 |
+ av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n"); |
724 |
+ err |= AVERROR(EINVAL); |
810 |
+ err |= AVERROR(EINVAL); |
725 |
} |
811 |
} |
726 |
|
812 |
|
727 |
- s->desc = av_pix_fmt_desc_get(inlink->format); |
813 |
- s->desc = av_pix_fmt_desc_get(inlink->format); |
728 |
- s->width = ctx->inputs[0]->w; |
814 |
- s->width = ctx->inputs[0]->w; |
729 |
- s->height = ctx->inputs[0]->h; |
815 |
- s->height = ctx->inputs[0]->h; |
730 |
+ if (err) return err; |
816 |
+ if (ctx->inputs[0]->h != ctx->inputs[1]->h) { |
|
|
817 |
+ av_log(ctx, AV_LOG_ERROR, "input height must match.\n"); |
818 |
+ err |= AVERROR(EINVAL); |
819 |
+ } |
731 |
|
820 |
|
732 |
- th = pthread_create(&s->vmaf_thread, NULL, call_vmaf, (void *) s); |
821 |
- th = pthread_create(&s->vmaf_thread, NULL, call_vmaf, (void *) s); |
733 |
- if (th) { |
822 |
- if (th) { |
734 |
- av_log(ctx, AV_LOG_ERROR, "Thread creation failed.\n"); |
823 |
- av_log(ctx, AV_LOG_ERROR, "Thread creation failed.\n"); |
735 |
- return AVERROR(EINVAL); |
824 |
- return AVERROR(EINVAL); |
736 |
- } |
825 |
+ if (ctx->inputs[0]->format != ctx->inputs[1]->format) { |
|
|
826 |
+ av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n"); |
827 |
+ err |= AVERROR(EINVAL); |
828 |
} |
737 |
- s->vmaf_thread_created = 1; |
829 |
- s->vmaf_thread_created = 1; |
738 |
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); |
|
|
739 |
+ s->bpc = desc->comp[0].depth; |
740 |
|
830 |
|
|
|
831 |
+ if (err) |
832 |
+ return err; |
833 |
+ |
834 |
+ desc = av_pix_fmt_desc_get(inlink->format); |
835 |
+ s->bpc = desc->comp[0].depth; |
836 |
+ |
741 |
return 0; |
837 |
return 0; |
742 |
} |
838 |
} |
743 |
@@ -320,35 +481,72 @@ static int activate(AVFilterContext *ctx) |
839 |
|
|
|
840 |
@@ -307,28 +596,76 @@ static int activate(AVFilterContext *ctx) |
744 |
return ff_framesync_activate(&s->fs); |
841 |
return ff_framesync_activate(&s->fs); |
745 |
} |
842 |
} |
746 |
|
843 |
|
Lines 757-776
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
757 |
+ |
854 |
+ |
758 |
+ return VMAF_OUTPUT_FORMAT_XML; |
855 |
+ return VMAF_OUTPUT_FORMAT_XML; |
759 |
+} |
856 |
+} |
|
|
857 |
+ |
858 |
+static enum VmafPoolingMethod pool_method_map(const char *pool_method) |
859 |
+{ |
860 |
+ if (av_stristr(pool_method, "min")) |
861 |
+ return VMAF_POOL_METHOD_MIN; |
862 |
+ if (av_stristr(pool_method, "mean")) |
863 |
+ return VMAF_POOL_METHOD_MEAN; |
864 |
+ if (av_stristr(pool_method, "harmonic_mean")) |
865 |
+ return VMAF_POOL_METHOD_HARMONIC_MEAN; |
866 |
+ |
867 |
+ return VMAF_POOL_METHOD_MEAN; |
868 |
+} |
760 |
+ |
869 |
+ |
761 |
static av_cold void uninit(AVFilterContext *ctx) |
870 |
static av_cold void uninit(AVFilterContext *ctx) |
762 |
{ |
871 |
{ |
763 |
LIBVMAFContext *s = ctx->priv; |
872 |
LIBVMAFContext *s = ctx->priv; |
764 |
|
|
|
765 |
+ int err = 0; |
873 |
+ int err = 0; |
766 |
+ |
874 |
|
767 |
ff_framesync_uninit(&s->fs); |
875 |
ff_framesync_uninit(&s->fs); |
768 |
|
876 |
|
769 |
- pthread_mutex_lock(&s->lock); |
877 |
- pthread_mutex_lock(&s->lock); |
770 |
- s->eof = 1; |
878 |
- s->eof = 1; |
771 |
- pthread_cond_signal(&s->cond); |
879 |
- pthread_cond_signal(&s->cond); |
772 |
- pthread_mutex_unlock(&s->lock); |
880 |
- pthread_mutex_unlock(&s->lock); |
773 |
+ if (!s->frame_cnt) goto clean_up; |
881 |
+ if (!s->frame_cnt) |
|
|
882 |
+ goto clean_up; |
774 |
|
883 |
|
775 |
- if (s->vmaf_thread_created) |
884 |
- if (s->vmaf_thread_created) |
776 |
- { |
885 |
- { |
Lines 786-792
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
786 |
- av_frame_free(&s->gmain); |
895 |
- av_frame_free(&s->gmain); |
787 |
+ for (unsigned i = 0; i < s->model_cnt; i++) { |
896 |
+ for (unsigned i = 0; i < s->model_cnt; i++) { |
788 |
+ double vmaf_score; |
897 |
+ double vmaf_score; |
789 |
+ err = vmaf_score_pooled(s->vmaf, s->model[i], VMAF_POOL_METHOD_MEAN, |
898 |
+ err = vmaf_score_pooled(s->vmaf, s->model[i], pool_method_map(s->pool), |
790 |
+ &vmaf_score, 0, s->frame_cnt - 1); |
899 |
+ &vmaf_score, 0, s->frame_cnt - 1); |
791 |
+ if (err) { |
900 |
+ if (err) { |
792 |
+ av_log(ctx, AV_LOG_ERROR, |
901 |
+ av_log(ctx, AV_LOG_ERROR, |
Lines 817-828
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html
Link Here
|
817 |
} |
926 |
} |
818 |
|
927 |
|
819 |
static const AVFilterPad libvmaf_inputs[] = { |
928 |
static const AVFilterPad libvmaf_inputs[] = { |
820 |
{ |
|
|
821 |
.name = "main", |
822 |
.type = AVMEDIA_TYPE_VIDEO, |
823 |
- },{ |
824 |
+ }, |
825 |
+ { |
826 |
.name = "reference", |
827 |
.type = AVMEDIA_TYPE_VIDEO, |
828 |
.config_props = config_input_ref, |