Introduce qindex -> QM level formula tuned for allintra mode

QMs help increase visual quality by effectively allocating more
bits towards encoding low and mid frequencies for a given file size,
which helps retain overall texture integrity, avoiding cases where
local features could collapse into flat patches or 'thin' high-freq
basis patterns.

The formula was empirically derived by encoding the CID22 validation
testset for each QP/QM tuple, and building a convex hull that
maximizes SSIMU2 scores, and a final subjective visual quality pass
as a sanity check.

Approximate BD-Rate gains over enable-qm=0 - cpu-used=6 (subset1):
- SSIMU2 60: -4.5%
- SSIMU2 70: -3.9%
- SSIMU2 80: -3.4%
- SSIMU2 90: -6.6%

Bug: aomedia:375221136
Change-Id: I29721cad07ee273a56c5d5d4b7e929301083a117
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 255a891..1f2f34f 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -731,8 +731,8 @@
    * control sets the minimum level of flatness from which the matrices
    * are determined.
    *
-   * By default, the encoder sets this minimum at half the available
-   * range.
+   * By default, the encoder sets this minimum at level 5 (4 in allintra
+   * mode).
    */
   AV1E_SET_QM_MIN = 64,
 
@@ -743,8 +743,8 @@
    * As quantisation levels increase, the matrices get flatter. This
    * control sets the maximum level of flatness possible.
    *
-   * By default, the encoder sets this maximum at the top of the
-   * available range.
+   * By default, the encoder sets this maximum at level 9 (10 in allintra
+   * mode)
    */
   AV1E_SET_QM_MAX = 65,
 
diff --git a/av1/arg_defs.c b/av1/arg_defs.c
index 1c06f5b..4f92cbe 100644
--- a/av1/arg_defs.c
+++ b/av1/arg_defs.c
@@ -460,10 +460,12 @@
   .enable_qm =
       ARG_DEF(NULL, "enable-qm", 1,
               "Enable quantisation matrices (0: false (default), 1: true)"),
-  .qm_min = ARG_DEF(NULL, "qm-min", 1,
-                    "Min quant matrix flatness (0..15), default is 8"),
-  .qm_max = ARG_DEF(NULL, "qm-max", 1,
-                    "Max quant matrix flatness (0..15), default is 15"),
+  .qm_min = ARG_DEF(
+      NULL, "qm-min", 1,
+      "Min quant matrix flatness (0..15), default is 5 (4 for allintra mode)"),
+  .qm_max = ARG_DEF(
+      NULL, "qm-max", 1,
+      "Max quant matrix flatness (0..15), default is 9 (10 for allintra mode)"),
   .reduced_tx_type_set = ARG_DEF(NULL, "reduced-tx-type-set", 1,
                                  "Use reduced set of transform types"),
   .use_intra_dct_only =
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index f10f5fa..071a2fe 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -2861,12 +2861,15 @@
     }
     priv->extra_cfg = default_extra_cfg[extra_cfg_idx];
     // Special handling:
-    // By default, if omitted, --enable-cdef = 1.
-    // Here we set its default value to 0 when --allintra is turned on.
-    // However, if users set --enable-cdef = 1 from command line,
-    // The encoder still respects it.
+    // By default, if omitted: --enable-cdef=1, --qm-min=5, and --qm-max=9
+    // Here we set its default values to 0, 4, and 10 respectively when
+    // --allintra is turned on.
+    // However, if users set --enable-cdef, --qm-min, or --qm-max, either from
+    // the command line or aom_codec_control(), the encoder still respects it.
     if (priv->cfg.g_usage == AOM_USAGE_ALL_INTRA) {
       priv->extra_cfg.enable_cdef = 0;
+      priv->extra_cfg.qm_min = DEFAULT_QM_FIRST_ALLINTRA;
+      priv->extra_cfg.qm_max = DEFAULT_QM_LAST_ALLINTRA;
     }
     av1_initialize_enc(priv->cfg.g_usage, priv->cfg.rc_end_usage);
 
