Add new mode tune=vmaf
This mode enables block based video pre-processing, RDO Lagrange
multiplier scaling using VMAF and VMAF motion based Q-index adjustment
to maximize encoder's VMAF performance.
Block based video pre-processing
--------------------------------
Based on the observation that VMAF score can be increased by applying
sharpening filters, we propose this method to pre-process blocks with
different filter strength.
RDO Lagrange multiplier scaling using VMAF
------------------------------------------
Scale the Lagrange multiplier used during the block partition search
stage according to this block's MSE-VMAF curve.
VMAF motion based Q-index adjustment
------------------------------------
A data fitting method is used to calculate the scaling factor of frame's
base Q index based on its VMAF motion score.
How to use it
-------------
1) Install libvmaf (https://github.com/Netflix/vmaf/tree/master/libvmaf)
1.1) Checkout libvmaf (I am in 'a833dc9')
>git clone https://github.com/Netflix/vmaf.git
1.2) Build & install libvmaf
>cd vmaf/libvmaf/
>meson build --buildtype release
>ninja -vC build install
2) Build & run aomenc with tune=vmaf
>cmake path/to/aom/ -DCONFIG_TUNE_VMAF=1
>make -j32
>./aomenc red_kayak_480p.y4m -o output --tune=vmaf
Results (BD-rate improvments)
-----------------------------
Test settings:
VBR, 150 frames, cpu-used=1/3 for midres/hdres, tune=psnr as baseline
tune= vmaf vmaf_with_preprocessing vmaf_without_preprocessing
VMAF VMAF PSNR SSIM VMAF
Hdres -37.90% -35.83% 3.10% 3.71% -4.69%
Midres -29.02% -27.75% 3.74% 4.12% -5.19%
Change-Id: I6ac64fc648ec4fa225b90bc1920658b94a469fac
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 8007ed2..0acaa5d 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -1286,6 +1286,7 @@
AOM_TUNE_DAALA_DIST,
AOM_TUNE_VMAF_WITH_PREPROCESSING,
AOM_TUNE_VMAF_WITHOUT_PREPROCESSING,
+ AOM_TUNE_VMAF_MAX_GAIN
} aom_tune_metric;
#define AOM_MAX_LAYERS 32 /**< Max number of layers */
diff --git a/apps/aomenc.c b/apps/aomenc.c
index 1f814bd..3ca784f 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -396,6 +396,7 @@
#endif
{ "vmaf_with_preprocessing", AOM_TUNE_VMAF_WITH_PREPROCESSING },
{ "vmaf_without_preprocessing", AOM_TUNE_VMAF_WITHOUT_PREPROCESSING },
+ { "vmaf", AOM_TUNE_VMAF_MAX_GAIN },
{ NULL, 0 }
};
static const arg_def_t tune_metric =
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index d5cef3f..8480776 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -502,7 +502,8 @@
#if !CONFIG_TUNE_VMAF
if (extra_cfg->tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
- extra_cfg->tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING) {
+ extra_cfg->tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
+ extra_cfg->tuning == AOM_TUNE_VMAF_MAX_GAIN) {
ERROR(
"This error may be related to the wrong configuration options: try to "
"set -DCONFIG_TUNE_VMAF=1 at the time CMake is run.");
@@ -510,8 +511,7 @@
#endif
#if CONFIG_TUNE_VMAF
- RANGE_CHECK(extra_cfg, tuning, AOM_TUNE_PSNR,
- AOM_TUNE_VMAF_WITHOUT_PREPROCESSING);
+ RANGE_CHECK(extra_cfg, tuning, AOM_TUNE_PSNR, AOM_TUNE_VMAF_MAX_GAIN);
#else
RANGE_CHECK(extra_cfg, tuning, AOM_TUNE_PSNR, AOM_TUNE_SSIM);
#endif
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 3b06cdf..4cc824b 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -381,7 +381,8 @@
}
#if CONFIG_TUNE_VMAF
if (cpi->oxcf.tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
- cpi->oxcf.tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING) {
+ cpi->oxcf.tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
+ cpi->oxcf.tuning == AOM_TUNE_VMAF_MAX_GAIN) {
av1_set_vmaf_rdmult(cpi, x, bsize, mi_row, mi_col, &x->rdmult);
}
#endif
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index c0fc1d7..908b02b 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -5219,7 +5219,8 @@
}
#if CONFIG_TUNE_VMAF
if (cpi->oxcf.tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
- cpi->oxcf.tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING) {
+ cpi->oxcf.tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
+ cpi->oxcf.tuning == AOM_TUNE_VMAF_MAX_GAIN) {
av1_set_quantizer(cm, av1_get_vmaf_base_qindex(cpi, q));
} else {
#endif
@@ -6132,7 +6133,8 @@
#if CONFIG_TUNE_VMAF
if (oxcf->tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
- oxcf->tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING) {
+ oxcf->tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
+ oxcf->tuning == AOM_TUNE_VMAF_MAX_GAIN) {
av1_set_mb_vmaf_rdmult_scaling(cpi);
}
#endif
@@ -6431,12 +6433,11 @@
#if CONFIG_TUNE_VMAF
if (!is_stat_generation_stage(cpi) &&
cpi->oxcf.tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING) {
- const bool use_block_based_methods = false;
- if (use_block_based_methods) {
- av1_vmaf_blk_preprocessing(cpi, sd);
- } else {
- av1_vmaf_frame_preprocessing(cpi, sd);
- }
+ av1_vmaf_frame_preprocessing(cpi, sd);
+ }
+ if (!is_stat_generation_stage(cpi) &&
+ cpi->oxcf.tuning == AOM_TUNE_VMAF_MAX_GAIN) {
+ av1_vmaf_blk_preprocessing(cpi, sd);
}
#endif
@@ -6648,7 +6649,8 @@
#if CONFIG_TUNE_VMAF
if (oxcf->tuning == AOM_TUNE_VMAF_WITH_PREPROCESSING ||
- oxcf->tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING) {
+ oxcf->tuning == AOM_TUNE_VMAF_WITHOUT_PREPROCESSING ||
+ oxcf->tuning == AOM_TUNE_VMAF_MAX_GAIN) {
update_vmaf_curve(cpi, cpi->source, &cpi->common.cur_frame->buf);
}
#endif