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