]> granicus.if.org Git - libvpx/commitdiff
Film Mode: Bias based on sub block energy.
authorPaul Wilkins <paulwilkins@google.com>
Tue, 2 Apr 2019 15:38:49 +0000 (16:38 +0100)
committerPaul Wilkins <paulwilkins@google.com>
Mon, 8 Apr 2019 10:11:10 +0000 (11:11 +0100)
Apply a bias for film mode against intra coding
(especially DC_PRED) and compound modes if the sub
blocks of the current block have significantly different
variance in the source.

Change-Id: Iac1fc0510141be5c472a0ec57567bab3d2fc4164

vp9/encoder/vp9_rdopt.c

index bf631d1bf0391034deecbf508819e7fdbcc1bfcc..a1f1069fecb2de1e81180815ce5ac5c421050055 100644 (file)
@@ -3132,6 +3132,7 @@ static void rd_variance_adjustment(VP9_COMP *cpi, MACROBLOCK *x,
                                    BLOCK_SIZE bsize, int64_t *this_rd,
                                    struct buf_2d *recon,
                                    MV_REFERENCE_FRAME ref_frame,
+                                   MV_REFERENCE_FRAME second_ref_frame,
                                    PREDICTION_MODE this_mode) {
   MACROBLOCKD *const xd = &x->e_mbd;
   unsigned int rec_variance;
@@ -3175,6 +3176,8 @@ static void rd_variance_adjustment(VP9_COMP *cpi, MACROBLOCK *x,
       if (ref_frame == INTRA_FRAME) {
         low_var_thresh *= 2;
         if (this_mode == DC_PRED) low_var_thresh *= 5;
+      } else if (second_ref_frame > INTRA_FRAME) {
+        low_var_thresh *= 2;
       }
     }
   } else {
@@ -3199,19 +3202,13 @@ static void rd_variance_adjustment(VP9_COMP *cpi, MACROBLOCK *x,
       (unsigned int)((int64_t)VAR_MULT * var_diff) / VPXMAX(1, src_variance);
   var_factor = VPXMIN(adj_max, var_factor);
 
-  *this_rd += (*this_rd * var_factor) / 100;
-
-  if (content_type == VP9E_CONTENT_FILM) {
-    if (src_rec_min <= low_var_thresh / 2) {
-      if (ref_frame == INTRA_FRAME) {
-        if (this_mode == DC_PRED)
-          *this_rd *= 2;
-        else
-          *this_rd += (*this_rd / 4);
-      }
-    }
+  if ((content_type == VP9E_CONTENT_FILM) &&
+      ((ref_frame == INTRA_FRAME) || (second_ref_frame > INTRA_FRAME))) {
+    var_factor *= 2;
   }
 
+  *this_rd += (*this_rd * var_factor) / 100;
+
   (void)xd;
 }
 
@@ -3747,11 +3744,39 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data,
       this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
     }
 
-    // Apply an adjustment to the rd value based on the similarity of the
-    // source variance and reconstructed variance.
     if (recon) {
+      // In film mode bias against DC pred and other intra if there is a
+      // significant difference between the variance of the sub blocks in the
+      // the source. Also apply some bias against compound modes which also
+      // tend to blur fine texture such as film grain over time.
+      //
+      // The sub block test here acts in the case where one or more sub
+      // blocks have high relatively variance but others relatively low
+      // variance. Here the high variance sub blocks may push the
+      // total variance for the current block size over the thresholds
+      // used in rd_variance_adjustment() below.
+      if (cpi->oxcf.content == VP9E_CONTENT_FILM) {
+        if (bsize >= BLOCK_16X16) {
+          int min_energy, max_energy;
+          vp9_get_sub_block_energy(cpi, x, mi_row, mi_col, bsize, &min_energy,
+                                   &max_energy);
+          if (max_energy > min_energy) {
+            if (ref_frame == INTRA_FRAME) {
+              if (this_mode == DC_PRED)
+                this_rd += (this_rd * (max_energy - min_energy));
+              else
+                this_rd += (this_rd * (max_energy - min_energy)) / 4;
+            } else if (second_ref_frame > INTRA_FRAME) {
+              this_rd += this_rd / 4;
+            }
+          }
+        }
+      }
+
+      // 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, recon, ref_frame,
-                             this_mode);
+                             second_ref_frame, this_mode);
     }
 
     if (ref_frame == INTRA_FRAME) {