Use arithmetic coding (cdf) to code sb filter lvl Change-Id: I5446327378938128f27186015619a079c2845d53
diff --git a/av1/common/blockd.h b/av1/common/blockd.h index 86fcd57..9ee553f 100644 --- a/av1/common/blockd.h +++ b/av1/common/blockd.h
@@ -465,6 +465,9 @@ BOUNDARY_TYPE boundary_info; #if CONFIG_LPF_SB uint8_t filt_lvl; + int reuse_sb_lvl; + int sign; + int delta; #endif } MB_MODE_INFO;
diff --git a/av1/common/entropy.c b/av1/common/entropy.c index 3ac9c82..17a8f13 100644 --- a/av1/common/entropy.c +++ b/av1/common/entropy.c
@@ -2313,6 +2313,11 @@ AVERAGE_TILE_CDFS(quarter_tx_size_cdf) #endif #endif +#if CONFIG_LPF_SB + AVERAGE_TILE_CDFS(lpf_reuse_cdf); + AVERAGE_TILE_CDFS(lpf_delta_cdf); + AVERAGE_TILE_CDFS(lpf_sign_cdf); +#endif // CONFIG_LPF_SB } void av1_average_tile_inter_cdfs(AV1_COMMON *cm, FRAME_CONTEXT *fc, @@ -2381,6 +2386,11 @@ #if CONFIG_MRC_TX AVERAGE_TILE_CDFS(mrc_mask_inter_cdf) #endif // CONFIG_MRC_TX +#if CONFIG_LPF_SB + AVERAGE_TILE_CDFS(lpf_reuse_cdf); + AVERAGE_TILE_CDFS(lpf_delta_cdf); + AVERAGE_TILE_CDFS(lpf_sign_cdf); +#endif // CONFIG_LPF_SB } #if CONFIG_PVQ
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c index 6ccd098..600d693 100644 --- a/av1/common/entropymode.c +++ b/av1/common/entropymode.c
@@ -5622,6 +5622,40 @@ }; #endif // CONFIG_KF_CTX +#if CONFIG_LPF_SB +static const aom_cdf_prob default_lpf_reuse_cdf[LPF_REUSE_CONTEXT][CDF_SIZE( + 2)] = { { AOM_ICDF(8192), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(32768), 0 } }; + +static const aom_cdf_prob + default_lpf_delta_cdf[LPF_DELTA_CONTEXT][CDF_SIZE(DELTA_RANGE)] = { + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 }, + { AOM_ICDF(4096), AOM_ICDF(7680), AOM_ICDF(10816), AOM_ICDF(13560), + AOM_ICDF(15961), AOM_ICDF(18062), AOM_ICDF(19900), AOM_ICDF(32768), 0 } + }; + +static const aom_cdf_prob + default_lpf_sign_cdf[LPF_REUSE_CONTEXT][LPF_SIGN_CONTEXT][CDF_SIZE(2)] = { + { { AOM_ICDF(6554), AOM_ICDF(32768), 0 }, + { AOM_ICDF(26214), AOM_ICDF(32768), 0 } }, + { { AOM_ICDF(16384), AOM_ICDF(32768), 0 }, + { AOM_ICDF(16384), AOM_ICDF(32768), 0 } } + }; +#endif // CONFIG_LPF_SB + static void init_mode_probs(FRAME_CONTEXT *fc) { av1_copy(fc->partition_prob, default_partition_probs); av1_copy(fc->intra_inter_prob, default_intra_inter_p); @@ -5798,6 +5832,11 @@ #if CONFIG_INTRABC av1_copy(fc->intrabc_cdf, default_intrabc_cdf); #endif +#if CONFIG_LPF_SB + av1_copy(fc->lpf_reuse_cdf, default_lpf_reuse_cdf); + av1_copy(fc->lpf_delta_cdf, default_lpf_delta_cdf); + av1_copy(fc->lpf_sign_cdf, default_lpf_sign_cdf); +#endif // CONFIG_LPF_SB } void av1_adapt_inter_frame_probs(AV1_COMMON *cm) {
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h index 92cd94a..e5c8f9d 100644 --- a/av1/common/entropymode.h +++ b/av1/common/entropymode.h
@@ -405,6 +405,11 @@ aom_cdf_prob cfl_sign_cdf[CDF_SIZE(CFL_JOINT_SIGNS)]; aom_cdf_prob cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CDF_SIZE(CFL_ALPHABET_SIZE)]; #endif +#if CONFIG_LPF_SB + 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 // CONFIG_LPF_SB } FRAME_CONTEXT; typedef struct FRAME_COUNTS { @@ -556,6 +561,11 @@ #if CONFIG_FILTER_INTRA unsigned int filter_intra[PLANE_TYPES][2]; #endif // CONFIG_FILTER_INTRA +#if CONFIG_LPF_SB + unsigned int lpf_reuse[LPF_REUSE_CONTEXT][2]; + unsigned int lpf_delta[LPF_DELTA_CONTEXT][DELTA_RANGE]; + unsigned int lpf_sign[LPF_SIGN_CONTEXT][2]; +#endif // CONFIG_LPF_SB } FRAME_COUNTS; #if CONFIG_KF_CTX
diff --git a/av1/common/enums.h b/av1/common/enums.h index aeae71c..efc79fd 100644 --- a/av1/common/enums.h +++ b/av1/common/enums.h
@@ -92,8 +92,13 @@ #if CONFIG_LPF_SB #define LPF_DELTA_BITS 3 #define LPF_STEP 2 +#define DELTA_RANGE (1 << LPF_DELTA_BITS) #define MAX_LPF_OFFSET (LPF_STEP * ((1 << LPF_DELTA_BITS) - 1)) +#define LPF_REUSE_CONTEXT 2 +#define LPF_DELTA_CONTEXT DELTA_RANGE +#define LPF_SIGN_CONTEXT 2 + // Half of maximum loop filter length (15-tap) #define FILT_BOUNDARY_OFFSET 8 #define FILT_BOUNDARY_MI_OFFSET (FILT_BOUNDARY_OFFSET >> MI_SIZE_LOG2)
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index e140847..f75975f 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -2579,6 +2579,9 @@ int filt_lvl; if (mi_row == 0 && mi_col == 0) { filt_lvl = aom_read_literal(r, 6, ACCT_STR); + 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; } else { int prev_mi_row, prev_mi_col; if (mi_col - MAX_MIB_SIZE < 0) { @@ -2589,22 +2592,37 @@ prev_mi_col = mi_col - MAX_MIB_SIZE; } - const uint8_t prev_lvl = - cm->mi_grid_visible[prev_mi_row * cm->mi_stride + prev_mi_col] - ->mbmi.filt_lvl; + 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; + const uint8_t prev_lvl = prev_mbmi->filt_lvl; - const int reuse_prev_lvl = aom_read_literal(r, 1, ACCT_STR); + const int reuse_ctx = prev_mbmi->reuse_sb_lvl; + const int reuse_prev_lvl = aom_read_symbol( + r, xd->tile_ctx->lpf_reuse_cdf[reuse_ctx], 2, ACCT_STR); + curr_mbmi->reuse_sb_lvl = reuse_prev_lvl; + if (reuse_prev_lvl) { filt_lvl = prev_lvl; + curr_mbmi->delta = 0; + curr_mbmi->sign = 0; } else { - unsigned int delta = aom_read_literal(r, LPF_DELTA_BITS, ACCT_STR); + const int delta_ctx = prev_mbmi->delta; + unsigned int delta = aom_read_symbol( + r, xd->tile_ctx->lpf_delta_cdf[delta_ctx], DELTA_RANGE, ACCT_STR); + curr_mbmi->delta = delta; delta *= LPF_STEP; if (delta) { - const int sign = aom_read_literal(r, 1, ACCT_STR); + const int sign_ctx = prev_mbmi->sign; + const int sign = aom_read_symbol( + r, xd->tile_ctx->lpf_sign_cdf[reuse_ctx][sign_ctx], 2, ACCT_STR); + curr_mbmi->sign = sign; filt_lvl = sign ? prev_lvl + delta : prev_lvl - delta; } else { filt_lvl = prev_lvl; + curr_mbmi->sign = 0; } } }
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index a546258..adad474 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -3153,10 +3153,10 @@ // 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[mi_row * cm->mi_stride + mi_col]->mbmi.filt_lvl, - 6); + aom_write_literal(w, cm->mi_grid_visible[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; } else { int prev_mi_row, prev_mi_col; if (mi_col - MAX_MIB_SIZE < 0) { @@ -3174,13 +3174,31 @@ const uint8_t curr_lvl = curr_mbmi->filt_lvl; const uint8_t prev_lvl = prev_mbmi->filt_lvl; - aom_write_literal(w, curr_lvl == prev_lvl, 1); - if (curr_lvl != prev_lvl) { - const int sign = curr_lvl > prev_lvl; - const unsigned int delta = abs(curr_lvl - prev_lvl) / LPF_STEP; + const int reuse_prev_lvl = curr_lvl == prev_lvl; + const int reuse_ctx = prev_mbmi->reuse_sb_lvl; + curr_mbmi->reuse_sb_lvl = reuse_prev_lvl; + aom_write_symbol(w, reuse_prev_lvl, + xd->tile_ctx->lpf_reuse_cdf[reuse_ctx], 2); - aom_write_literal(w, delta, LPF_DELTA_BITS); - if (delta) aom_write_literal(w, sign, 1); + if (reuse_prev_lvl) { + curr_mbmi->delta = 0; + curr_mbmi->sign = 0; + } else { + const unsigned int delta = abs(curr_lvl - prev_lvl) / LPF_STEP; + const int delta_ctx = prev_mbmi->delta; + curr_mbmi->delta = delta; + aom_write_symbol(w, delta, xd->tile_ctx->lpf_delta_cdf[delta_ctx], + DELTA_RANGE); + + if (delta) { + const int sign = curr_lvl > prev_lvl; + const int sign_ctx = prev_mbmi->sign; + curr_mbmi->sign = sign; + aom_write_symbol(w, sign, + xd->tile_ctx->lpf_sign_cdf[reuse_ctx][sign_ctx], 2); + } else { + curr_mbmi->sign = 0; + } } } }