diff --git a/av1/common/quant_common.h b/av1/common/quant_common.h
index 7e0a20c..1a7b281 100644
--- a/av1/common/quant_common.h
+++ b/av1/common/quant_common.h
@@ -36,6 +36,8 @@
 #define DEFAULT_QM_V 12
 #define DEFAULT_QM_FIRST 5
 #define DEFAULT_QM_LAST 9
+#define DEFAULT_QM_FIRST_ALLINTRA 4
+#define DEFAULT_QM_LAST_ALLINTRA 10
 #define LOSSLESS_Q_STEP 4  // this should equal to dc/ac_qlookup_QTX[0]
 
 struct AV1Common;
@@ -58,6 +60,33 @@
   return first + (qindex * (last + 1 - first)) / QINDEX_RANGE;
 }
 
+// QM levels tuned for allintra mode (including still images)
+// This formula was empirically derived by encoding the CID22 validation
+// testset for each QP/QM tuple, and building a convex hull that
+// maximizes SSIMU2 scores, and a final subjective visual quality pass
+// as a sanity check.
+static inline int aom_get_qmlevel_allintra(int qindex, int first, int last) {
+  int qm_level = 0;
+
+  if (qindex <= 40) {
+    qm_level = 10;
+  } else if (qindex <= 100) {
+    qm_level = 9;
+  } else if (qindex <= 160) {
+    qm_level = 8;
+  } else if (qindex <= 200) {
+    qm_level = 7;
+  } else if (qindex <= 220) {
+    qm_level = 6;
+  } else if (qindex <= 240) {
+    qm_level = 5;
+  } else {
+    qm_level = 4;
+  }
+
+  return clamp(qm_level, first, last);
+}
+
 // Initialize all global quant/dequant matrices.
 void av1_qm_init(struct CommonQuantParams *quant_params, int num_planes);
 
diff --git a/av1/encoder/av1_quantize.c b/av1/encoder/av1_quantize.c
index d44795d..5de1114 100644
--- a/av1/encoder/av1_quantize.c
+++ b/av1/encoder/av1_quantize.c
@@ -864,7 +864,8 @@
 }
 
 void av1_set_quantizer(AV1_COMMON *const cm, int min_qmlevel, int max_qmlevel,
-                       int q, int enable_chroma_deltaq, int enable_hdr_deltaq) {
+                       int q, int enable_chroma_deltaq, int enable_hdr_deltaq,
+                       bool is_allintra) {
   // quantizer has to be reinitialized with av1_init_quantizer() if any
   // delta_q changes.
   CommonQuantParams *quant_params = &cm->quant_params;
@@ -896,18 +897,29 @@
     }
   }
 
-  quant_params->qmatrix_level_y =
-      aom_get_qmlevel(quant_params->base_qindex, min_qmlevel, max_qmlevel);
-  quant_params->qmatrix_level_u =
-      aom_get_qmlevel(quant_params->base_qindex + quant_params->u_ac_delta_q,
-                      min_qmlevel, max_qmlevel);
+  // Select the best QM formula based on whether we're encoding in allintra mode
+  // or any other mode
+  int (*get_qmlevel)(int, int, int);
 
-  if (!cm->seq_params->separate_uv_delta_q)
-    quant_params->qmatrix_level_v = quant_params->qmatrix_level_u;
-  else
+  if (is_allintra) {
+    get_qmlevel = aom_get_qmlevel_allintra;
+  } else {
+    get_qmlevel = aom_get_qmlevel;
+  }
+
+  quant_params->qmatrix_level_y =
+      get_qmlevel(quant_params->base_qindex, min_qmlevel, max_qmlevel);
+  quant_params->qmatrix_level_u =
+      get_qmlevel(quant_params->base_qindex + quant_params->u_ac_delta_q,
+                  min_qmlevel, max_qmlevel);
+
+  if (cm->seq_params->separate_uv_delta_q) {
     quant_params->qmatrix_level_v =
-        aom_get_qmlevel(quant_params->base_qindex + quant_params->v_ac_delta_q,
-                        min_qmlevel, max_qmlevel);
+        get_qmlevel(quant_params->base_qindex + quant_params->v_ac_delta_q,
+                    min_qmlevel, max_qmlevel);
+  } else {
+    quant_params->qmatrix_level_v = quant_params->qmatrix_level_u;
+  }
 }
 
 // Table that converts 0-63 Q-range values passed in outside to the Qindex
