shithub: libvpx

Download patch

ref: 8a2fc54508801f6f4c17c69b3e7f8240993e2f05
parent: dc9d36c0a6c749616d5543aa208864d7b0181fea
author: Marco <[email protected]>
date: Mon Oct 26 10:56:46 EDT 2015

Adjustments to vp9-denoising.

Adjust variance threshold, delta-qp, and intra penalty cost,
based on estimated noise level in source.

Replace denoising_on with a level value=L/M/H.

Change-Id: I0c017dae75a5d897367d2c42dec26f2f37e447c1

--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -486,10 +486,17 @@
   // Account for larger interval on base layer for temporal layers.
   if (cr->percent_refresh > 0 &&
       rc->frames_since_key <  (4 * cpi->svc.number_temporal_layers) *
-      (100 / cr->percent_refresh))
+      (100 / cr->percent_refresh)) {
     cr->rate_ratio_qdelta = 3.0;
-  else
+  } else {
     cr->rate_ratio_qdelta = 2.0;
+#if CONFIG_VP9_TEMPORAL_DENOISING
+  if (cpi->oxcf.noise_sensitivity > 0 &&
+      cpi->denoiser.denoising_level >= kMedium)
+    // Reduce the delta-qp if the estimated source noise is above threshold.
+    cr->rate_ratio_qdelta = 1.5;
+#endif
+  }
   // Adjust some parameters for low resolutions at low bitrates.
   if (cm->width <= 352 &&
       cm->height <= 288 &&
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -323,7 +323,7 @@
   struct buf_2d src = mb->plane[0].src;
   int is_skin = 0;
 
-  if (bs <= BLOCK_16X16 && denoiser->denoising_on) {
+  if (bs <= BLOCK_16X16 && denoiser->denoising_level >= kMedium) {
     // Take center pixel in block to determine is_skin.
     const int y_width_shift = (4 << b_width_log2_lookup[bs]) >> 1;
     const int y_height_shift = (4 << b_height_log2_lookup[bs]) >> 1;
@@ -340,7 +340,7 @@
     is_skin = vp9_skin_pixel(ysource, usource, vsource);
   }
 
-  if (denoiser->denoising_on)
+  if (denoiser->denoising_level >= kMedium)
     decision = perform_motion_compensation(denoiser, mb, bs,
                                            denoiser->increase_denoising,
                                            mi_row, mi_col, ctx,
@@ -523,8 +523,8 @@
                                       int height) {
   // Denoiser is off by default, i.e., no denoising is performed.
   // Noise level is measured periodically, and if observed to be above
-  // thresh_noise_estimate, then denoising is performed, i.e., denoising_on = 1.
-  denoiser->denoising_on = 0;
+  // thresh_noise_estimate, then denoising is performed.
+  denoiser->denoising_level = kLow;
   denoiser->noise_estimate = 0;
   denoiser->noise_estimate_count = 0;
   denoiser->thresh_noise_estimate = 20;
@@ -651,10 +651,15 @@
       if (cpi->denoiser.noise_estimate_count == num_frames_estimate) {
         // Reset counter and check noise level condition.
         cpi->denoiser.noise_estimate_count = 0;
-       if (cpi->denoiser.noise_estimate > cpi->denoiser.thresh_noise_estimate)
-         cpi->denoiser.denoising_on = 1;
-       else
-         cpi->denoiser.denoising_on = 0;
+        if (cpi->denoiser.noise_estimate >
+            (cpi->denoiser.thresh_noise_estimate << 1))
+          cpi->denoiser.denoising_level = kHigh;
+        else
+          if (cpi->denoiser.noise_estimate >
+              cpi->denoiser.thresh_noise_estimate)
+            cpi->denoiser.denoising_level = kMedium;
+          else
+            cpi->denoiser.denoising_level = kLow;
       }
     }
   }
--- a/vp9/encoder/vp9_denoiser.h
+++ b/vp9/encoder/vp9_denoiser.h
@@ -26,6 +26,12 @@
   FILTER_BLOCK
 } VP9_DENOISER_DECISION;
 
