shithub: libvpx

Download patch

ref: 7e234b92286fbf96be601f2ff239a7afe2f6c09b
parent: 9a1ce7be7d4a3056b9da1df64cb7d5115a513dd9
author: paulwilkins <[email protected]>
date: Wed Mar 18 10:41:18 EDT 2015

Revised rd adjustment for variance.

Revised adjustment for rd based on source complexity.
Two cases:

1) Bias against low variance intra predictors
when the actual source variance is higher.

2) When the source variance is very low to give a slight
bias against predictors that might introduce false texture
or features.

The impact on metrics of this change across the test sets is
small and mixed.

derf -0.073%, -0.049%, -0.291%
std hd -0.093%, -0.1%, -0.557%
yt  +0.186%, +0.04%, - 0.074%
ythd +0.625%, + 0.563%, +0.584%

Medium to strong psycho-visual improvements in some
problem clips.

This feature and intra weight on GF group length now
turned on by default.

Change-Id: Idefc8b633a7b7bc56c42dbe19f6b2f872d73851e

--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -61,12 +61,9 @@
 #define RC_FACTOR_MAX       1.75
 
 
-#define INTRA_WEIGHT_EXPERIMENT 0
-#if INTRA_WEIGHT_EXPERIMENT
 #define NCOUNT_INTRA_THRESH 8192
 #define NCOUNT_INTRA_FACTOR 3
 #define NCOUNT_FRAME_II_THRESH 5.0
-#endif
 
 #define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
 
@@ -832,7 +829,6 @@
           // Keep a count of cases where the inter and intra were very close
           // and very low. This helps with scene cut detection for example in
           // cropped clips with black bars at the sides or top and bottom.
-#if INTRA_WEIGHT_EXPERIMENT
           if (((this_error - intrapenalty) * 9 <= motion_error * 10) &&
               (this_error < (2 * intrapenalty))) {
             neutral_count += 1.0;
@@ -843,12 +839,6 @@
             neutral_count += (double)motion_error /
                              DOUBLE_DIVIDE_CHECK((double)this_error);
           }
-#else
-          if (((this_error - intrapenalty) * 9 <= motion_error * 10) &&
-              (this_error < (2 * intrapenalty))) {
-            neutral_count += 1.0;
-          }
-#endif
 
           mv.row *= 8;
           mv.col *= 8;
@@ -1291,11 +1281,10 @@
     frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2);
 
   modified_pct_inter = frame->pcnt_inter;
-#if INTRA_WEIGHT_EXPERIMENT
   if ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) <
-      (double)NCOUNT_FRAME_II_THRESH)
+      (double)NCOUNT_FRAME_II_THRESH) {
     modified_pct_inter = frame->pcnt_inter - frame->pcnt_neutral;
-#endif
+  }
   modified_pcnt_intra = 100 * (1.0 - modified_pct_inter);
 
 
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -50,7 +50,6 @@
 
 #define MIN_EARLY_TERM_INDEX    3
 #define NEW_MV_DISCOUNT_FACTOR  8
-#define SOURCE_VARIANCE_RD_ADJUSTMENT 0
 
 typedef struct {
   PREDICTION_MODE mode;
@@ -2825,21 +2824,22 @@
   rd_cost->rdcost = RDCOST(x->rdmult, x->rddiv, rd_cost->rate, rd_cost->dist);
 }
 
-#if SOURCE_VARIANCE_RD_ADJUSTMENT
 // This function is designed to apply a bias or adjustment to an rd value based
 // on the relative variance of the source and reconstruction.
 #define LOW_VAR_THRESH 16
-#define LOW_VAR_DIFF_THRESH 1
 #define VLOW_ADJ_MAX 25
-#define VHIGH_ADJ_MAX 10
+#define VHIGH_ADJ_MAX 8
 static void rd_variance_adjustment(VP9_COMP *cpi,
                                    MACROBLOCK *x,
                                    BLOCK_SIZE bsize,
                                    int64_t *this_rd,
+                                   MV_REFERENCE_FRAME ref_frame,
                                    unsigned int source_variance) {
   MACROBLOCKD *const xd = &x->e_mbd;
   unsigned int recon_variance;
-  unsigned int var_diff;
+  unsigned int absvar_diff = 0;
+  int64_t var_error = 0;
+  int64_t var_factor = 0;
 
   if (*this_rd == INT64_MAX)
     return;
@@ -2857,22 +2857,31 @@
     vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize);
 #endif  // CONFIG_VP9_HIGHBITDEPTH
 
-  var_diff = (source_variance > recon_variance)
-    ? (source_variance - recon_variance) : (recon_variance - source_variance);
+  if ((source_variance + recon_variance) > LOW_VAR_THRESH) {
+    absvar_diff = (source_variance > recon_variance)
+      ? (source_variance - recon_variance)
+      : (recon_variance - source_variance);
 
-  if ((source_variance > LOW_VAR_THRESH) && (var_diff > LOW_VAR_DIFF_THRESH)) {
-    unsigned int var_factor;
-    if (source_variance > recon_variance) {
-      var_factor =
-        MIN(VLOW_ADJ_MAX, (var_diff * VLOW_ADJ_MAX) / source_variance);
-    } else {
-      var_factor =
-        MIN(VHIGH_ADJ_MAX, (var_diff * VHIGH_ADJ_MAX) / source_variance);
-    }
-    *this_rd += (*this_rd * var_factor) / 100;
+    var_error = (200 * source_variance * recon_variance) /
+      ((source_variance * source_variance) +
+       (recon_variance * recon_variance));
+    var_error = 100 - var_error;
   }
+
+  // Source variance above a threshold and ref frame is intra.
+  // This case is targeted mainly at discouraging intra modes that give rise
+  // to a predictor with a low spatial complexity compared to the source.
+  if ((source_variance > LOW_VAR_THRESH) && (ref_frame == INTRA_FRAME) &&
+      (source_variance > recon_variance)) {
+    var_factor = MIN(absvar_diff, MIN(VLOW_ADJ_MAX, var_error));
+  // A second possible case of interest is where the source variance
+  // is very low and we wish to discourage false texture or motion trails.
+  } else if ((source_variance < (LOW_VAR_THRESH >> 1)) &&
+             (recon_variance > source_variance)) {
+    var_factor = MIN(absvar_diff, MIN(VHIGH_ADJ_MAX, var_error));
+  }
+  *this_rd += (*this_rd * var_factor) / 100;
 }
-#endif
 
 void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi,
                                TileDataEnc *tile_data,
@@ -3330,11 +3339,10 @@
       this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
     }
 
-#if SOURCE_VARIANCE_RD_ADJUSTMENT
     // Apply an adjustment to the rd value based on the similarity of the
     // source variance and reconstructed variance.
-    rd_variance_adjustment(cpi, x, bsize, &this_rd, x->source_variance);
-#endif
+    rd_variance_adjustment(cpi, x, bsize, &this_rd,
+                           ref_frame, x->source_variance);
 
     if (ref_frame == INTRA_FRAME) {
     // Keep record of best intra rd