git: d8e2f9a0e8e6 - main - multimedia/ffmpeg: switch 5e728b3087b2 to merged version

From: Jan Beich <jbeich_at_FreeBSD.org>
Date: Sun, 06 Mar 2022 10:17:01 UTC
The branch main has been updated by jbeich:

URL: https://cgit.FreeBSD.org/ports/commit/?id=d8e2f9a0e8e618110c4539de4d24f9eeb1852851

commit d8e2f9a0e8e618110c4539de4d24f9eeb1852851
Author:     Jan Beich <jbeich@FreeBSD.org>
AuthorDate: 2022-03-06 08:24:14 +0000
Commit:     Jan Beich <jbeich@FreeBSD.org>
CommitDate: 2022-03-06 10:15:52 +0000

    multimedia/ffmpeg: switch 5e728b3087b2 to merged version
---
 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 15966071adc0..626f08570496 100644
--- a/multimedia/ffmpeg/Makefile
+++ b/multimedia/ffmpeg/Makefile
@@ -2,7 +2,7 @@
 
 PORTNAME=	ffmpeg
 PORTVERSION=	4.4.1
-PORTREVISION=	6
+PORTREVISION=	7
 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,