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