Make lpf_sb work with loopfilter_level Make lpf_sb compatible with loopfilter_level, when USE_GUESS_LEVEL = 1. Filter levels will be selected based on q index and applied for filtering on Y, U, V planes separately. Current model only allows to guess one filter level. Now Y_vert = Y_horz = U = V. In the future, we need to retrain the model and get filter levels for Y_vert, Y_horz, U and V separately. When USE_GUESS_LEVEL = 0, lpf_sb can't work with loopfilter_level yet. Change-Id: Icd774a147c07a4035cf8204a8754b2a99668bbfd
diff --git a/av1/common/av1_loopfilter.c b/av1/common/av1_loopfilter.c index d563aaf..43941cf 100644 --- a/av1/common/av1_loopfilter.c +++ b/av1/common/av1_loopfilter.c
@@ -350,8 +350,13 @@ #endif const MB_MODE_INFO *mbmi) { #if CONFIG_LPF_SB +#if CONFIG_LOOPFILTER_LEVEL + const int lvl_idx = plane == 0 ? dir_idx : plane + 1; + return cm->mi[mi_row * cm->mi_stride + mi_col].mbmi.filt_lvl[lvl_idx]; +#else return cm->mi[mi_row * cm->mi_stride + mi_col].mbmi.filt_lvl; #endif +#endif const int segment_id = mbmi->segment_id; if (cm->delta_lf_present_flag) { @@ -429,6 +434,9 @@ #if CONFIG_LPF_SB void av1_loop_filter_sb_level_init(AV1_COMMON *cm, int mi_row, int mi_col, +#if CONFIG_LOOPFILTER_LEVEL + int plane, int dir, +#endif int lvl) { const int mi_row_start = AOMMAX(0, mi_row - FILT_BOUNDARY_MI_OFFSET); const int mi_col_start = AOMMAX(0, mi_col - FILT_BOUNDARY_MI_OFFSET); @@ -440,9 +448,14 @@ int row, col; for (row = mi_row_start; row < mi_row_end; ++row) { for (col = mi_col_start; col < mi_col_end; ++col) { - // Note: can't use cm->mi_grid_visible. Because for each partition, - // all visible pointers will point to the first of the partition. +// Note: can't use cm->mi_grid_visible. Because for each partition, +// all visible pointers will point to the first of the partition. +#if CONFIG_LOOPFILTER_LEVEL + const int lvl_idx = plane == 0 ? dir : plane + 1; + cm->mi[row * cm->mi_stride + col].mbmi.filt_lvl[lvl_idx] = lvl; +#else cm->mi[row * cm->mi_stride + col].mbmi.filt_lvl = lvl; +#endif // CONFIG_LOOPFILTER_LEVEL } } } @@ -939,7 +952,11 @@ txsize_vert_map[uv_txsize_lookup[block_size][mbmi->tx_size][1][1]]; #if CONFIG_EXT_DELTA_Q #if CONFIG_LOOPFILTER_LEVEL +#if CONFIG_LPF_SB + const int filter_level = get_filter_level(cm, lfi_n, 0, 0, 0, 0, mbmi); +#else const int filter_level = get_filter_level(cm, lfi_n, 0, 0, mbmi); +#endif #else #if CONFIG_LPF_SB const int filter_level = get_filter_level(cm, lfi_n, 0, 0, mbmi); @@ -1033,7 +1050,11 @@ const BLOCK_SIZE block_size = mbmi->sb_type; #if CONFIG_EXT_DELTA_Q #if CONFIG_LOOPFILTER_LEVEL +#if CONFIG_LPF_SB + const int filter_level = get_filter_level(cm, lfi_n, 0, 0, 0, 0, mbmi); +#else const int filter_level = get_filter_level(cm, lfi_n, 0, 0, mbmi); +#endif #else #if CONFIG_LPF_SB const int filter_level = get_filter_level(cm, lfi_n, 0, 0, mbmi); @@ -1507,8 +1528,13 @@ // Filter level can vary per MI #if CONFIG_EXT_DELTA_Q #if CONFIG_LOOPFILTER_LEVEL +#if CONFIG_LPF_SB + if (!(lfl_r[c_step] = get_filter_level(cm, &cm->lf_info, 0, 0, 0, 0, mbmi))) + continue; +#else if (!(lfl_r[c_step] = get_filter_level(cm, &cm->lf_info, 0, 0, mbmi))) continue; +#endif #else #if CONFIG_LPF_SB if (!(lfl_r[c_step] = @@ -2169,8 +2195,13 @@ #if CONFIG_EXT_DELTA_Q #if CONFIG_LOOPFILTER_LEVEL +#if CONFIG_LPF_SB + const uint32_t curr_level = get_filter_level(cm, &cm->lf_info, edge_dir, + plane, mi_row, mi_col, mbmi); +#else const uint32_t curr_level = get_filter_level(cm, &cm->lf_info, edge_dir, plane, mbmi); +#endif #else #if CONFIG_LPF_SB const uint32_t curr_level = @@ -2211,8 +2242,14 @@ #if CONFIG_EXT_DELTA_Q #if CONFIG_LOOPFILTER_LEVEL +#if CONFIG_LPF_SB + const uint32_t pv_lvl = + get_filter_level(cm, &cm->lf_info, edge_dir, plane, mi_row, + mi_col, &mi_prev->mbmi); +#else const uint32_t pv_lvl = get_filter_level(cm, &cm->lf_info, edge_dir, plane, &mi_prev->mbmi); +#endif #else #if CONFIG_LPF_SB const uint32_t pv_lvl = get_filter_level(cm, &cm->lf_info, pv_row, @@ -2620,8 +2657,12 @@ #endif #if CONFIG_LPF_SB - if (partial_frame && !frame_filter_level) return; +#if CONFIG_LOOPFILTER_LEVEL + if (partial_frame && !frame_filter_level && !frame_filter_level_r) return; #else + if (partial_frame && !frame_filter_level) return; +#endif // CONFIG_LOOPFILTER_LEVEL +#else // !CONFIG_LPF_SB #if CONFIG_LOOPFILTER_LEVEL if (!frame_filter_level && !frame_filter_level_r) return; #else @@ -2645,7 +2686,14 @@ end_mi_row = AOMMIN(mi_row_range, cm->mi_rows); end_mi_col = AOMMIN(mi_col_range, cm->mi_cols); +#if CONFIG_LOOPFILTER_LEVEL + av1_loop_filter_sb_level_init(cm, mi_row, mi_col, y_only, 0, + frame_filter_level); + av1_loop_filter_sb_level_init(cm, mi_row, mi_col, y_only, 1, + frame_filter_level_r); +#else av1_loop_filter_sb_level_init(cm, mi_row, mi_col, frame_filter_level); +#endif } else { start_mi_row = 0; mi_rows_to_filter = cm->mi_rows;
diff --git a/av1/common/av1_loopfilter.h b/av1/common/av1_loopfilter.h index 75dda7d..78305ec 100644 --- a/av1/common/av1_loopfilter.h +++ b/av1/common/av1_loopfilter.h
@@ -148,6 +148,9 @@ #if CONFIG_LPF_SB void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm, struct macroblockd *mbd, int filter_level, +#if CONFIG_LOOPFILTER_LEVEL + int frame_filter_level_r, +#endif int y_only, int partial_frame, int mi_row, int mi_col); @@ -158,6 +161,9 @@ int col_start, int col_end, int y_only); void av1_loop_filter_sb_level_init(struct AV1Common *cm, int mi_row, int mi_col, +#if CONFIG_LOOPFILTER_LEVEL + int plane, int dir, +#endif int lvl); #else void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm,
diff --git a/av1/common/blockd.h b/av1/common/blockd.h index 1cd667a..b2465ea 100644 --- a/av1/common/blockd.h +++ b/av1/common/blockd.h
@@ -356,11 +356,19 @@ BOUNDARY_TYPE boundary_info; #if CONFIG_LPF_SB +#if CONFIG_LOOPFILTER_LEVEL + // 0: y plane vert, 1: y plane horz, 2: u plane, 3: v plane + uint8_t filt_lvl[4]; + int reuse_sb_lvl[4]; + int sign[4]; + int delta[4]; +#else uint8_t filt_lvl; int reuse_sb_lvl; int sign; int delta; -#endif +#endif // CONFIG_LOOPFILTER_LEVEL +#endif // CONFIG_LPF_SB #if CONFIG_JNT_COMP int compound_idx;
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c index f211b9d..47c22b8 100644 --- a/av1/common/entropymode.c +++ b/av1/common/entropymode.c
@@ -2829,6 +2829,64 @@ #endif // CONFIG_KF_CTX #if CONFIG_LPF_SB +#if CONFIG_LOOPFILTER_LEVEL +static const aom_cdf_prob + default_lpf_reuse_cdf[4][LPF_REUSE_CONTEXT][CDF_SIZE(2)] = { + { { AOM_CDF2(4259) }, { AOM_CDF2(728) } }, + { { AOM_CDF2(4259) }, { AOM_CDF2(728) } }, + { { AOM_CDF2(4259) }, { AOM_CDF2(728) } }, + { { AOM_CDF2(4259) }, { AOM_CDF2(728) } }, + }; + +static const aom_cdf_prob + default_lpf_delta_cdf[4][LPF_DELTA_CONTEXT][CDF_SIZE(DELTA_RANGE)] = { + { { AOM_CDF8(100, 688, 2128, 4642, 7895, 11851, 17050) }, + { AOM_CDF8(100, 1291, 4358, 7425, 10654, 13559, 18563) }, + { AOM_CDF8(100, 1086, 4982, 9134, 13031, 16991, 23123) }, + { AOM_CDF8(100, 1068, 3395, 7973, 12512, 17967, 22812) }, + { AOM_CDF8(100, 442, 2809, 7178, 12535, 17450, 22417) }, + { AOM_CDF8(100, 561, 2246, 6050, 11103, 16592, 21353) }, + { AOM_CDF8(100, 345, 2399, 5559, 9682, 13992, 20126) }, + { AOM_CDF8(100, 337, 1540, 3573, 6438, 10196, 16320) } }, + { { AOM_CDF8(100, 688, 2128, 4642, 7895, 11851, 17050) }, + { AOM_CDF8(100, 1291, 4358, 7425, 10654, 13559, 18563) }, + { AOM_CDF8(100, 1086, 4982, 9134, 13031, 16991, 23123) }, + { AOM_CDF8(100, 1068, 3395, 7973, 12512, 17967, 22812) }, + { AOM_CDF8(100, 442, 2809, 7178, 12535, 17450, 22417) }, + { AOM_CDF8(100, 561, 2246, 6050, 11103, 16592, 21353) }, + { AOM_CDF8(100, 345, 2399, 5559, 9682, 13992, 20126) }, + { AOM_CDF8(100, 337, 1540, 3573, 6438, 10196, 16320) } }, + { { AOM_CDF8(100, 688, 2128, 4642, 7895, 11851, 17050) }, + { AOM_CDF8(100, 1291, 4358, 7425, 10654, 13559, 18563) }, + { AOM_CDF8(100, 1086, 4982, 9134, 13031, 16991, 23123) }, + { AOM_CDF8(100, 1068, 3395, 7973, 12512, 17967, 22812) }, + { AOM_CDF8(100, 442, 2809, 7178, 12535, 17450, 22417) }, + { AOM_CDF8(100, 561, 2246, 6050, 11103, 16592, 21353) }, + { AOM_CDF8(100, 345, 2399, 5559, 9682, 13992, 20126) }, + { AOM_CDF8(100, 337, 1540, 3573, 6438, 10196, 16320) } }, + { { AOM_CDF8(100, 688, 2128, 4642, 7895, 11851, 17050) }, + { AOM_CDF8(100, 1291, 4358, 7425, 10654, 13559, 18563) }, + { AOM_CDF8(100, 1086, 4982, 9134, 13031, 16991, 23123) }, + { AOM_CDF8(100, 1068, 3395, 7973, 12512, 17967, 22812) }, + { AOM_CDF8(100, 442, 2809, 7178, 12535, 17450, 22417) }, + { AOM_CDF8(100, 561, 2246, 6050, 11103, 16592, 21353) }, + { AOM_CDF8(100, 345, 2399, 5559, 9682, 13992, 20126) }, + { AOM_CDF8(100, 337, 1540, 3573, 6438, 10196, 16320) } }, + }; + +static const aom_cdf_prob + default_lpf_sign_cdf[4][LPF_REUSE_CONTEXT][LPF_SIGN_CONTEXT][CDF_SIZE(2)] = + { + { { { AOM_CDF2(100) }, { AOM_CDF2(11932) } }, + { { AOM_CDF2(14785) }, { AOM_CDF2(8145) } } }, + { { { AOM_CDF2(100) }, { AOM_CDF2(11932) } }, + { { AOM_CDF2(14785) }, { AOM_CDF2(8145) } } }, + { { { AOM_CDF2(100) }, { AOM_CDF2(11932) } }, + { { AOM_CDF2(14785) }, { AOM_CDF2(8145) } } }, + { { { AOM_CDF2(100) }, { AOM_CDF2(11932) } }, + { { AOM_CDF2(14785) }, { AOM_CDF2(8145) } } }, + }; +#else static const aom_cdf_prob default_lpf_reuse_cdf[LPF_REUSE_CONTEXT][CDF_SIZE( 2)] = { { AOM_CDF2(4259) }, { AOM_CDF2(728) } }; @@ -2847,6 +2905,7 @@ { { AOM_CDF2(100) }, { AOM_CDF2(11932) } }, { { AOM_CDF2(14785) }, { AOM_CDF2(8145) } } }; +#endif // CONFIG_LOOPFILTER_LEVEL #endif // CONFIG_LPF_SB #if CONFIG_EXT_INTRA_MOD
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h index acb23c8..9b9f156 100644 --- a/av1/common/entropymode.h +++ b/av1/common/entropymode.h
@@ -319,9 +319,16 @@ aom_cdf_prob cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CDF_SIZE(CFL_ALPHABET_SIZE)]; #endif #if CONFIG_LPF_SB +#if CONFIG_LOOPFILTER_LEVEL + aom_cdf_prob lpf_reuse_cdf[4][LPF_REUSE_CONTEXT][CDF_SIZE(2)]; + aom_cdf_prob lpf_delta_cdf[4][LPF_DELTA_CONTEXT][CDF_SIZE(DELTA_RANGE)]; + aom_cdf_prob lpf_sign_cdf[4][LPF_REUSE_CONTEXT][LPF_SIGN_CONTEXT] + [CDF_SIZE(2)]; +#else aom_cdf_prob lpf_reuse_cdf[LPF_REUSE_CONTEXT][CDF_SIZE(2)]; aom_cdf_prob lpf_delta_cdf[LPF_DELTA_CONTEXT][CDF_SIZE(DELTA_RANGE)]; aom_cdf_prob lpf_sign_cdf[LPF_REUSE_CONTEXT][LPF_SIGN_CONTEXT][CDF_SIZE(2)]; +#endif #endif // CONFIG_LPF_SB } FRAME_CONTEXT; @@ -429,9 +436,15 @@ [FILTER_INTRA_MODES]; #endif // CONFIG_FILTER_INTRA #if CONFIG_LPF_SB +#if CONFIG_LOOPFILTER_LEVEL + unsigned int lpf_reuse[4][LPF_REUSE_CONTEXT][2]; + unsigned int lpf_delta[4][LPF_DELTA_CONTEXT][DELTA_RANGE]; + unsigned int lpf_sign[4][LPF_REUSE_CONTEXT][LPF_SIGN_CONTEXT][2]; +#else unsigned int lpf_reuse[LPF_REUSE_CONTEXT][2]; unsigned int lpf_delta[LPF_DELTA_CONTEXT][DELTA_RANGE]; unsigned int lpf_sign[LPF_REUSE_CONTEXT][LPF_SIGN_CONTEXT][2]; +#endif // CONFIG_LOOPFILTER_LEVEL #endif // CONFIG_LPF_SB } FRAME_COUNTS;
diff --git a/av1/common/enums.h b/av1/common/enums.h index 3425c97..2d6184b 100644 --- a/av1/common/enums.h +++ b/av1/common/enums.h
@@ -106,7 +106,7 @@ #define FILT_BOUNDARY_OFFSET 0 #define FILT_BOUNDARY_MI_OFFSET (FILT_BOUNDARY_OFFSET >> MI_SIZE_LOG2) -#define USE_GUESS_LEVEL 0 +#define USE_GUESS_LEVEL 1 #define USE_LOOP_FILTER_SUPERBLOCK 1 #endif // CONFIG_LPF_SB
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index ef5f370..2c9128b 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -792,6 +792,77 @@ #endif // CONFIG_EXT_PARTITION_TYPES #if CONFIG_LPF_SB +#if CONFIG_LOOPFILTER_LEVEL + if (bsize == cm->sb_size && !USE_GUESS_LEVEL) { + int lvl_idx; + int filt_lvl[4]; + if (mi_row == 0 && mi_col == 0) { + filt_lvl[0] = aom_read_literal(r, 6, ACCT_STR); + filt_lvl[1] = aom_read_literal(r, 6, ACCT_STR); + if (filt_lvl[0] || filt_lvl[1]) { + filt_lvl[2] = aom_read_literal(r, 6, ACCT_STR); + filt_lvl[3] = aom_read_literal(r, 6, ACCT_STR); + } + for (lvl_idx = 0; lvl_idx < 4; ++lvl_idx) { + cm->mi_grid_visible[0]->mbmi.reuse_sb_lvl[lvl_idx] = 0; + cm->mi_grid_visible[0]->mbmi.delta[lvl_idx] = 0; + cm->mi_grid_visible[0]->mbmi.sign[lvl_idx] = 0; + } + } else { + int prev_mi_row, prev_mi_col; + if (mi_col - MAX_MIB_SIZE < 0) { + prev_mi_row = mi_row - MAX_MIB_SIZE; + prev_mi_col = mi_col; + } else { + prev_mi_row = mi_row; + prev_mi_col = mi_col - MAX_MIB_SIZE; + } + + MB_MODE_INFO *curr_mbmi = + &cm->mi_grid_visible[mi_row * cm->mi_stride + mi_col]->mbmi; + MB_MODE_INFO *prev_mbmi = + &cm->mi_grid_visible[prev_mi_row * cm->mi_stride + prev_mi_col]->mbmi; + for (lvl_idx = 0; lvl_idx < 4; ++lvl_idx) { + const uint8_t prev_lvl = prev_mbmi->filt_lvl[lvl_idx]; + + const int reuse_ctx = prev_mbmi->reuse_sb_lvl[lvl_idx]; + const int reuse_prev_lvl = aom_read_symbol( + r, xd->tile_ctx->lpf_reuse_cdf[lvl_idx][reuse_ctx], 2, ACCT_STR); + curr_mbmi->reuse_sb_lvl[lvl_idx] = reuse_prev_lvl; + + if (reuse_prev_lvl) { + filt_lvl[lvl_idx] = prev_lvl; + curr_mbmi->delta[lvl_idx] = 0; + curr_mbmi->sign[lvl_idx] = 0; + } else { + const int delta_ctx = prev_mbmi->delta[lvl_idx]; + unsigned int delta = aom_read_symbol( + r, xd->tile_ctx->lpf_delta_cdf[lvl_idx][delta_ctx], DELTA_RANGE, + ACCT_STR); + curr_mbmi->delta[lvl_idx] = delta; + delta *= LPF_STEP; + + if (delta) { + const int sign_ctx = prev_mbmi->sign[lvl_idx]; + const int sign = aom_read_symbol( + r, xd->tile_ctx->lpf_sign_cdf[lvl_idx][reuse_ctx][sign_ctx], 2, + ACCT_STR); + curr_mbmi->sign[lvl_idx] = sign; + filt_lvl[lvl_idx] = sign ? prev_lvl + delta : prev_lvl - delta; + } else { + filt_lvl[lvl_idx] = prev_lvl; + curr_mbmi->sign[lvl_idx] = 0; + } + } + } + } + + av1_loop_filter_sb_level_init(cm, mi_row, mi_col, 0, 0, filt_lvl[0]); + av1_loop_filter_sb_level_init(cm, mi_row, mi_col, 0, 1, filt_lvl[1]); + av1_loop_filter_sb_level_init(cm, mi_row, mi_col, 1, 0, filt_lvl[2]); + av1_loop_filter_sb_level_init(cm, mi_row, mi_col, 2, 0, filt_lvl[3]); + } +#else if (bsize == cm->sb_size && !USE_GUESS_LEVEL) { int filt_lvl; if (mi_row == 0 && mi_col == 0) { @@ -846,7 +917,8 @@ av1_loop_filter_sb_level_init(cm, mi_row, mi_col, filt_lvl); } -#endif +#endif // CONFIG_LOOPFILTER_LEVEL +#endif // CONFIG_LPF_SB #if CONFIG_LOOP_RESTORATION for (int plane = 0; plane < av1_num_planes(cm); ++plane) { @@ -1114,12 +1186,18 @@ #endif // CONFIG_INTRABC && !CONFIG_LPF_SB struct loopfilter *lf = &cm->lf; #if CONFIG_LOOPFILTER_LEVEL - lf->filter_level[0] = aom_rb_read_literal(rb, 6); - lf->filter_level[1] = aom_rb_read_literal(rb, 6); - if (lf->filter_level[0] || lf->filter_level[1]) { - lf->filter_level_u = aom_rb_read_literal(rb, 6); - lf->filter_level_v = aom_rb_read_literal(rb, 6); +#if CONFIG_LPF_SB + if (USE_GUESS_LEVEL) { +#endif // CONFIG_LPF_SB + lf->filter_level[0] = aom_rb_read_literal(rb, 6); + lf->filter_level[1] = aom_rb_read_literal(rb, 6); + if (lf->filter_level[0] || lf->filter_level[1]) { + lf->filter_level_u = aom_rb_read_literal(rb, 6); + lf->filter_level_v = aom_rb_read_literal(rb, 6); + } +#if CONFIG_LPF_SB } +#endif // CONFIG_LPF_SB #else #if CONFIG_LPF_SB if (USE_GUESS_LEVEL) lf->filter_level = aom_rb_read_literal(rb, 6); @@ -2216,11 +2294,30 @@ cm->sb_size); #if CONFIG_LPF_SB if (USE_LOOP_FILTER_SUPERBLOCK) { +#if CONFIG_LOOPFILTER_LEVEL + if (USE_GUESS_LEVEL) { + if (cm->lf.filter_level[0] || cm->lf.filter_level[1]) { + av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb, + cm->lf.filter_level[0], + cm->lf.filter_level[1], 0, 1, mi_row, + mi_col); + av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb, + cm->lf.filter_level_u, + cm->lf.filter_level_u, 1, 1, mi_row, + mi_col); + av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb, + cm->lf.filter_level_v, + cm->lf.filter_level_v, 2, 1, mi_row, + mi_col); + } + } +#else // apply deblocking filtering right after each superblock is decoded 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, filter_lvl, 0, 1, mi_row, mi_col); +#endif // CONFIG_LOOPFILTER_LEVEL } #endif // CONFIG_LPF_SB } @@ -2253,7 +2350,7 @@ #if CONFIG_OBU if (endTile == cm->tile_rows * cm->tile_cols - 1) #endif -#if CONFIG_LOOPFILTER_LEVEL +#if CONFIG_LOOPFILTER_LEVEL && !CONFIG_LPF_SB if (cm->lf.filter_level[0] || cm->lf.filter_level[1]) { av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb, cm->lf.filter_level[0], cm->lf.filter_level[1], 0, @@ -2265,7 +2362,7 @@ cm->lf.filter_level_v, cm->lf.filter_level_v, 2, 0); } -#else +#elif !CONFIG_LPF_SB av1_loop_filter_frame(get_frame_new_buffer(cm), cm, &pbi->mb, cm->lf.filter_level, 0, 0); #endif // CONFIG_LOOPFILTER_LEVEL
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index ba271c7..3c305e2 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -2298,11 +2298,26 @@ #if CONFIG_LPF_SB // send filter level for each superblock (64x64) if (bsize == cm->sb_size && !USE_GUESS_LEVEL) { + int lvl_idx; if (mi_row == 0 && mi_col == 0) { +#if CONFIG_LOOPFILTER_LEVEL + aom_write_literal(w, cm->mi[0].mbmi.filt_lvl[0], 6); + aom_write_literal(w, cm->mi[0].mbmi.filt_lvl[1], 6); + if (cm->mi[0].mbmi.filt_lvl[0] || cm->mi[0].mbmi.filt_lvl[1]) { + aom_write_literal(w, cm->mi[0].mbmi.filt_lvl[2], 6); + aom_write_literal(w, cm->mi[0].mbmi.filt_lvl[3], 6); + } + for (lvl_idx = 0; lvl_idx < 4; ++lvl_idx) { + cm->mi_grid_visible[0]->mbmi.reuse_sb_lvl[lvl_idx] = 0; + cm->mi_grid_visible[0]->mbmi.delta[lvl_idx] = 0; + cm->mi_grid_visible[0]->mbmi.sign[lvl_idx] = 0; + } +#else 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; +#endif } else { int prev_mi_row, prev_mi_col; if (mi_col - MAX_MIB_SIZE < 0) { @@ -2317,6 +2332,44 @@ MB_MODE_INFO *prev_mbmi = &cm->mi_grid_visible[prev_mi_row * cm->mi_stride + prev_mi_col]->mbmi; +#if CONFIG_LOOPFILTER_LEVEL + for (lvl_idx = 0; lvl_idx < 4; ++lvl_idx) { + const uint8_t curr_lvl = curr_mbmi->filt_lvl[lvl_idx]; + const uint8_t prev_lvl = prev_mbmi->filt_lvl[lvl_idx]; + + const int reuse_prev_lvl = curr_lvl == prev_lvl; + const int reuse_ctx = prev_mbmi->reuse_sb_lvl[lvl_idx]; + curr_mbmi->reuse_sb_lvl[lvl_idx] = reuse_prev_lvl; + aom_write_symbol(w, reuse_prev_lvl, + xd->tile_ctx->lpf_reuse_cdf[lvl_idx][reuse_ctx], 2); + cpi->td.counts->lpf_reuse[lvl_idx][reuse_ctx][reuse_prev_lvl]++; + + if (reuse_prev_lvl) { + curr_mbmi->delta[lvl_idx] = 0; + curr_mbmi->sign[lvl_idx] = 0; + } else { + const unsigned int delta = abs(curr_lvl - prev_lvl) / LPF_STEP; + const int delta_ctx = prev_mbmi->delta[lvl_idx]; + curr_mbmi->delta[lvl_idx] = delta; + aom_write_symbol(w, delta, + xd->tile_ctx->lpf_delta_cdf[lvl_idx][delta_ctx], + DELTA_RANGE); + cpi->td.counts->lpf_delta[lvl_idx][delta_ctx][delta]++; + + if (delta) { + const int sign = curr_lvl > prev_lvl; + const int sign_ctx = prev_mbmi->sign[lvl_idx]; + curr_mbmi->sign[lvl_idx] = sign; + aom_write_symbol( + w, sign, + xd->tile_ctx->lpf_sign_cdf[lvl_idx][reuse_ctx][sign_ctx], 2); + cpi->td.counts->lpf_sign[lvl_idx][reuse_ctx][sign_ctx][sign]++; + } else { + curr_mbmi->sign[lvl_idx] = 0; + } + } + } +#else const uint8_t curr_lvl = curr_mbmi->filt_lvl; const uint8_t prev_lvl = prev_mbmi->filt_lvl; @@ -2349,6 +2402,7 @@ curr_mbmi->sign = 0; } } +#endif // CONFIG_LOOPFILTER_LEVEL } } #endif @@ -2586,12 +2640,18 @@ // Encode the loop filter level and type #if CONFIG_LOOPFILTER_LEVEL - aom_wb_write_literal(wb, lf->filter_level[0], 6); - aom_wb_write_literal(wb, lf->filter_level[1], 6); - if (lf->filter_level[0] || lf->filter_level[1]) { - aom_wb_write_literal(wb, lf->filter_level_u, 6); - aom_wb_write_literal(wb, lf->filter_level_v, 6); +#if CONFIG_LPF_SB + if (USE_GUESS_LEVEL) { +#endif // CONFIG_LPF_SB + aom_wb_write_literal(wb, lf->filter_level[0], 6); + aom_wb_write_literal(wb, lf->filter_level[1], 6); + if (lf->filter_level[0] || lf->filter_level[1]) { + aom_wb_write_literal(wb, lf->filter_level_u, 6); + aom_wb_write_literal(wb, lf->filter_level_v, 6); + } +#if CONFIG_LPF_SB } +#endif // CONFIG_LPF_SB #else #if CONFIG_LPF_SB if (USE_GUESS_LEVEL) aom_wb_write_literal(wb, lf->filter_level, 6);
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index f984652..f1d516e 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -3256,6 +3256,23 @@ } #if CONFIG_LPF_SB if (USE_LOOP_FILTER_SUPERBLOCK) { +#if CONFIG_LOOPFILTER_LEVEL + int filter_lvl[4]; + + if (USE_GUESS_LEVEL) { + struct loopfilter *lf = &cpi->common.lf; + filter_lvl[0] = lf->filter_level[0]; + filter_lvl[1] = lf->filter_level[1]; + filter_lvl[2] = lf->filter_level_u; + filter_lvl[3] = lf->filter_level_v; + av1_loop_filter_frame(cm->frame_to_show, cm, xd, filter_lvl[0], + filter_lvl[1], 0, 1, mi_row, mi_col); + av1_loop_filter_frame(cm->frame_to_show, cm, xd, filter_lvl[2], + filter_lvl[2], 1, 1, mi_row, mi_col); + av1_loop_filter_frame(cm->frame_to_show, cm, xd, filter_lvl[3], + filter_lvl[3], 2, 1, mi_row, mi_col); + } +#else int filter_lvl; if (USE_GUESS_LEVEL) { @@ -3283,6 +3300,7 @@ // 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_LOOPFILTER_LEVEL } #endif // CONFIG_LPF_SB }
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 0aac2cb..f6228bd 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -4709,10 +4709,10 @@ #endif #endif // CONFIG_LPF_SB { -#if CONFIG_LPF_SB +#if CONFIG_LPF_SB && !CONFIG_LOOPFILTER_LEVEL av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0, 0, 0); -#else +#elif !CONFIG_LPF_SB #if CONFIG_LOOPFILTER_LEVEL av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level[0], lf->filter_level[1], 0, 0);
diff --git a/av1/encoder/picklpf.c b/av1/encoder/picklpf.c index b064ddb..12f07de 100644 --- a/av1/encoder/picklpf.c +++ b/av1/encoder/picklpf.c
@@ -27,7 +27,7 @@ #include "av1/encoder/encoder.h" #include "av1/encoder/picklpf.h" -#if CONFIG_LPF_SB +#if CONFIG_LPF_SB && !CONFIG_LOOPFILTER_LEVEL #if CONFIG_HIGHBITDEPTH static int compute_sb_y_sse_highbd(const YV12_BUFFER_CONFIG *src, const YV12_BUFFER_CONFIG *frame, @@ -115,7 +115,7 @@ } } -#if CONFIG_LPF_SB +#if CONFIG_LPF_SB && !CONFIG_LOOPFILTER_LEVEL // TODO(chengchen): reduce memory usage by copy superblock instead of frame static int try_filter_superblock(const YV12_BUFFER_CONFIG *sd, AV1_COMP *const cpi, int filt_level, @@ -230,7 +230,7 @@ return filt_best; } -#else // CONFIG_LPF_SB +#elif !CONFIG_LPF_SB // CONFIG_LPF_SB static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd, AV1_COMP *const cpi, int filt_level, int partial_frame @@ -401,6 +401,7 @@ LPF_PICK_METHOD method) { AV1_COMMON *const cm = &cpi->common; struct loopfilter *const lf = &cm->lf; + (void)sd; lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness; @@ -450,13 +451,16 @@ if (cm->bit_depth != AOM_BITS_8 && cm->frame_type == KEY_FRAME) filt_guess -= 4; #if CONFIG_LOOPFILTER_LEVEL + // TODO(chengchen): retrain the model for Y, U, V filter levels lf->filter_level[0] = clamp(filt_guess, min_filter_level, max_filter_level); lf->filter_level[1] = clamp(filt_guess, min_filter_level, max_filter_level); + lf->filter_level_u = clamp(filt_guess, min_filter_level, max_filter_level); + lf->filter_level_v = clamp(filt_guess, min_filter_level, max_filter_level); #else lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level); #endif } else { -#if CONFIG_LPF_SB +#if CONFIG_LPF_SB && !CONFIG_LOOPFILTER_LEVEL int mi_row, mi_col; // TODO(chengchen): init last_lvl using previous frame's info? int last_lvl = 0; @@ -485,7 +489,7 @@ } } } -#else // CONFIG_LPF_SB +#elif !CONFIG_LPF_SB // !CONFIG_LPF_SB #if CONFIG_LOOPFILTER_LEVEL lf->filter_level[0] = lf->filter_level[1] = search_filter_level( sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 2);
diff --git a/build/cmake/aom_experiment_deps.cmake b/build/cmake/aom_experiment_deps.cmake index 8727da6..1a7e563 100644 --- a/build/cmake/aom_experiment_deps.cmake +++ b/build/cmake/aom_experiment_deps.cmake
@@ -130,12 +130,6 @@ endif () endif () - if (CONFIG_LPF_SB) - if (CONFIG_LOOPFILTER_LEVEL) - change_config_and_warn(CONFIG_LOOPFILTER_LEVEL 0 CONFIG_LPF_SB) - endif () - endif () - if (CONFIG_MFMV) if (NOT CONFIG_FRAME_MARKER) change_config_and_warn(CONFIG_FRAME_MARKER 1 CONFIG_MFMV)
diff --git a/configure b/configure index b1ab811..0ffd515 100755 --- a/configure +++ b/configure
@@ -587,11 +587,6 @@ log_echo "encoder side amvr requires hash_me" enable_feature hash_me fi - if enabled lpf_sb; then - log_echo "lpf_sb can't work with loopfilter_level yet." - log_echo "disabling loopfilter_level" - disable_feature loopfilter_level - fi } process_targets() {