shithub: libvpx

Download patch

ref: 81374532905b376cead0958c543c431bac530620
parent: a0765aa9f34e7f5dfa1ba938dbe9e1399a75bf5e
author: Clement Courbet <courbet@google.com>
date: Fri Mar 20 05:22:55 EDT 2020

Optimize vp9_get_sub_block_energy.

Because energy scaling is non-decreasing, we can work on the variance
and scale after the loop. This avoids costly computations (in
particular, log()) within the loop.
We've measured that we spend 0.8% of our total time computing the log.

Change-Id: I302fc0ecd9fd8cf96ee9f31b8673e82de1b2b3e2

--- a/vp9/encoder/vp9_aq_variance.c
+++ b/vp9/encoder/vp9_aq_variance.c
@@ -186,6 +186,17 @@
   return log(var + 1.0);
 }
 
+#define DEFAULT_E_MIDPOINT 10.0
+static int scale_block_energy(VP9_COMP *cpi, unsigned int block_var) {
+  double energy;
+  double energy_midpoint;
+  energy_midpoint =
+      (cpi->oxcf.pass == 2) ? cpi->twopass.mb_av_energy : DEFAULT_E_MIDPOINT;
+  energy = log(block_var + 1.0) - energy_midpoint;
+  return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
+}
+#undef DEFAULT_E_MIDPOINT
+
 // Get the range of sub block energy values;
 void vp9_get_sub_block_energy(VP9_COMP *cpi, MACROBLOCK *mb, int mi_row,
                               int mi_col, BLOCK_SIZE bsize, int *min_e,
@@ -202,18 +213,25 @@
     *min_e = vp9_block_energy(cpi, mb, bsize);
     *max_e = *min_e;
   } else {
-    int energy;
-    *min_e = ENERGY_MAX;
-    *max_e = ENERGY_MIN;
+    unsigned int var;
+    // Because scale_block_energy is non-decreasing, we can find the min/max
+    // block variance and scale afterwards. This avoids a costly scaling at
+    // every iteration.
+    unsigned int min_var = UINT_MAX;
+    unsigned int max_var = 0;
 
     for (y = 0; y < ymis; ++y) {
       for (x = 0; x < xmis; ++x) {
         vp9_setup_src_planes(mb, cpi->Source, mi_row + y, mi_col + x);
-        energy = vp9_block_energy(cpi, mb, BLOCK_8X8);
-        *min_e = VPXMIN(*min_e, energy);
-        *max_e = VPXMAX(*max_e, energy);
+        vpx_clear_system_state();
+        var = block_variance(cpi, mb, BLOCK_8X8);
+        vpx_clear_system_state();
+        min_var = VPXMIN(min_var, var);
+        max_var = VPXMAX(max_var, var);
       }
     }
+    *min_e = scale_block_energy(cpi, min_var);
+    *max_e = scale_block_energy(cpi, max_var);
   }
 
   // Re-instate source pointers back to what they should have been on entry.
@@ -220,13 +238,10 @@
   vp9_setup_src_planes(mb, cpi->Source, mi_row, mi_col);
 }
 
-#define DEFAULT_E_MIDPOINT 10.0
 int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
-  double energy;
-  double energy_midpoint;
+  unsigned int var;
   vpx_clear_system_state();
-  energy_midpoint =
-      (cpi->oxcf.pass == 2) ? cpi->twopass.mb_av_energy : DEFAULT_E_MIDPOINT;
-  energy = vp9_log_block_var(cpi, x, bs) - energy_midpoint;
-  return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
+  var = block_variance(cpi, x, bs);
+  vpx_clear_system_state();
+  return scale_block_energy(cpi, var);
 }