Normalize SB QP scaling

Calculate the SB level statistics across the entire frame. Use
their geometric means for the frame level normalization.

Change-Id: I990b188ab9d8100f96c33c42e1c5305388c6a7a9
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index ce9fdcc..234acb0 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -3132,7 +3132,39 @@
                              sizeof(*cpi->mb_wiener_variance)));
 }
 
+static int get_var_perceptual_ai(AV1_COMP *const cpi, BLOCK_SIZE bsize,
+                                 int mi_row, int mi_col) {
+  AV1_COMMON *const cm = &cpi->common;
+  const int mi_wide = mi_size_wide[bsize];
+  const int mi_high = mi_size_high[bsize];
+
+  const int mi_step = mi_size_wide[BLOCK_16X16];
+  int sb_wiener_var = 0;
+  int mb_stride = cpi->frame_info.mb_cols;
+  int mb_count = 0;
+  int mb_wiener_var[64];
+
+  for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
+    for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
+      if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
+        continue;
+
+      mb_wiener_var[mb_count] =
+          (int)cpi->mb_wiener_variance[(row / mi_step) * mb_stride +
+                                       (col / mi_step)];
+      ++mb_count;
+    }
+  }
+  qsort(mb_wiener_var, mb_count - 1, sizeof(*mb_wiener_var), qsort_comp);
+
+  sb_wiener_var = mb_wiener_var[mb_count / 3];
+  sb_wiener_var = AOMMAX(1, sb_wiener_var);
+
+  return sb_wiener_var;
+}
+
 static void set_mb_wiener_variance(AV1_COMP *cpi) {
+  AV1_COMMON *const cm = &cpi->common;
   uint8_t *buffer = cpi->source->y_buffer;
   int buf_stride = cpi->source->y_stride;
   ThreadData *td = &cpi->td;
@@ -3208,45 +3240,36 @@
     }
   }
 
-  if (count) cpi->norm_wiener_variance /= count;
+  int sb_step = mi_size_wide[cm->seq_params->sb_size];
+  double sb_wiener_log = 0;
+  int sb_count = 0;
+
+  for (int mi_row = 0; mi_row < cm->mi_params.mi_rows; mi_row += sb_step) {
+    for (int mi_col = 0; mi_col < cm->mi_params.mi_cols; mi_col += sb_step) {
+      int sb_wiener_var =
+          get_var_perceptual_ai(cpi, cm->seq_params->sb_size, mi_row, mi_col);
+      sb_wiener_log += log(sb_wiener_var);
+      ++sb_count;
+    }
+  }
+
+  if (sb_count)
+    cpi->norm_wiener_variance = (int64_t)(exp(sb_wiener_log / sb_count));
   cpi->norm_wiener_variance = AOMMAX(1, cpi->norm_wiener_variance);
 }
 
 int av1_get_sbq_perceptual_ai(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
                               int mi_col) {
   AV1_COMMON *const cm = &cpi->common;
-  const int mi_wide = mi_size_wide[bsize];
-  const int mi_high = mi_size_high[bsize];
   const int base_qindex = cm->quant_params.base_qindex;
-
-  const int mi_step = mi_size_wide[BLOCK_16X16];
-  int64_t sb_wiener_var;
-  int mb_stride = cpi->frame_info.mb_cols;
-  int mb_count = 0;
-  int mb_wiener_var[64];
-
-  for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
-    for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
-      if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
-        continue;
-
-      mb_wiener_var[mb_count] =
-          (int)cpi->mb_wiener_variance[(row / mi_step) * mb_stride +
-                                       (col / mi_step)];
-      ++mb_count;
-    }
-  }
-  qsort(mb_wiener_var, mb_count - 1, sizeof(*mb_wiener_var), qsort_comp);
-
-  sb_wiener_var = mb_wiener_var[mb_count / 2];
-  sb_wiener_var = AOMMAX(1, sb_wiener_var);
-
+  int sb_wiener_var = get_var_perceptual_ai(cpi, bsize, mi_row, mi_col);
   int offset = 0;
   double beta = (double)cpi->norm_wiener_variance / sb_wiener_var;
   offset = av1_get_deltaq_offset(cm->seq_params->bit_depth, base_qindex, beta);
+
   const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
-  offset = AOMMIN(offset, delta_q_info->delta_q_res * 9 - 1);
-  offset = AOMMAX(offset, -delta_q_info->delta_q_res * 9 + 1);
+  offset = AOMMIN(offset, delta_q_info->delta_q_res * 20 - 1);
+  offset = AOMMAX(offset, -delta_q_info->delta_q_res * 20 + 1);
   int qindex = cm->quant_params.base_qindex + offset;
   qindex = AOMMIN(qindex, MAXQ);
   qindex = AOMMAX(qindex, MINQ);
@@ -3436,8 +3459,10 @@
 
   aom_clear_system_state();
 
-  init_mb_wiener_var_buffer(cpi);
-  set_mb_wiener_variance(cpi);
+  if (cpi->oxcf.q_cfg.deltaq_mode == DELTA_Q_PERCEPTUAL_AI) {
+    init_mb_wiener_var_buffer(cpi);
+    set_mb_wiener_variance(cpi);
+  }
 
 #if CONFIG_INTERNAL_STATS
   memset(cpi->mode_chosen_counts, 0,