]> granicus.if.org Git - libvpx/commitdiff
Some minor improvements in bilateral filter expt.
authorDebargha Mukherjee <debargha@google.com>
Tue, 21 Apr 2015 16:29:56 +0000 (09:29 -0700)
committerDebargha Mukherjee <debargha@google.com>
Thu, 23 Apr 2015 01:09:42 +0000 (18:09 -0700)
Changes include:

* Uses double for RD cost computation to guard against overflow
for large resolution frames.
* Use previous frame's filter level to code the level better.
* Change precision of the filter parameters.
* Allow spatial variance for x and y to be different

Change-Id: I1669f65eb0ab1e8519962954c92d59e04f1277b7
derflr: +0.556% (a little up from before)

vp9/common/vp9_entropymode.c
vp9/common/vp9_loopfilter.c
vp9/common/vp9_loopfilter.h
vp9/decoder/vp9_decodeframe.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encoder.c
vp9/encoder/vp9_picklpf.c
vp9/encoder/vp9_rd.h

index 49c07a2646694fe1791e9a888c7f1acc0acc5d68..b2799b3aee25e35ec8c21ece8f8ba40b782d6772 100644 (file)
@@ -1257,6 +1257,10 @@ void vp9_setup_past_independence(VP9_COMMON *cm) {
 
   // To force update of the sharpness
   lf->last_sharpness_level = -1;
+#if CONFIG_LOOP_POSTFILTER
+  lf->bilateral_level = 0;
+  lf->last_bilateral_level = 0;
+#endif
 
   vp9_default_coef_probs(cm);
   vp9_init_mode_probs(&cm->fc);
index d086c4fccb0e455c466b06b337abf1c6170bb189..e8b734e36b9f75c7ee267ef838fe23561c601f3e 100644 (file)
@@ -242,7 +242,7 @@ int vp9_bilateral_level_bits(const VP9_COMMON *const cm) {
 
 int vp9_loop_bilateral_used(int level, int kf) {
   const bilateral_params_t param = vp9_bilateral_level_to_params(level, kf);
-  return (param.sigma_x && param.sigma_r);
+  return (param.sigma_x && param.sigma_y && param.sigma_r);
 }
 
 void vp9_loop_bilateral_init(loop_filter_info_n *lfi, int level, int kf) {
@@ -250,11 +250,14 @@ void vp9_loop_bilateral_init(loop_filter_info_n *lfi, int level, int kf) {
   lfi->bilateral_used = vp9_loop_bilateral_used(level, kf);
   if (lfi->bilateral_used) {
     if (param.sigma_x != lfi->bilateral_sigma_x_set ||
+        param.sigma_y != lfi->bilateral_sigma_y_set ||
         param.sigma_r != lfi->bilateral_sigma_r_set) {
       const int sigma_x = param.sigma_x;
+      const int sigma_y = param.sigma_y;
       const int sigma_r = param.sigma_r;
       const double sigma_r_d = (double)sigma_r / BILATERAL_PRECISION;
       const double sigma_x_d = (double)sigma_x / BILATERAL_PRECISION;
+      const double sigma_y_d = (double)sigma_y / BILATERAL_PRECISION;
       double *wr_lut_ = lfi->wr_lut + 255;
       double *wx_lut_ = lfi->wx_lut + BILATERAL_HALFWIN * (1 + BILATERAL_WIN);
       int i, x, y;
@@ -265,9 +268,11 @@ void vp9_loop_bilateral_init(loop_filter_info_n *lfi, int level, int kf) {
       for (y = -BILATERAL_HALFWIN; y <= BILATERAL_HALFWIN; y++)
         for (x = -BILATERAL_HALFWIN; x <= BILATERAL_HALFWIN; x++) {
           wx_lut_[y * BILATERAL_WIN + x] =
-              exp(-(x * x + y * y) / (2 * sigma_x_d * sigma_x_d));
+              exp(-(x * x) / (2 * sigma_x_d * sigma_x_d) -
+                   (y * y) / (2 * sigma_y_d * sigma_y_d));
         }
       lfi->bilateral_sigma_x_set = sigma_x;
+      lfi->bilateral_sigma_y_set = sigma_y;
       lfi->bilateral_sigma_r_set = sigma_r;
     }
   }
index 78aea1108f8915b553b6f1fe8b7d71703850a81a..3301035dce0e25e73c8d2c690b5cca70b7f2dda2 100644 (file)
@@ -38,49 +38,50 @@ struct VP9Common;
 #define BILATERAL_LEVELS        (1 << BILATERAL_LEVEL_BITS)
 #define DEF_BILATERAL_LEVEL     2
 
-#define BILATERAL_PRECISION     8
+#define BILATERAL_PRECISION     16
 #define BILATERAL_HALFWIN       3
 #define BILATERAL_WIN           (2 * BILATERAL_HALFWIN + 1)
 
 typedef struct bilateral_params {
-  int sigma_x;  // spatial variance
+  int sigma_x;  // spatial variance x
+  int sigma_y;  // spatial variance y
   int sigma_r;  // range variance
 } bilateral_params_t;
 
 static bilateral_params_t
     bilateral_level_to_params_arr[BILATERAL_LEVELS + 1] = {
-  // Values are rounded to 1/8 th precision
-  {0, 0},    // 0 - default
-  {4, 16},
-  {5, 16},
-  {6, 16},
-  {7, 16},
-  {9, 18},
-  {12, 20},
-  {16, 20},
-  {20, 20},
+  // Values are rounded to 1/16 th precision
+  {0, 0, 0},    // 0 - default
+  {8, 9, 30},
+  {9, 8, 30},
+  {9, 11, 32},
+  {11, 9, 32},
+  {14, 14, 32},
+  {18, 18, 36},
+  {24, 24, 40},
+  {32, 32, 40},
 };
 
 static bilateral_params_t
     bilateral_level_to_params_arr_kf[BILATERAL_LEVELS_KF + 1] = {
-  // Values are rounded to 1/8 th precision
-  {0, 0},    // 0 - default
-  {4, 16},
-  {5, 16},
-  {6, 16},
-  {7, 16},
-  {9, 18},
-  {12, 20},
-  {15, 22},
-  {18, 24},
-  {21, 24},
-  {24, 24},
-  {24, 28},
-  {28, 24},
-  {28, 28},
-  {28, 32},
-  {32, 24},
-  {32, 28},
+  // Values are rounded to 1/16 th precision
+  {0, 0, 0},    // 0 - default
+  {8, 8, 30},
+  {9, 9, 32},
+  {10, 10, 32},
+  {12, 12, 32},
+  {14, 14, 32},
+  {18, 18, 36},
+  {24, 24, 40},
+  {30, 30, 44},
+  {36, 36, 48},
+  {42, 42, 48},
+  {48, 48, 48},
+  {48, 48, 56},
+  {56, 56, 48},
+  {56, 56, 56},
+  {56, 56, 64},
+  {64, 64, 48},
 };
 
 int vp9_bilateral_level_bits(const struct VP9Common *const cm);
@@ -112,6 +113,7 @@ struct loopfilter {
 
 #if CONFIG_LOOP_POSTFILTER
   int bilateral_level;
+  int last_bilateral_level;
 #endif
 };
 
@@ -130,6 +132,7 @@ typedef struct {
   double wx_lut[BILATERAL_WIN * BILATERAL_WIN];
   double wr_lut[512];
   int bilateral_sigma_x_set;
+  int bilateral_sigma_y_set;
   int bilateral_sigma_r_set;
   int bilateral_used;
 #endif
index 8fd4a3e9d791e57305876239b6cace5fc1dfb70c..b8d740eda7fcd0df9f05908e3bb1d7249b32675f 100644 (file)
@@ -1631,9 +1631,15 @@ static void setup_loopfilter(VP9_COMMON *cm,
 #if CONFIG_LOOP_POSTFILTER
   lf->bilateral_level = vp9_rb_read_bit(rb);
   if (lf->bilateral_level) {
-    lf->bilateral_level += vp9_rb_read_literal(
-        rb, vp9_bilateral_level_bits(cm));
+    int level = vp9_rb_read_literal(rb, vp9_bilateral_level_bits(cm));
+    lf->bilateral_level = level + (level >= lf->last_bilateral_level);
+  } else {
+    lf->bilateral_level = lf->last_bilateral_level;
   }
+  if (cm->frame_type != KEY_FRAME)
+    cm->lf.last_bilateral_level = cm->lf.bilateral_level;
+  else
+    cm->lf.last_bilateral_level = 0;
 #endif  // CONFIG_LOOP_POSTFILTER
 }
 
@@ -2377,6 +2383,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
       }
     }
   }
+
 #if CONFIG_VP9_HIGHBITDEPTH
   get_frame_new_buffer(cm)->bit_depth = cm->bit_depth;
 #endif
index 8f9e01634b9a64ad69f89be976571ea6c02aa5d6..1d5fb43af7fb71536bb829c23b8b59d6a6b4ccdc 100644 (file)
@@ -1527,10 +1527,13 @@ static void encode_loopfilter(VP9_COMMON *cm,
     }
   }
 #if CONFIG_LOOP_POSTFILTER
-  vp9_wb_write_bit(wb, lf->bilateral_level > 0);
-  if (lf->bilateral_level > 0)
-    vp9_wb_write_literal(wb, lf->bilateral_level - 1,
+  vp9_wb_write_bit(wb, lf->bilateral_level != lf->last_bilateral_level);
+  if (lf->bilateral_level != lf->last_bilateral_level) {
+    int level = lf->bilateral_level -
+                (lf->bilateral_level > lf->last_bilateral_level);
+    vp9_wb_write_literal(wb, level,
                          vp9_bilateral_level_bits(cm));
+  }
 #endif  // CONFIG_LOOP_POSTFILTER
 }
 
index a822b3e8b1f274c451a2ce78d1be34369924dfc3..f5a462790994441d0484c8b9bc2a2c1907abc119 100644 (file)
@@ -3423,6 +3423,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
   // Pick the loop filter level for the frame.
   loopfilter_frame(cpi, cm);
 
+  // printf("Bilateral level: %d\n", cm->lf.bilateral_level);
+
   // build the bitstream
   vp9_pack_bitstream(cpi, dest, size);
 
@@ -3463,6 +3465,13 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
 
   cm->last_frame_type = cm->frame_type;
 
+#if CONFIG_LOOP_POSTFILTER
+  if (cm->frame_type != KEY_FRAME)
+    cm->lf.last_bilateral_level = cm->lf.bilateral_level;
+  else
+    cm->lf.last_bilateral_level = 0;
+#endif
+
   if (!(is_two_pass_svc(cpi) && cpi->svc.encode_empty_frame_state == ENCODING))
     vp9_rc_postencode_update(cpi, *size);
 
index 1da6c32e5c397b38e3cf2933f7842922731cd464..e225bd9a636230271a3dc6fca825df3028ec53c7 100644 (file)
@@ -87,15 +87,16 @@ static int try_bilateral_frame(const YV12_BUFFER_CONFIG *sd,
 static int64_t search_bilateral_level(const YV12_BUFFER_CONFIG *sd,
                                       VP9_COMP *cpi,
                                       int filter_level, int partial_frame,
-                                      int64_t *best_cost_ret) {
+                                      double *best_cost_ret) {
   VP9_COMMON *const cm = &cpi->common;
   int i, bilateral_best, err;
-  int64_t best_cost;
-  int64_t cost[BILATERAL_LEVELS_KF];
+  double best_cost;
+  double cost[BILATERAL_LEVELS_KF];
   const int bilateral_level_bits = vp9_bilateral_level_bits(&cpi->common);
   const int bilateral_levels = 1 << bilateral_level_bits;
 #ifdef USE_RD_LOOP_POSTFILTER_SEARCH
   MACROBLOCK *x = &cpi->mb;
+  int bits;
 #endif
 
   //  Make a copy of the unfiltered / processed recon buffer
@@ -107,9 +108,10 @@ static int64_t search_bilateral_level(const YV12_BUFFER_CONFIG *sd,
   bilateral_best = 0;
   err = try_bilateral_frame(sd, cpi, 0, partial_frame);
 #ifdef USE_RD_LOOP_POSTFILTER_SEARCH
-  cost[0] = RDCOST(x->rdmult, x->rddiv, 0, err);
+  bits = cm->lf.last_bilateral_level == 0 ? 0 : bilateral_level_bits;
+  cost[0] = RDCOST_DBL(x->rdmult, x->rddiv, (bits << 2), err);
 #else
-  cost[0] = err;
+  cost[0] = (double)err;
 #endif
   best_cost = cost[0];
   for (i = 1; i <= bilateral_levels; ++i) {
@@ -118,10 +120,10 @@ static int64_t search_bilateral_level(const YV12_BUFFER_CONFIG *sd,
     // Normally the rate is rate in bits * 256 and dist is sum sq err * 64
     // when RDCOST is used.  However below we just scale both in the correct
     // ratios appropriately but not exactly by these values.
-    cost[i] = RDCOST(x->rdmult, x->rddiv,
-                     bilateral_level_bits << 2, err);
+    bits = cm->lf.last_bilateral_level == i ? 0 : bilateral_level_bits;
+    cost[i] = RDCOST_DBL(x->rdmult, x->rddiv, (bits << 2), err);
 #else
-    cost[i] = err;
+    cost[i] = (double)err;
 #endif
     if (cost[i] < best_cost) {
       bilateral_best = i;
@@ -144,18 +146,19 @@ static int search_filter_bilateral_level(const YV12_BUFFER_CONFIG *sd,
   const int max_filter_level = get_max_filter_level(cpi);
   int filt_direction = 0;
   int filt_best, bilateral_best;
-  int64_t best_err;
+  double best_err;
+  int i;
 
   // Start the search at the previous frame filter level unless it is now out of
   // range.
   int filt_mid = clamp(lf->filter_level, min_filter_level, max_filter_level);
   int filter_step = filt_mid < 16 ? 4 : filt_mid / 4;
-  // Sum squared error at each filter level
-  int64_t ss_err[MAX_LOOP_FILTER + 1];
+  double ss_err[MAX_LOOP_FILTER + 1];
   int bilateral;
 
   // Set each entry to -1
-  vpx_memset(ss_err, 0xFF, sizeof(ss_err));
+  for (i = 0; i <= MAX_LOOP_FILTER; ++i)
+    ss_err[i] = -1.0;
 
   bilateral = search_bilateral_level(sd, cpi, filt_mid,
                                      partial_frame, &best_err);
@@ -168,14 +171,14 @@ static int search_filter_bilateral_level(const YV12_BUFFER_CONFIG *sd,
     const int filt_low = MAX(filt_mid - filter_step, min_filter_level);
 
     // Bias against raising loop filter in favor of lowering it.
-    int64_t bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
+    double bias = (best_err / (1 << (15 - (filt_mid / 8)))) * filter_step;
 
     if ((cpi->oxcf.pass == 2) && (cpi->twopass.section_intra_rating < 20))
       bias = (bias * cpi->twopass.section_intra_rating) / 20;
 
     // yx, bias less for large block size
     if (cm->tx_mode != ONLY_4X4)
-      bias >>= 1;
+      bias /= 2;
 
     if (filt_direction <= 0 && filt_low != filt_mid) {
       // Get Low filter error score
index 6383f556bec78aced7b29d89538bbdcce96f24a2..b20f84332860ab97e13306e98481196c0afc9cd1 100644 (file)
@@ -25,10 +25,10 @@ extern "C" {
 #define RDDIV_BITS          7
 
 #define RDCOST(RM, DM, R, D) \
-  (((128 + ((int64_t)R) * (RM)) >> 8) + (D << DM))
+  (((128 + ((int64_t)R) * (RM)) >> 8) + ((D) << (DM)))
 
 #define RDCOST_DBL(RM, DM, R, D) \
-  (((((double)R) * (RM)) / 256.0) + ((double)D  * (1 << DM)))
+  (((((double)(R)) * (RM)) / 256.0) + ((double)(D)  * (1 << (DM))))
 
 #define QIDX_SKIP_THRESH     115