Commit 880166ab authored by Cheng Chen's avatar Cheng Chen

LOOPFILTER_LEVEL: add flexibility for EXT_DELTA_Q

When experiment LOOPFILTER_LEVEL is on, there're four base filter levels
for each frame. This patch enables one to use one delta or four deltas
to update corresponding filter levels for each superblock in
EXT_DELTA_Q.

1 bit per frame is sent through bitstream to select one or four deltas.
Now, we hard code to use one delta.

Change-Id: I9c61a035064fa81878b0575ad21664e2b22a6a45
parent dbaa18cb
......@@ -651,8 +651,13 @@ static uint8_t get_filter_level(const AV1_COMMON *cm,
#endif // CONFIG_SUPERTX
if (cm->delta_lf_present_flag) {
#if CONFIG_LOOPFILTER_LEVEL
const int delta_lf_idx = delta_lf_id_lut[plane][dir_idx];
const int delta_lf = mbmi->curr_delta_lf[delta_lf_idx];
int delta_lf;
if (cm->delta_lf_multi) {
const int delta_lf_idx = delta_lf_id_lut[plane][dir_idx];
delta_lf = mbmi->curr_delta_lf[delta_lf_idx];
} else {
delta_lf = mbmi->current_delta_lf_from_base;
}
int lvl_seg =
clamp(delta_lf + cm->lf.filter_level[dir_idx], 0, MAX_LOOP_FILTER);
#else
......
......@@ -1684,23 +1684,23 @@ static const aom_cdf_prob default_delta_q_cdf[CDF_SIZE(DELTA_Q_PROBS + 1)] = {
};
#if CONFIG_EXT_DELTA_Q
#if CONFIG_LOOPFILTER_LEVEL
static const aom_prob default_delta_lf_probs[FRAME_LF_COUNT][DELTA_LF_PROBS] = {
{ 220, 220, 220 }, { 220, 220, 220 }, { 220, 220, 220 }, { 220, 220, 220 }
};
static const aom_prob
default_delta_lf_multi_probs[FRAME_LF_COUNT][DELTA_LF_PROBS] = {
{ 220, 220, 220 }, { 220, 220, 220 }, { 220, 220, 220 }, { 220, 220, 220 }
};
static const aom_cdf_prob
default_delta_lf_cdf[FRAME_LF_COUNT][CDF_SIZE(DELTA_LF_PROBS + 1)] = {
default_delta_lf_multi_cdf[FRAME_LF_COUNT][CDF_SIZE(DELTA_LF_PROBS + 1)] = {
{ AOM_ICDF(28160), AOM_ICDF(32120), AOM_ICDF(32677), AOM_ICDF(32768), 0 },
{ AOM_ICDF(28160), AOM_ICDF(32120), AOM_ICDF(32677), AOM_ICDF(32768), 0 },
{ AOM_ICDF(28160), AOM_ICDF(32120), AOM_ICDF(32677), AOM_ICDF(32768), 0 },
{ AOM_ICDF(28160), AOM_ICDF(32120), AOM_ICDF(32677), AOM_ICDF(32768), 0 }
};
#else
#endif // CONFIG_LOOPFILTER_LEVEL
static const aom_prob default_delta_lf_probs[DELTA_LF_PROBS] = { 220, 220,
220 };
static const aom_cdf_prob default_delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)] = {
AOM_ICDF(28160), AOM_ICDF(32120), AOM_ICDF(32677), AOM_ICDF(32768), 0
};
#endif // CONFIG_LOOPFILTER_LEVEL
#endif
/* clang-format off */
......@@ -5720,6 +5720,9 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
#if CONFIG_EXT_DELTA_Q
av1_copy(fc->delta_lf_prob, default_delta_lf_probs);
av1_copy(fc->delta_lf_cdf, default_delta_lf_cdf);
#if CONFIG_LOOPFILTER_LEVEL
av1_copy(fc->delta_lf_multi_cdf, default_delta_lf_multi_cdf);
#endif // CONFIG_LOOPFILTER_LEVEL
#endif
#if CONFIG_CFL
av1_copy(fc->cfl_sign_cdf, default_cfl_sign_cdf);
......@@ -5952,13 +5955,12 @@ void av1_adapt_intra_frame_probs(AV1_COMMON *cm) {
#if CONFIG_LOOPFILTER_LEVEL
for (i = 0; i < FRAME_LF_COUNT; ++i)
for (int j = 0; j < DELTA_LF_PROBS; ++j)
fc->delta_lf_prob[i][j] = mode_mv_merge_probs(pre_fc->delta_lf_prob[i][j],
counts->delta_lf[i][j]);
#else
fc->delta_lf_multi_prob[i][j] = mode_mv_merge_probs(
pre_fc->delta_lf_multi_prob[i][j], counts->delta_lf_multi[i][j]);
#endif // CONFIG_LOOPFILTER_LEVEL
for (i = 0; i < DELTA_LF_PROBS; ++i)
fc->delta_lf_prob[i] =
mode_mv_merge_probs(pre_fc->delta_lf_prob[i], counts->delta_lf[i]);
#endif // CONFIG_LOOPFILTER_LEVEL
#endif // CONFIG_EXT_DELTA_Q
#if CONFIG_EXT_INTRA
#if CONFIG_INTRA_INTERP
......
......@@ -361,10 +361,9 @@ typedef struct frame_contexts {
aom_cdf_prob delta_q_cdf[CDF_SIZE(DELTA_Q_PROBS + 1)];
#if CONFIG_EXT_DELTA_Q
#if CONFIG_LOOPFILTER_LEVEL
aom_cdf_prob delta_lf_cdf[FRAME_LF_COUNT][CDF_SIZE(DELTA_LF_PROBS + 1)];
#else
aom_cdf_prob delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)];
aom_cdf_prob delta_lf_multi_cdf[FRAME_LF_COUNT][CDF_SIZE(DELTA_LF_PROBS + 1)];
#endif // CONFIG_LOOPFILTER_LEVEL
aom_cdf_prob delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)];
#endif
#if CONFIG_EXT_TX
aom_cdf_prob intra_ext_tx_cdf[EXT_TX_SETS_INTRA][EXT_TX_SIZES][INTRA_MODES]
......@@ -381,10 +380,9 @@ typedef struct frame_contexts {
aom_prob delta_q_prob[DELTA_Q_PROBS];
#if CONFIG_EXT_DELTA_Q
#if CONFIG_LOOPFILTER_LEVEL
aom_prob delta_lf_prob[FRAME_LF_COUNT][DELTA_LF_PROBS];
#else
aom_prob delta_lf_prob[DELTA_LF_PROBS];
aom_prob delta_lf_multi_prob[FRAME_LF_COUNT][DELTA_LF_PROBS];
#endif // CONFIG_LOOPFILTER_LEVEL
aom_prob delta_lf_prob[DELTA_LF_PROBS];
#endif
#if CONFIG_PVQ
// TODO(any): If PVQ is enabled, most of coefficient related cdf,
......@@ -516,10 +514,9 @@ typedef struct FRAME_COUNTS {
unsigned int delta_q[DELTA_Q_PROBS][2];
#if CONFIG_EXT_DELTA_Q
#if CONFIG_LOOPFILTER_LEVEL
unsigned int delta_lf[FRAME_LF_COUNT][DELTA_LF_PROBS][2];
#else
unsigned int delta_lf[DELTA_LF_PROBS][2];
unsigned int delta_lf_multi[FRAME_LF_COUNT][DELTA_LF_PROBS][2];
#endif // CONFIG_LOOPFILTER_LEVEL
unsigned int delta_lf[DELTA_LF_PROBS][2];
#endif
#if CONFIG_EXT_TX && CONFIG_RECT_TX
unsigned int tx_size_implied[TX_SIZES][TX_SIZES];
......
......@@ -86,6 +86,7 @@ extern "C" {
// 4 frame filter levels: y plane vertical, y plane horizontal,
// u plane, and v plane
#define FRAME_LF_COUNT 4
#define DEFAULT_DELTA_LF_MULTI 0
#endif // CONFIG_LOOPFILTER_LEVEL
#if CONFIG_LPF_SB
......
......@@ -513,6 +513,12 @@ typedef struct AV1Common {
int delta_lf_present_flag;
// Resolution of delta lf level
int delta_lf_res;
#if CONFIG_LOOPFILTER_LEVEL
// This is a flag for number of deltas of loop filter level
// 0: use 1 delta, for y_vertical, y_horizontal, u, and v
// 1: use separate deltas for each filter level
int delta_lf_multi;
#endif // CONFIG_LOOPFILTER_LEVEL
#endif
int num_tg;
#if CONFIG_REFERENCE_BUFFER
......
......@@ -5048,6 +5048,9 @@ static size_t read_uncompressed_header(AV1Decoder *pbi,
#if CONFIG_EXT_DELTA_Q
cm->delta_lf_res = 1;
cm->delta_lf_present_flag = 0;
#if CONFIG_LOOPFILTER_LEVEL
cm->delta_lf_multi = 0;
#endif // CONFIG_LOOPFILTER_LEVEL
#endif
if (segment_quantizer_active == 0 && cm->base_qindex > 0) {
cm->delta_q_present_flag = aom_rb_read_bit(rb);
......@@ -5061,12 +5064,13 @@ static size_t read_uncompressed_header(AV1Decoder *pbi,
assert(!segment_quantizer_active);
cm->delta_lf_present_flag = aom_rb_read_bit(rb);
if (cm->delta_lf_present_flag) {
xd->prev_delta_lf_from_base = 0;
cm->delta_lf_res = 1 << aom_rb_read_literal(rb, 2);
#if CONFIG_LOOPFILTER_LEVEL
cm->delta_lf_multi = aom_rb_read_bit(rb);
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id)
xd->prev_delta_lf[lf_id] = 0;
#endif // CONFIG_LOOPFILTER_LEVEL
xd->prev_delta_lf_from_base = 0;
cm->delta_lf_res = 1 << aom_rb_read_literal(rb, 2);
}
#endif // CONFIG_EXT_DELTA_Q
}
......
......@@ -96,8 +96,14 @@ static int read_delta_lflevel(AV1_COMMON *cm, MACROBLOCKD *xd, aom_reader *r,
if ((bsize != BLOCK_64X64 || mbmi->skip == 0) && read_delta_lf_flag) {
#if CONFIG_LOOPFILTER_LEVEL
abs = aom_read_symbol(r, ec_ctx->delta_lf_cdf[lf_id], DELTA_LF_PROBS + 1,
ACCT_STR);
if (cm->delta_lf_multi) {
assert(lf_id >= 0 && lf_id < FRAME_LF_COUNT);
abs = aom_read_symbol(r, ec_ctx->delta_lf_multi_cdf[lf_id],
DELTA_LF_PROBS + 1, ACCT_STR);
} else {
abs = aom_read_symbol(r, ec_ctx->delta_lf_cdf, DELTA_LF_PROBS + 1,
ACCT_STR);
}
#else
abs =
aom_read_symbol(r, ec_ctx->delta_lf_cdf, DELTA_LF_PROBS + 1, ACCT_STR);
......@@ -105,8 +111,13 @@ static int read_delta_lflevel(AV1_COMMON *cm, MACROBLOCKD *xd, aom_reader *r,
smallval = (abs < DELTA_LF_SMALL);
if (counts) {
#if CONFIG_LOOPFILTER_LEVEL
for (i = 0; i < abs; ++i) counts->delta_lf[lf_id][i][1]++;
if (smallval) counts->delta_lf[lf_id][abs][0]++;
if (cm->delta_lf_multi) {
for (i = 0; i < abs; ++i) counts->delta_lf_multi[lf_id][i][1]++;
if (smallval) counts->delta_lf_multi[lf_id][abs][0]++;
} else {
for (i = 0; i < abs; ++i) counts->delta_lf[i][1]++;
if (smallval) counts->delta_lf[abs][0]++;
}
#else
for (i = 0; i < abs; ++i) counts->delta_lf[i][1]++;
if (smallval) counts->delta_lf[abs][0]++;
......@@ -1115,12 +1126,20 @@ static void read_intra_frame_mode_info(AV1_COMMON *const cm,
#if CONFIG_EXT_DELTA_Q
if (cm->delta_lf_present_flag) {
#if CONFIG_LOOPFILTER_LEVEL
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
mbmi->curr_delta_lf[lf_id] = xd->curr_delta_lf[lf_id] =
xd->prev_delta_lf[lf_id] +
read_delta_lflevel(cm, xd, r, lf_id, mbmi, mi_col, mi_row) *
if (cm->delta_lf_multi) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
mbmi->curr_delta_lf[lf_id] = xd->curr_delta_lf[lf_id] =
xd->prev_delta_lf[lf_id] +
read_delta_lflevel(cm, xd, r, lf_id, mbmi, mi_col, mi_row) *
cm->delta_lf_res;
xd->prev_delta_lf[lf_id] = xd->curr_delta_lf[lf_id];
}
} else {
mbmi->current_delta_lf_from_base = xd->current_delta_lf_from_base =
xd->prev_delta_lf_from_base +
read_delta_lflevel(cm, xd, r, -1, mbmi, mi_col, mi_row) *
cm->delta_lf_res;
xd->prev_delta_lf[lf_id] = xd->curr_delta_lf[lf_id];
xd->prev_delta_lf_from_base = xd->current_delta_lf_from_base;
}
#else
mbmi->current_delta_lf_from_base = xd->current_delta_lf_from_base =
......@@ -2876,12 +2895,20 @@ static void read_inter_frame_mode_info(AV1Decoder *const pbi,
#if CONFIG_EXT_DELTA_Q
if (cm->delta_lf_present_flag) {
#if CONFIG_LOOPFILTER_LEVEL
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
mbmi->curr_delta_lf[lf_id] = xd->curr_delta_lf[lf_id] =
xd->prev_delta_lf[lf_id] +
read_delta_lflevel(cm, xd, r, lf_id, mbmi, mi_col, mi_row) *
if (cm->delta_lf_multi) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
mbmi->curr_delta_lf[lf_id] = xd->curr_delta_lf[lf_id] =
xd->prev_delta_lf[lf_id] +
read_delta_lflevel(cm, xd, r, lf_id, mbmi, mi_col, mi_row) *
cm->delta_lf_res;
xd->prev_delta_lf[lf_id] = xd->curr_delta_lf[lf_id];
}
} else {
mbmi->current_delta_lf_from_base = xd->current_delta_lf_from_base =
xd->prev_delta_lf_from_base +
read_delta_lflevel(cm, xd, r, -1, mbmi, mi_col, mi_row) *
cm->delta_lf_res;
xd->prev_delta_lf[lf_id] = xd->curr_delta_lf[lf_id];
xd->prev_delta_lf_from_base = xd->current_delta_lf_from_base;
}
#else
mbmi->current_delta_lf_from_base = xd->current_delta_lf_from_base =
......
......@@ -541,8 +541,14 @@ static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
(void)cm;
#if CONFIG_LOOPFILTER_LEVEL
aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf[lf_id],
DELTA_LF_PROBS + 1);
if (cm->delta_lf_multi) {
assert(lf_id >= 0 && lf_id < FRAME_LF_COUNT);
aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL),
ec_ctx->delta_lf_multi_cdf[lf_id], DELTA_LF_PROBS + 1);
} else {
aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
DELTA_LF_PROBS + 1);
}
#else
aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
DELTA_LF_PROBS + 1);
......@@ -1724,12 +1730,20 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row,
#if CONFIG_EXT_DELTA_Q
#if CONFIG_LOOPFILTER_LEVEL
if (cm->delta_lf_present_flag) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
if (cm->delta_lf_multi) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
int reduced_delta_lflevel =
(mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) /
cm->delta_lf_res;
write_delta_lflevel(cm, xd, lf_id, reduced_delta_lflevel, w);
xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id];
}
} else {
int reduced_delta_lflevel =
(mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) /
(mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) /
cm->delta_lf_res;
write_delta_lflevel(cm, xd, lf_id, reduced_delta_lflevel, w);
xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id];
write_delta_lflevel(cm, xd, -1, reduced_delta_lflevel, w);
xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base;
}
}
#else
......@@ -2119,12 +2133,20 @@ static void write_mb_modes_kf(AV1_COMMON *cm, MACROBLOCKD *xd,
#if CONFIG_EXT_DELTA_Q
#if CONFIG_LOOPFILTER_LEVEL
if (cm->delta_lf_present_flag) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
if (cm->delta_lf_multi) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
int reduced_delta_lflevel =
(mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) /
cm->delta_lf_res;
write_delta_lflevel(cm, xd, lf_id, reduced_delta_lflevel, w);
xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id];
}
} else {
int reduced_delta_lflevel =
(mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) /
(mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) /
cm->delta_lf_res;
write_delta_lflevel(cm, xd, lf_id, reduced_delta_lflevel, w);
xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id];
write_delta_lflevel(cm, xd, -1, reduced_delta_lflevel, w);
xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base;
}
}
#else
......@@ -4757,11 +4779,12 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
aom_wb_write_bit(wb, cm->delta_lf_present_flag);
if (cm->delta_lf_present_flag) {
aom_wb_write_literal(wb, OD_ILOG_NZ(cm->delta_lf_res) - 1, 2);
xd->prev_delta_lf_from_base = 0;
#if CONFIG_LOOPFILTER_LEVEL
aom_wb_write_bit(wb, cm->delta_lf_multi);
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id)
xd->prev_delta_lf[lf_id] = 0;
#endif // CONFIG_LOOPFILTER_LEVEL
xd->prev_delta_lf_from_base = 0;
}
#endif // CONFIG_EXT_DELTA_Q
}
......
......@@ -1624,19 +1624,31 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
#if CONFIG_EXT_DELTA_Q
#if CONFIG_LOOPFILTER_LEVEL
if (cm->delta_lf_present_flag) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
if (cm->delta_lf_multi) {
for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) {
const int delta_lf =
(mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) /
cm->delta_lf_res;
const int abs_delta_lf = abs(delta_lf);
for (i = 0; i < AOMMIN(abs_delta_lf, DELTA_LF_SMALL); ++i) {
td->counts->delta_lf_multi[lf_id][i][1]++;
}
if (abs_delta_lf < DELTA_LF_SMALL)
td->counts->delta_lf_multi[lf_id][abs_delta_lf][0]++;
xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id];
}
} else {
const int delta_lf =
(mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) /
(mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) /
cm->delta_lf_res;
const int abs_delta_lf = abs(delta_lf);
for (i = 0; i < AOMMIN(abs_delta_lf, DELTA_LF_SMALL); ++i) {
td->counts->delta_lf[lf_id][i][1]++;
td->counts->delta_lf[i][1]++;
}
if (abs_delta_lf < DELTA_LF_SMALL)
td->counts->delta_lf[lf_id][abs_delta_lf][0]++;
xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id];
td->counts->delta_lf[abs_delta_lf][0]++;
xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base;
}
xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base;
}
#else
if (cm->delta_lf_present_flag) {
......
......@@ -5552,6 +5552,9 @@ static void encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size,
#if CONFIG_EXT_DELTA_Q
cm->delta_q_present_flag = cpi->oxcf.deltaq_mode != NO_DELTA_Q;
cm->delta_lf_present_flag = cpi->oxcf.deltaq_mode == DELTA_Q_LF;
#if CONFIG_LOOPFILTER_LEVEL
cm->delta_lf_multi = DEFAULT_DELTA_LF_MULTI;
#endif // CONFIG_LOOPFILTER_LEVEL
#endif
if (cpi->sf.recode_loop == DISALLOW_RECODE) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment