shithub: libvpx

Download patch

ref: b1072a793d4957e5a504d125ae5ded808b90060d
parent: 96a024a12a925d37239d7409a4fd4cc6047add8e
author: sdeng <[email protected]>
date: Fri May 31 13:25:09 EDT 2019

Hierarchical rdmult scaling when tune=ssim

Use different lagrangian multiplier scaling factor for different block
size. The blocks whose sizes are less than 16x16 share the same multiplier
of their parent block.

The additional gains/loss on top of the tune=ssim are:
Data Set   Overall PSNR   SSIM    MS-SSIM
Lowres         2.918     -3.691   -2.596
Midres         1.708     -2.656   -2.624
HDres          1.619     -2.496   -2.391
Midres_10bd    1.518     -3.263   -3.561

The overall gains/loss comparing to tune=psnr are:
Data Set   Overall PSNR   SSIM    MS-SSIM
Lowres         5.583     -6.208   -4.978
Midres         4.024     -5.610   -6.411
HDres          4.102     -6.614   -7.457
Midres_10bd    4.647     -7.181   -8.614

Change-Id: I0e6c5008488734e979b2dacde9fc2a17f3aa620f

--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -268,21 +268,38 @@
 }
 
 static void set_ssim_rdmult(VP9_COMP *const cpi, MACROBLOCK *const x,
-                            int mi_row, int mi_col, int *rdmult) {
+                            const BLOCK_SIZE bsize, const int mi_row,
+                            const int mi_col, int *const rdmult) {
   const VP9_COMMON *const cm = &cpi->common;
 
-  // SSIM rdmult scaling factors are currently 64x64 based.
-  const int num_8x8_w = 8;
-  const int num_8x8_h = 8;
+  const int bsize_base = BLOCK_16X16;
+  const int num_8x8_w = num_8x8_blocks_wide_lookup[bsize_base];
+  const int num_8x8_h = num_8x8_blocks_high_lookup[bsize_base];
   const int num_cols = (cm->mi_cols + num_8x8_w - 1) / num_8x8_w;
-  const int row = mi_row / num_8x8_h;
-  const int col = mi_col / num_8x8_w;
-  const int index = row * num_cols + col;
+  const int num_rows = (cm->mi_rows + num_8x8_h - 1) / num_8x8_h;
+  const int num_bcols =
+      (num_8x8_blocks_wide_lookup[bsize] + num_8x8_w - 1) / num_8x8_w;
+  const int num_brows =
+      (num_8x8_blocks_high_lookup[bsize] + num_8x8_h - 1) / num_8x8_h;
+  int row, col;
+  double num_of_mi = 0.0;
+  double geom_mean_of_scale = 0.0;
 
   assert(cpi->oxcf.tuning == VP8_TUNE_SSIM);
-  *rdmult =
-      (int)((double)(*rdmult) * cpi->mi_ssim_rdmult_scaling_factors[index]);
-  *rdmult = VPXMAX(*rdmult, 1);
+
+  for (row = mi_row / num_8x8_w;
+       row < num_rows && row < mi_row / num_8x8_w + num_brows; ++row) {
+    for (col = mi_col / num_8x8_h;
+         col < num_cols && col < mi_col / num_8x8_h + num_bcols; ++col) {
+      const int index = row * num_cols + col;
+      geom_mean_of_scale += log(cpi->mi_ssim_rdmult_scaling_factors[index]);
+      num_of_mi += 1.0;
+    }
+  }
+  geom_mean_of_scale = exp(geom_mean_of_scale / num_of_mi);
+
+  *rdmult = (int)((double)(*rdmult) * geom_mean_of_scale);
+  *rdmult = VPXMAX(*rdmult, 0);
   set_error_per_bit(x, *rdmult);
   vpx_clear_system_state();
 }
@@ -323,7 +340,7 @@
   x->rddiv = cpi->rd.RDDIV;
   x->rdmult = cpi->rd.RDMULT;
   if (oxcf->tuning == VP8_TUNE_SSIM) {
-    set_ssim_rdmult(cpi, x, mi_row, mi_col, &x->rdmult);
+    set_ssim_rdmult(cpi, x, bsize, mi_row, mi_col, &x->rdmult);
   }
 
   // required by vp9_append_sub8x8_mvs_for_idx() and vp9_find_best_ref_mvs()
@@ -1970,7 +1987,7 @@
   }
 
   if (oxcf->tuning == VP8_TUNE_SSIM) {
-    set_ssim_rdmult(cpi, x, mi_row, mi_col, &x->rdmult);
+    set_ssim_rdmult(cpi, x, bsize, mi_row, mi_col, &x->rdmult);
   }
 }
 
@@ -2221,7 +2238,7 @@
     const VP9EncoderConfig *const oxcf = &cpi->oxcf;
     x->rdmult = x->cb_rdmult;
     if (oxcf->tuning == VP8_TUNE_SSIM) {
-      set_ssim_rdmult(cpi, x, mi_row, mi_col, &x->rdmult);
+      set_ssim_rdmult(cpi, x, bsize, mi_row, mi_col, &x->rdmult);
     }
   }
 
@@ -3845,7 +3862,7 @@
   const int rd_div = x->rddiv;
   int partition_mul = x->cb_rdmult;
   if (oxcf->tuning == VP8_TUNE_SSIM) {
-    set_ssim_rdmult(cpi, x, mi_row, mi_col, &partition_mul);
+    set_ssim_rdmult(cpi, x, bsize, mi_row, mi_col, &partition_mul);
   }
   vp9_rd_cost_update(partition_mul, rd_div, &best_rdc);
 
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -2397,7 +2397,7 @@
   vp9_set_speed_features_framesize_dependent(cpi, oxcf->speed);
 
   {
-    const int bsize = BLOCK_64X64;
+    const int bsize = BLOCK_16X16;
     const int w = num_8x8_blocks_wide_lookup[bsize];
     const int h = num_8x8_blocks_high_lookup[bsize];
     const int num_cols = (cm->mi_cols + w - 1) / w;
@@ -4759,15 +4759,9 @@
 // Some sample values are:
 // (for midres test set)
 // SSIM_VAR_SCALE  avg_psnr   ssim   ms_ssim
-//     16.0          2.312   -3.062  -3.882
-//     32.0          0.852   -2.260  -2.821
-//     64.0          0.294   -1.606  -1.925
-// (for midres_10bd test set)
-// SSIM_VAR_SCALE  avg_psnr   ssim   ms_ssim
-//      8.0          6.782   -3.872  -5.464
-//     16.0          3.189   -4.083  -5.258
-//     32.0          1.113   -3.423  -4.309
-//     64.0          0.241   -2.515  -3.074
+//      8.0          8.980   -5.767  -7.069
+//     16.0          4.315   -5.610  -6.411
+//     32.0          1.559   -4.541  -4.980
 #define SSIM_VAR_SCALE 16.0
 static void set_mb_ssim_rdmult_scaling(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
@@ -4776,7 +4770,7 @@
   MACROBLOCKD *xd = &x->e_mbd;
   uint8_t *y_buffer = cpi->Source->y_buffer;
   const int y_stride = cpi->Source->y_stride;
-  const int block_size = BLOCK_64X64;
+  const int block_size = BLOCK_16X16;
 
   const int num_8x8_w = num_8x8_blocks_wide_lookup[block_size];
   const int num_8x8_h = num_8x8_blocks_high_lookup[block_size];