diff --git a/av1/encoder/av1_quantize.h b/av1/encoder/av1_quantize.h
index 35b0fa8..bf3b365 100644
--- a/av1/encoder/av1_quantize.h
+++ b/av1/encoder/av1_quantize.h
@@ -12,6 +12,8 @@
 #ifndef AOM_AV1_ENCODER_AV1_QUANTIZE_H_
 #define AOM_AV1_ENCODER_AV1_QUANTIZE_H_
 
+#include <stdbool.h>
+
 #include "config/aom_config.h"
 
 #include "av1/common/quant_common.h"
@@ -120,7 +122,7 @@
 
 void av1_set_quantizer(struct AV1Common *const cm, int min_qmlevel,
                        int max_qmlevel, int q, int enable_chroma_deltaq,
-                       int enable_hdr_deltaq);
+                       int enable_hdr_deltaq, bool is_allintra);
 
 int av1_quantizer_to_qindex(int quantizer);
 
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 6df5e2e..4d28bd2 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -2646,7 +2646,8 @@
   }
 
   av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
-                    q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq);
+                    q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq,
+                    cpi->oxcf.mode == ALLINTRA);
   av1_set_speed_features_qindex_dependent(cpi, cpi->oxcf.speed);
   av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
                      cm->seq_params->bit_depth);
@@ -2660,7 +2661,8 @@
       cpi->rc.high_source_sad) {
     if (av1_encodedframe_overshoot_cbr(cpi, &q)) {
       av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
-                        q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq);
+                        q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq,
+                        cpi->oxcf.mode == ALLINTRA);
       av1_set_speed_features_qindex_dependent(cpi, cpi->oxcf.speed);
       av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
                          cm->seq_params->bit_depth);
@@ -2964,7 +2966,8 @@
     }
 
     av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q,
-                      q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq);
+                      q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq,
+                      oxcf->mode == ALLINTRA);
     av1_set_speed_features_qindex_dependent(cpi, oxcf->speed);
     av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
                        cm->seq_params->bit_depth);
diff --git a/av1/encoder/encoder_utils.c b/av1/encoder/encoder_utils.c
index 32eb2f6..73a0dac 100644
--- a/av1/encoder/encoder_utils.c
+++ b/av1/encoder/encoder_utils.c
@@ -1127,7 +1127,8 @@
     set_encoding_params_for_screen_content(cpi, pass);
     av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel,
                       q_for_screen_content_quick_run,
-                      q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq);
+                      q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq,
+                      oxcf->mode == ALLINTRA);
     av1_set_speed_features_qindex_dependent(cpi, oxcf->speed);
     av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
                        cm->seq_params->bit_depth);
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index a81cc29..69d465e 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -1368,7 +1368,8 @@
 
   av1_set_quantizer(
       cm, cpi->oxcf.q_cfg.qm_minlevel, cpi->oxcf.q_cfg.qm_maxlevel, qindex,
-      cpi->oxcf.q_cfg.enable_chroma_deltaq, cpi->oxcf.q_cfg.enable_hdr_deltaq);
+      cpi->oxcf.q_cfg.enable_chroma_deltaq, cpi->oxcf.q_cfg.enable_hdr_deltaq,
+      cpi->oxcf.mode == ALLINTRA);
 
   av1_setup_block_planes(xd, seq_params->subsampling_x,
                          seq_params->subsampling_y, num_planes);
diff --git a/av1/encoder/tune_butteraugli.c b/av1/encoder/tune_butteraugli.c
index 99fd464..e6061ec 100644
--- a/av1/encoder/tune_butteraugli.c
+++ b/av1/encoder/tune_butteraugli.c
@@ -299,7 +299,8 @@
   // cpi->sf.part_sf.fixed_partition_size = BLOCK_32X32;
 
   av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q_index,
-                    q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq);
+                    q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq,
+                    oxcf->mode == ALLINTRA);
   av1_set_speed_features_qindex_dependent(cpi, oxcf->speed);
   av1_init_quantizer(&cpi->enc_quant_dequant_params, &cm->quant_params,
                      cm->seq_params->bit_depth);