From nobody Sun Mar 6 14:09:24 2022 X-Original-To: dev-commits-ports-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 26FC919FF8B5; Sun, 6 Mar 2022 14:09:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4KBNkY0Tx9z3QpV; Sun, 6 Mar 2022 14:09:25 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1646575765; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=9+WIMkLKbYDRLFlbUFARxgCP70KpnmYJrtwTVxg7ZT8=; b=FBCKtgJu+NcRYECyxFHpAFRTwti71oBRKiGUcP3pEUIZQvRZ6gTRTH/Yk5UlsKyu5h6WP3 dPb/GpMX/1gei/K+r037Y9g/H2YdAyE2w9rAMmsDeGJ2KN+zQ0627BU0NFP3bOEpE3wwu0 1ES8dYnfgv+RkqKmfzia7kL0TTNIgK9wGAHKMAUbCmRE02Bfurfgwhi3VmbInrakDlDN0V FluI5r4C+hIJEUp7O6GWRbD1Kul9jC0oOMlcXpLPq3vR1AcfJnkbiVu+9TMx+iL8DzQwxQ eE3/uQhSaQyMh8t/ciyuI20aj3UmdAavIYlpwE/SEJvdZQ1cU0JfJb3vduTf0w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E07CC15D96; Sun, 6 Mar 2022 14:09:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 226E9OxJ079015; Sun, 6 Mar 2022 14:09:24 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 226E9OJI079014; Sun, 6 Mar 2022 14:09:24 GMT (envelope-from git) Date: Sun, 6 Mar 2022 14:09:24 GMT Message-Id: <202203061409.226E9OJI079014@gitrepo.freebsd.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-branches@FreeBSD.org From: Jan Beich Subject: git: e2d4c4d6095c - 2022Q1 - multimedia/ffmpeg: switch 5e728b3087b2 to merged version List-Id: Commit messages for all branches of the ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-all@freebsd.org X-BeenThere: dev-commits-ports-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jbeich X-Git-Repository: ports X-Git-Refname: refs/heads/2022Q1 X-Git-Reftype: branch X-Git-Commit: e2d4c4d6095cd646a6da0d24c88835f3a2a94b42 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1646575765; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=9+WIMkLKbYDRLFlbUFARxgCP70KpnmYJrtwTVxg7ZT8=; b=drQarpgXmIC+Tt7q9+Z6UcBWa3t9/EBpDF/cGVLfszclX+S/kbRdITvRN/FTUjPXKeOghc fKWBbEncJTZA7lHh8Aiqr1g+wCG912B6c8lTLxForz0Mp9AUtv19sOM8wmkZnhYp8My7/D khCT0/klMRQ59z9s2x/cUHgszMxFwbvv82UcOznufWba9R+tn8eAGRtEdda66GD3bvLuN7 3SsnP1pSSDBwMB4ZnC3S+KymLHyfWzc/IXMbOmkMxlUvObGCM1skATOWFWe79qJ2GnpLgJ pnS13MX4EUONgm3sKkrfSAIAlOFJTOcfLFFFJD+6IMT7l1xdxauFMAZHmiCh8A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1646575765; a=rsa-sha256; cv=none; b=rKUZ5S7HX5OEWGreHDJFQyvSVvcJfGmGI30Wl+Cy6LVBXvoXau+t0TtV0VJa6PmZfxKgr8 VLRcaFvRaNRUV89q4bqhboteiOO12UNJMxm384WPlX6c8/NjlTMGh+bE2nMWr3vt3lRMYX YywoD+/xysfTi7HYT6hzuGX+lC92lUfE0KiFpugzz3M7JHpUSgl1Cclvmj+nauFFKEj6EI rd+ZQMSeuuBj5e0Kd77oqCMpAgntSUTsjF5CVwEYqCnz9s39hGOFcdLlyEQm4AIGDJ0tS7 LOVmcMMSpxNmvvzQIGECvmg707Tt64IvL/Xn2MnsGkTv8Uc+VkM3nMdATKOJHw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch 2022Q1 has been updated by jbeich: URL: https://cgit.FreeBSD.org/ports/commit/?id=e2d4c4d6095cd646a6da0d24c88835f3a2a94b42 commit e2d4c4d6095cd646a6da0d24c88835f3a2a94b42 Author: Jan Beich AuthorDate: 2022-03-06 08:24:14 +0000 Commit: Jan Beich CommitDate: 2022-03-06 10:17:21 +0000 multimedia/ffmpeg: switch 5e728b3087b2 to merged version (cherry picked from commit d8e2f9a0e8e618110c4539de4d24f9eeb1852851) --- multimedia/ffmpeg/Makefile | 2 +- multimedia/ffmpeg/files/patch-vmaf | 397 ++++++++++++++++++++++++------------- 2 files changed, 261 insertions(+), 138 deletions(-) diff --git a/multimedia/ffmpeg/Makefile b/multimedia/ffmpeg/Makefile index 2428c5f40f57..2391d0ec85a3 100644 --- a/multimedia/ffmpeg/Makefile +++ b/multimedia/ffmpeg/Makefile @@ -2,7 +2,7 @@ PORTNAME= ffmpeg PORTVERSION= 4.4.1 -PORTREVISION= 3 +PORTREVISION= 4 PORTEPOCH= 1 CATEGORIES= multimedia audio net MASTER_SITES= https://ffmpeg.org/releases/ diff --git a/multimedia/ffmpeg/files/patch-vmaf b/multimedia/ffmpeg/files/patch-vmaf index b503561803c1..abe772274d3c 100644 --- a/multimedia/ffmpeg/files/patch-vmaf +++ b/multimedia/ffmpeg/files/patch-vmaf @@ -1,8 +1,8 @@ -https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html +https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/3d29724c008d --- configure.orig 2021-10-24 20:47:11 UTC +++ configure -@@ -3663,7 +3663,7 @@ uspp_filter_deps="gpl avcodec" +@@ -3663,7 +3663,7 @@ vidstabtransform_filter_deps="libvidstab" vaguedenoiser_filter_deps="gpl" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" @@ -11,7 +11,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" -@@ -6441,7 +6441,7 @@ enabled libtwolame && require libtwolame twolam +@@ -6441,7 +6441,7 @@ enabled libvidstab && require_pkg_config libvid enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit @@ -22,7 +22,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init --- doc/filters.texi.orig 2021-10-24 20:47:07 UTC +++ doc/filters.texi -@@ -13867,66 +13867,37 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Cano +@@ -13867,66 +13867,58 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Cano @section libvmaf @@ -41,50 +41,63 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html The filter has following options: @table @option --@item model_path --Set the model path which is to be used for SVM. --Default value: @code{"/usr/local/share/model/vmaf_v0.6.1.pkl"} +@item model +A `|` delimited list of vmaf models. Each model can be configured with a number of parameters. +Default value: @code{"version=vmaf_v0.6.1"} - -+@item feature -+A `|` delimited list of features. Each feature can be configured with a number of parameters. + - @item log_path --Set the file path to be used to store logs. -+Set the file path to be used to store log files. + @item model_path +-Set the model path which is to be used for SVM. +-Default value: @code{"/usr/local/share/model/vmaf_v0.6.1.pkl"} ++Deprecated, use model='path=...'. - @item log_fmt +-@item log_path +-Set the file path to be used to store logs. +- +-@item log_fmt -Set the format of the log file (csv, json or xml). -+Set the format of the log file (xml, json, csv, or sub). - --@item enable_transform +- + @item enable_transform -This option can enable/disable the @code{score_transform} applied to the final predicted VMAF score, -if you have specified score_transform option in the input parameter file passed to @code{run_vmaf_training.py} -Default value: @code{false} -- --@item phone_model ++Deprecated, use model='enable_transform=true'. + + @item phone_model -Invokes the phone model which will generate VMAF scores higher than in the -regular model, which is more suitable for laptop, TV, etc. viewing conditions. -Default value: @code{false} -- --@item psnr ++Deprecated, use model='enable_transform=true'. + ++@item enable_conf_interval ++Deprecated, use model='enable_conf_interval=true'. ++ ++@item feature ++A `|` delimited list of features. Each feature can be configured with a number of parameters. ++ + @item psnr -Enables computing psnr along with vmaf. -Default value: @code{false} -- --@item ssim ++Deprecated, use feature='name=psnr'. + + @item ssim -Enables computing ssim along with vmaf. -Default value: @code{false} -- --@item ms_ssim ++Deprecated, use feature='name=ssim'. + + @item ms_ssim -Enables computing ms_ssim along with vmaf. -Default value: @code{false} -- ++Deprecated, use feature='name=ms_ssim'. + -@item pool -Set the pool method to be used for computing vmaf. -Options are @code{min}, @code{harmonic_mean} or @code{mean} (default). -- ++@item log_path ++Set the file path to be used to store log files. + ++@item log_fmt ++Set the format of the log file (xml, json, csv, or sub). ++ @item n_threads -Set number of threads to be used when computing vmaf. -Default value: @code{0}, which makes use of all available logical processors. @@ -102,7 +115,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html @end table This filter also supports the @ref{framesync} options. -@@ -13934,23 +13905,31 @@ This filter also supports the @ref{framesync} options. +@@ -13934,23 +13926,31 @@ This filter also supports the @ref{framesync} options. @subsection Examples @itemize @item @@ -123,13 +136,13 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html +Example with multiple models: @example -ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf="psnr=1:log_fmt=json" -f null - -+ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='model=version=vmaf_v0.6.1\\:name=vmaf|version=vmaf_v0.6.1neg\\:name=vmaf_neg:log_path=output.xml' -f null - ++ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='model=version=vmaf_v0.6.1\\:name=vmaf|version=vmaf_v0.6.1neg\\:name=vmaf_neg' -f null - @end example @item +Example with multiple addtional features: +@example -+ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='feature=name=psnr|name=ciede:log_path=output.xml' -f null - ++ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='feature=name=psnr|name=ciede' -f null - +@end example + +@item @@ -152,7 +165,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html #include "libavutil/avstring.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" -@@ -39,211 +39,372 @@ +@@ -39,23 +39,9 @@ typedef struct LIBVMAFContext { typedef struct LIBVMAFContext { const AVClass *class; FFFrameSync fs; @@ -168,20 +181,18 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html - AVFrame *gmain; - AVFrame *gref; - int frame_set; -- char *model_path; + char *model_path; char *log_path; char *log_fmt; - int disable_clip; - int disable_avx; -- int enable_transform; -- int phone_model; -- int psnr; -- int ssim; -- int ms_ssim; -- char *pool; + int enable_transform; + int phone_model; + int psnr; +@@ -65,185 +51,488 @@ typedef struct LIBVMAFContext { int n_threads; int n_subsample; -- int enable_conf_interval; + int enable_conf_interval; - int error; + char *model_cfg; + char *feature_cfg; @@ -204,16 +215,21 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html - {"psnr", "Enables computing psnr along with vmaf.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"ssim", "Enables computing ssim along with vmaf.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"ms_ssim", "Enables computing ms-ssim along with vmaf.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, -- {"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, -- {"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}, -- {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, ++ {"model_path", "use model='path=...'.", OFFSET(model_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, ++ {"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}, ++ {"enable_transform", "use model='enable_transform=true'.", OFFSET(enable_transform), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"phone_model", "use model='enable_transform=true'.", OFFSET(phone_model), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"psnr", "use feature='name=psnr'.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"ssim", "use feature='name=ssim'.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"ms_ssim", "use feature='name=ms_ssim'.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, + {"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}, + {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, - {"enable_conf_interval", "Enables confidence interval.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, -+ {"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}, -+ {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, -+ {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, -+ {"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}, -+ {"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}, -+ {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, ++ {"enable_conf_interval", "model='enable_conf_interval=true'.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"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}, ++ {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, { NULL } }; @@ -309,7 +325,8 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html +{ + int err = vmaf_picture_alloc(dst, pix_fmt_map(src->format), bpc, + src->width, src->height); -+ if (err) return AVERROR(ENOMEM); ++ if (err) ++ return AVERROR(ENOMEM); -static void compute_vmaf_score(LIBVMAFContext *s) + for (unsigned i = 0; i < 3; i++) { @@ -332,6 +349,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html - char *format; + AVFilterContext *ctx = fs->parent; + LIBVMAFContext *s = ctx->priv; ++ VmafPicture pic_ref, pic_dist; + AVFrame *ref, *dist; + int err = 0; @@ -345,7 +363,6 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html + if (ctx->is_disabled || !ref) + return ff_filter_frame(ctx->outputs[0], dist); + -+ VmafPicture pic_ref; + err = copy_picture_data(ref, &pic_ref, s->bpc); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); @@ -353,7 +370,6 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html } - format = (char *) s->desc->name; -+ VmafPicture pic_dist; + err = copy_picture_data(dist, &pic_dist, s->bpc); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); @@ -377,6 +393,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html } -static void *call_vmaf(void *ctx) ++ +static AVDictionary **delimited_dict_parse(char *str, unsigned *cnt) { - LIBVMAFContext *s = (LIBVMAFContext *) ctx; @@ -387,27 +404,38 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html - pthread_mutex_lock(&s->lock); - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); ++ AVDictionary **dict = NULL; ++ char *str_copy = NULL; ++ char *saveptr = NULL; ++ unsigned cnt2; + int err = 0; -+ if (!str) return NULL; + -+ *cnt = 1; ++ if (!str) ++ return NULL; ++ ++ cnt2 = 1; + for (char *p = str; *p; p++) { + if (*p == '|') -+ (*cnt)++; ++ cnt2++; } - pthread_exit(NULL); + -+ AVDictionary **dict = av_calloc(*cnt, sizeof(*dict)); -+ if (!dict) goto fail; ++ dict = av_calloc(cnt2, sizeof(*dict)); ++ if (!dict) ++ goto fail; + -+ char *str_copy = av_strdup(str); -+ if (!str_copy) goto fail; ++ str_copy = av_strdup(str); ++ if (!str_copy) ++ goto fail; + -+ char *saveptr = NULL; -+ for (unsigned i = 0; i < *cnt; i++) { ++ *cnt = 0; ++ for (unsigned i = 0; i < cnt2; i++) { + char *s = av_strtok(i == 0 ? str_copy : NULL, "|", &saveptr); -+ err = av_dict_parse_string(&dict[i], s, "=", ":", 0); -+ if (err) goto fail; ++ if (!s) ++ continue; ++ err = av_dict_parse_string(&dict[(*cnt)++], s, "=", ":", 0); ++ if (err) ++ goto fail; + } + + av_free(str_copy); @@ -421,8 +449,8 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html + } + av_free(dict); + } -+ if (str_copy) -+ av_free(str_copy); ++ ++ av_free(str_copy); + *cnt = 0; return NULL; } @@ -434,18 +462,20 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html LIBVMAFContext *s = ctx->priv; - AVFrame *master, *ref; - int ret; -+ if (!s->feature_cfg) return 0; ++ AVDictionary **dict = NULL; ++ unsigned dict_cnt; ++ int err = 0; - ret = ff_framesync_dualinput_get(fs, &master, &ref); - if (ret < 0) - return ret; - if (!ref) - return ff_filter_frame(ctx->outputs[0], master); -+ int err = 0; ++ if (!s->feature_cfg) ++ return 0; - pthread_mutex_lock(&s->lock); -+ unsigned dict_cnt = 0; -+ AVDictionary **dict = delimited_dict_parse(s->feature_cfg, &dict_cnt); ++ dict = delimited_dict_parse(s->feature_cfg, &dict_cnt); + if (!dict) { + av_log(ctx, AV_LOG_ERROR, + "could not parse feature config: %s\n", s->feature_cfg); @@ -496,12 +526,14 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html +static int parse_models(AVFilterContext *ctx) +{ + LIBVMAFContext *s = ctx->priv; -+ if (!s->model_cfg) return 0; -+ ++ AVDictionary **dict; ++ unsigned dict_cnt; + int err = 0; + -+ unsigned dict_cnt = 0; -+ AVDictionary **dict = delimited_dict_parse(s->model_cfg, &dict_cnt); ++ if (!s->model_cfg) return 0; ++ ++ dict_cnt = 0; ++ dict = delimited_dict_parse(s->model_cfg, &dict_cnt); + if (!dict) { av_log(ctx, AV_LOG_ERROR, - "libvmaf encountered an error, check log for details\n"); @@ -514,13 +546,15 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html - av_frame_ref(s->gmain, master); + s->model_cnt = dict_cnt; + s->model = av_calloc(s->model_cnt, sizeof(*s->model)); -+ if (!s->model) return AVERROR(ENOMEM); ++ if (!s->model) ++ return AVERROR(ENOMEM); - s->frame_set = 1; + for (unsigned i = 0; i < dict_cnt; i++) { -+ VmafModelConfig model_cfg = {0}; ++ VmafModelConfig model_cfg = { 0 }; + AVDictionaryEntry *e = NULL; -+ char *version, *path; ++ char *version = NULL; ++ char *path = NULL; - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); @@ -569,7 +603,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not load libvmaf model with path: %s\n", -+ e->value); ++ path); + goto exit; + } + } @@ -581,13 +615,14 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html + goto exit; + } + -+ e = NULL; + while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { ++ VmafFeatureDictionary *feature_opts_dict = NULL; + char *feature_opt = NULL; ++ + char *feature_name = av_strtok(e->key, ".", &feature_opt); -+ if (!feature_opt) continue; ++ if (!feature_opt) ++ continue; + -+ VmafFeatureDictionary *feature_opts_dict = NULL; + err = vmaf_feature_dictionary_set(&feature_opts_dict, + feature_opt, e->value); + if (err) { @@ -645,6 +680,92 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html + return VMAF_LOG_LEVEL_INFO; + } +} ++ ++static int parse_deprecated_options(AVFilterContext *ctx) ++{ ++ LIBVMAFContext *s = ctx->priv; ++ VmafModel *model = NULL; ++ VmafModelCollection *model_collection = NULL; ++ enum VmafModelFlags flags = VMAF_MODEL_FLAGS_DEFAULT; ++ int err = 0; ++ ++ VmafModelConfig model_cfg = { ++ .name = "vmaf", ++ .flags = flags, ++ }; ++ ++ if (s->enable_transform || s->phone_model) ++ flags |= VMAF_MODEL_FLAG_ENABLE_TRANSFORM; ++ ++ if (!s->model_path) ++ goto extra_metrics_only; ++ ++ if (s->enable_conf_interval) { ++ err = vmaf_model_collection_load_from_path(&model, &model_collection, ++ &model_cfg, s->model_path); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading model file: %s\n", s->model_path); ++ goto exit; ++ } ++ ++ err = vmaf_use_features_from_model_collection(s->vmaf, model_collection); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractors from model file: %s\n", ++ s->model_path); ++ goto exit; ++ } ++ } else { ++ err = vmaf_model_load_from_path(&model, &model_cfg, s->model_path); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading model file: %s\n", s->model_path); ++ goto exit; ++ } ++ err = vmaf_use_features_from_model(s->vmaf, model); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractors from model file: %s\n", ++ s->model_path); ++ goto exit; ++ } ++ } ++ ++extra_metrics_only: ++ if (s->psnr) { ++ VmafFeatureDictionary *d = NULL; ++ vmaf_feature_dictionary_set(&d, "enable_chroma", "false"); ++ ++ err = vmaf_use_feature(s->vmaf, "psnr", d); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractor: psnr\n"); ++ goto exit; ++ } ++ } ++ ++ if (s->ssim) { ++ err = vmaf_use_feature(s->vmaf, "float_ssim", NULL); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractor: ssim\n"); ++ goto exit; ++ } ++ } ++ ++ if (s->ms_ssim) { ++ err = vmaf_use_feature(s->vmaf, "float_ms_ssim", NULL); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractor: ms_ssim\n"); ++ goto exit; ++ } ++ } ++ ++exit: ++ return err; ++} + static av_cold int init(AVFilterContext *ctx) { @@ -663,114 +784,125 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html - s->error = 0; + err = vmaf_init(&s->vmaf, cfg); -+ if (err) return AVERROR(EINVAL); ++ if (err) ++ return AVERROR(EINVAL); - s->vmaf_thread_created = 0; - pthread_mutex_init(&s->lock, NULL); - pthread_cond_init (&s->cond, NULL); -+ err = parse_models(ctx); -+ if (err) return err; ++ err = parse_deprecated_options(ctx); ++ if (err) ++ return err; ++ err = parse_models(ctx); ++ if (err) ++ return err; ++ + err = parse_features(ctx); -+ if (err) return err; ++ if (err) ++ return err; + s->fs.on_event = do_vmaf; return 0; } -@@ -251,8 +412,9 @@ static av_cold int init(AVFilterContext *ctx) - static int query_formats(AVFilterContext *ctx) - { - static const enum AVPixelFormat pix_fmts[] = { -- AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, -- AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUV420P10LE, -+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16LE, -+ AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P16LE, -+ AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P16LE, - AV_PIX_FMT_NONE - }; - -@@ -262,33 +424,32 @@ static int query_formats(AVFilterContext *ctx) - return ff_set_common_formats(ctx, fmts_list); - } +@@ -265,31 +554,36 @@ static int config_input_ref(AVFilterLink *inlink) -- static int config_input_ref(AVFilterLink *inlink) { - AVFilterContext *ctx = inlink->dst; + AVFilterContext *ctx = inlink->dst; LIBVMAFContext *s = ctx->priv; - int th; ++ const AVPixFmtDescriptor *desc; ++ int err = 0; - if (ctx->inputs[0]->w != ctx->inputs[1]->w || - ctx->inputs[0]->h != ctx->inputs[1]->h) { - av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n"); - return AVERROR(EINVAL); -+ int err = 0; -+ + if (ctx->inputs[0]->w != ctx->inputs[1]->w) { + av_log(ctx, AV_LOG_ERROR, "input width must match.\n"); + err |= AVERROR(EINVAL); } -+ -+ if (ctx->inputs[0]->h != ctx->inputs[1]->h) { -+ av_log(ctx, AV_LOG_ERROR, "input height must match.\n"); -+ err |= AVERROR(EINVAL); -+ } -+ if (ctx->inputs[0]->format != ctx->inputs[1]->format) { -- av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n"); -- return AVERROR(EINVAL); -+ av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n"); -+ err |= AVERROR(EINVAL); + av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n"); + return AVERROR(EINVAL); } - s->desc = av_pix_fmt_desc_get(inlink->format); - s->width = ctx->inputs[0]->w; - s->height = ctx->inputs[0]->h; -+ if (err) return err; ++ if (ctx->inputs[0]->h != ctx->inputs[1]->h) { ++ av_log(ctx, AV_LOG_ERROR, "input height must match.\n"); ++ err |= AVERROR(EINVAL); ++ } - th = pthread_create(&s->vmaf_thread, NULL, call_vmaf, (void *) s); - if (th) { - av_log(ctx, AV_LOG_ERROR, "Thread creation failed.\n"); - return AVERROR(EINVAL); -- } ++ if (ctx->inputs[0]->format != ctx->inputs[1]->format) { ++ av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n"); ++ err |= AVERROR(EINVAL); + } - s->vmaf_thread_created = 1; -+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); -+ s->bpc = desc->comp[0].depth; ++ if (err) ++ return err; ++ ++ desc = av_pix_fmt_desc_get(inlink->format); ++ s->bpc = desc->comp[0].depth; ++ return 0; } -@@ -320,35 +481,72 @@ static int activate(AVFilterContext *ctx) + +@@ -320,28 +614,80 @@ static int activate(AVFilterContext *ctx) return ff_framesync_activate(&s->fs); } +static enum VmafOutputFormat log_fmt_map(const char *log_fmt) +{ -+ if (av_stristr(log_fmt, "xml")) -+ return VMAF_OUTPUT_FORMAT_XML; -+ if (av_stristr(log_fmt, "json")) -+ return VMAF_OUTPUT_FORMAT_JSON; -+ if (av_stristr(log_fmt, "csv")) -+ return VMAF_OUTPUT_FORMAT_CSV; -+ if (av_stristr(log_fmt, "sub")) -+ return VMAF_OUTPUT_FORMAT_SUB; ++ if (log_fmt) { ++ if (av_stristr(log_fmt, "xml")) ++ return VMAF_OUTPUT_FORMAT_XML; ++ if (av_stristr(log_fmt, "json")) ++ return VMAF_OUTPUT_FORMAT_JSON; ++ if (av_stristr(log_fmt, "csv")) ++ return VMAF_OUTPUT_FORMAT_CSV; ++ if (av_stristr(log_fmt, "sub")) ++ return VMAF_OUTPUT_FORMAT_SUB; ++ } + + return VMAF_OUTPUT_FORMAT_XML; +} ++ ++static enum VmafPoolingMethod pool_method_map(const char *pool_method) ++{ ++ if (pool_method) { ++ if (av_stristr(pool_method, "min")) ++ return VMAF_POOL_METHOD_MIN; ++ if (av_stristr(pool_method, "mean")) ++ return VMAF_POOL_METHOD_MEAN; ++ if (av_stristr(pool_method, "harmonic_mean")) ++ return VMAF_POOL_METHOD_HARMONIC_MEAN; ++ } ++ ++ return VMAF_POOL_METHOD_MEAN; ++} + static av_cold void uninit(AVFilterContext *ctx) { LIBVMAFContext *s = ctx->priv; - + int err = 0; -+ + ff_framesync_uninit(&s->fs); - pthread_mutex_lock(&s->lock); - s->eof = 1; - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); -+ if (!s->frame_cnt) goto clean_up; ++ if (!s->frame_cnt) ++ goto clean_up; - if (s->vmaf_thread_created) - { @@ -786,7 +918,7 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html - av_frame_free(&s->gmain); + for (unsigned i = 0; i < s->model_cnt; i++) { + double vmaf_score; -+ err = vmaf_score_pooled(s->vmaf, s->model[i], VMAF_POOL_METHOD_MEAN, ++ err = vmaf_score_pooled(s->vmaf, s->model[i], pool_method_map(s->pool), + &vmaf_score, 0, s->frame_cnt - 1); + if (err) { + av_log(ctx, AV_LOG_ERROR, @@ -817,12 +949,3 @@ https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html } static const AVFilterPad libvmaf_inputs[] = { - { - .name = "main", - .type = AVMEDIA_TYPE_VIDEO, -- },{ -+ }, -+ { - .name = "reference", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_input_ref,