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/decoder/decodeframe.c b/av1/decoder/decodeframe.c index 2a1a284..2b27499 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -2282,9 +2282,10 @@ #if CONFIG_LPF_SB if (USE_LOOP_FILTER_SUPERBLOCK) { // apply deblocking filtering right after each superblock is decoded - const int guess_filter_lvl = FAKE_FILTER_LEVEL; + const int filter_lvl = + cm->mi[mi_row * cm->mi_stride + mi_col].mbmi.filt_lvl; av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb, - guess_filter_lvl, 0, 1, mi_row, mi_col); + filter_lvl, 0, 1, mi_row, mi_col); } #endif // CONFIG_LPF_SB }
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