LPF_SB: select filter level and apply for superblock

For each superblock, select the best deblocking filter level and apply
filtering. The filter level is signaled to decoder using a delta based
scheme.

Change-Id: I53e32589cabac9e2a4e580808fdd39ac878fe8c6
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 12d69ee..3b83d0c 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2295,7 +2295,7 @@
   // send filter level for each superblock (64x64)
   if (bsize == cm->sb_size) {
     if (mi_row == 0 && mi_col == 0) {
-      aom_write_literal(w, cm->mi_grid_visible[0]->mbmi.filt_lvl, 6);
+      aom_write_literal(w, cm->mi[0].mbmi.filt_lvl, 6);
       cm->mi_grid_visible[0]->mbmi.reuse_sb_lvl = 0;
       cm->mi_grid_visible[0]->mbmi.delta = 0;
       cm->mi_grid_visible[0]->mbmi.sign = 0;
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 978300a..918eea1 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -52,6 +52,9 @@
 #endif
 #include "av1/encoder/ethread.h"
 #include "av1/encoder/extend.h"
+#if CONFIG_LPF_SB
+#include "av1/encoder/picklpf.h"
+#endif
 #include "av1/encoder/rd.h"
 #include "av1/encoder/rdopt.h"
 #include "av1/encoder/segmentation.h"
@@ -3503,9 +3506,25 @@
 #if CONFIG_LPF_SB
     if (USE_LOOP_FILTER_SUPERBLOCK) {
       // apply deblocking filtering right after each superblock is encoded.
-      const int guess_filter_lvl = FAKE_FILTER_LEVEL;
-      av1_loop_filter_frame(get_frame_new_buffer(cm), cm, xd, guess_filter_lvl,
-                            0, 1, mi_row, mi_col);
+      int last_lvl;
+      if (mi_row == 0 && mi_col == 0) {
+        last_lvl = 0;
+      } else {
+        if (mi_col == 0) {
+          last_lvl =
+              cm->mi[(mi_row - MAX_MIB_SIZE) * cm->mi_stride].mbmi.filt_lvl;
+        } else {
+          last_lvl = cm->mi[mi_row * cm->mi_stride + mi_col - MAX_MIB_SIZE]
+                         .mbmi.filt_lvl;
+        }
+      }
+      const int filter_lvl = av1_search_filter_level(cpi->source, cpi, 1, NULL,
+                                                     mi_row, mi_col, last_lvl);
+      av1_loop_filter_frame(get_frame_new_buffer(cm), cm, xd, filter_lvl, 0, 1,
+                            mi_row, mi_col);
+      // if filter_lvl is 0, we still need to set mi info
+      if (filter_lvl == 0)
+        av1_loop_filter_sb_level_init(cm, mi_row, mi_col, filter_lvl);
     }
 #endif  // CONFIG_LPF_SB
   }
@@ -3674,6 +3693,10 @@
 
   av1_init_tile_data(cpi);
 
+#if CONFIG_LPF_SB
+  cm->frame_to_show = get_frame_new_buffer(cm);
+#endif
+
   for (tile_row = 0; tile_row < cm->tile_rows; ++tile_row)
     for (tile_col = 0; tile_col < cm->tile_cols; ++tile_col)
       av1_encode_tile(cpi, &cpi->td, tile_row, tile_col);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 66bce63..d8c9037 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4657,7 +4657,11 @@
       || cm->single_tile_decoding
 #endif  // CONFIG_EXT_TILE
       ) {
+#if CONFIG_LPF_SB
+    if (!USE_LOOP_FILTER_SUPERBLOCK) no_loopfilter = 1;
+#else
     no_loopfilter = 1;
+#endif  // CONFIG_LPF_SB
 #if CONFIG_LOOP_RESTORATION
     no_restoration = 1;
 #endif  // CONFIG_LOOP_RESTORATION
@@ -4689,7 +4693,9 @@
 
     aom_usec_timer_start(&timer);
 
+#if !CONFIG_LPF_SB
     av1_pick_filter_level(cpi->source, cpi, cpi->sf.lpf_pick);
+#endif
 
     aom_usec_timer_mark(&timer);
     cpi->time_pick_lpf += aom_usec_timer_elapsed(&timer);
diff --git a/av1/encoder/picklpf.c b/av1/encoder/picklpf.c
index 0fcda6c..5b74efa 100644
--- a/av1/encoder/picklpf.c
+++ b/av1/encoder/picklpf.c
@@ -144,9 +144,9 @@
   return filt_err;
 }
 
-static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
-                               int partial_frame, double *best_cost_ret,
-                               int mi_row, int mi_col, int last_lvl) {
+int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
+                            int partial_frame, double *best_cost_ret,
+                            int mi_row, int mi_col, int last_lvl) {
   assert(partial_frame == 1);
   assert(last_lvl >= 0);
 
@@ -466,8 +466,13 @@
     // there're (FILT_BOUNDAR_OFFSET + 16) pixels.
     for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MAX_MIB_SIZE) {
       for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
+#if CONFIG_LPF_SB
+        int lvl =
+            av1_search_filter_level(sd, cpi, 1, NULL, mi_row, mi_col, last_lvl);
+#else
         int lvl =
             search_filter_level(sd, cpi, 1, NULL, mi_row, mi_col, last_lvl);
+#endif
         if (USE_LOOP_FILTER_SUPERBLOCK) lvl = FAKE_FILTER_LEVEL;
 
         av1_loop_filter_sb_level_init(cm, mi_row, mi_col, lvl);
diff --git a/av1/encoder/picklpf.h b/av1/encoder/picklpf.h
index 2a16835..9c04d7d 100644
--- a/av1/encoder/picklpf.h
+++ b/av1/encoder/picklpf.h
@@ -23,6 +23,11 @@
 int av1_get_max_filter_level(const AV1_COMP *cpi);
 void av1_pick_filter_level(const struct yv12_buffer_config *sd,
                            struct AV1_COMP *cpi, LPF_PICK_METHOD method);
+#if CONFIG_LPF_SB
+int av1_search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
+                            int partial_frame, double *best_cost_ret,
+                            int mi_row, int mi_col, int last_lvl);
+#endif  // CONFIG_LPF_SB
 #ifdef __cplusplus
 }  // extern "C"
 #endif