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