+typedef enum vp9_denoiser_level {
+  kLow,
+  kMedium,
+  kHigh
+} VP9_DENOISER_LEVEL;
+
 typedef struct vp9_denoiser {
   YV12_BUFFER_CONFIG running_avg_y[MAX_REF_FRAMES];
   YV12_BUFFER_CONFIG mc_running_avg_y;
@@ -32,7 +38,7 @@
   YV12_BUFFER_CONFIG last_source;
   int increase_denoising;
   int frame_buffer_initialized;
-  int denoising_on;
+  VP9_DENOISER_LEVEL denoising_level;
   int noise_estimate;
   int thresh_noise_estimate;
   int noise_estimate_count;
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -481,7 +481,7 @@
   VP9_COMMON *const cm = &cpi->common;
   const int is_key_frame = (cm->frame_type == KEY_FRAME);
   const int threshold_multiplier = is_key_frame ? 20 : 1;
-  const int64_t threshold_base = (int64_t)(threshold_multiplier *
+  int64_t threshold_base = (int64_t)(threshold_multiplier *
       cpi->y_dequant[q][1]);
   if (is_key_frame) {
     thresholds[0] = threshold_base;
@@ -489,6 +489,16 @@
     thresholds[2] = threshold_base >> 2;
     thresholds[3] = threshold_base << 2;
   } else {
+#if CONFIG_VP9_TEMPORAL_DENOISING
+  if (cpi->oxcf.noise_sensitivity > 0) {
+    // Increase base variance threshold is estimated noise level is high.
+    if (cpi->denoiser.denoising_level == kHigh)
+      threshold_base = threshold_base << 2;
+    else
+      if (cpi->denoiser.denoising_level == kMedium)
+        threshold_base = threshold_base << 1;
+  }
+#endif
     thresholds[1] = threshold_base;
     if (cm->width <= 352 && cm->height <= 288) {
       thresholds[0] = threshold_base >> 2;
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -1068,6 +1068,21 @@
     {GOLDEN_FRAME, NEWMV}
 };
 
+int set_intra_cost_penalty(const VP9_COMP *const cpi, BLOCK_SIZE bsize) {
+  const VP9_COMMON *const cm = &cpi->common;
+  // Reduce the intra cost penalty for small blocks (<=16x16).
+  int reduction_fac =
+      (bsize <= BLOCK_16X16) ? ((bsize <= BLOCK_8X8) ? 4 : 2) : 0;
+#if CONFIG_VP9_TEMPORAL_DENOISING
+  if (cpi->oxcf.noise_sensitivity > 0 &&
+      cpi->denoiser.denoising_level == kHigh)
+     // Don't reduce intra cost penalty if estimated noise level is high.
+     reduction_fac = 0;
+#endif
+  return vp9_get_intra_cost_penalty(
+      cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth) >> reduction_fac;
+}
+
 // TODO(jingning) placeholder for inter-frame non-RD mode decision.
 // this needs various further optimizations. to be continued..
 void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
@@ -1094,11 +1109,7 @@
   // var_y and sse_y are saved to be used in skipping checking
   unsigned int var_y = UINT_MAX;
   unsigned int sse_y = UINT_MAX;
-  // Reduce the intra cost penalty for small blocks (<=16x16).
-  const int reduction_fac = (bsize <= BLOCK_16X16) ?
-      ((bsize <= BLOCK_8X8) ? 4 : 2) : 0;
-  const int intra_cost_penalty = vp9_get_intra_cost_penalty(
-      cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth) >> reduction_fac;
+  const int intra_cost_penalty = set_intra_cost_penalty(cpi, bsize);
   const int64_t inter_mode_thresh = RDCOST(x->rdmult, x->rddiv,
                                            intra_cost_penalty, 0);
   const int *const rd_threshes = cpi->rd.threshes[mbmi->segment_id][bsize];