Commit 231fe424 authored by Fangwen Fu's avatar Fangwen Fu

Extend delta q to have delta lf

This is the second patch.
* Add delta loop filter level at super block level.
* Add symbol coding for delta lf syntax
* Allow delta lf to work with segments

Change-Id: I393a021a875d03c6e113127cbb3543fc077308e4
parent c756e4d0
......@@ -294,7 +294,42 @@ static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
SIMD_WIDTH);
}
}
#if CONFIG_EXT_DELTA_Q
static uint8_t get_filter_level(const AV1_COMMON *cm,
const loop_filter_info_n *lfi_n,
const MB_MODE_INFO *mbmi) {
#if CONFIG_SUPERTX
const int segment_id = AOMMIN(mbmi->segment_id, mbmi->segment_id_supertx);
assert(
IMPLIES(supertx_enabled(mbmi), mbmi->segment_id_supertx != MAX_SEGMENTS));
assert(IMPLIES(supertx_enabled(mbmi),
mbmi->segment_id_supertx <= mbmi->segment_id));
#else
const int segment_id = mbmi->segment_id;
#endif // CONFIG_SUPERTX
if (cm->delta_lf_present_flag) {
int lvl_seg = clamp(mbmi->current_delta_lf_from_base + cm->lf.filter_level,
0, MAX_LOOP_FILTER);
const int scale = 1 << (lvl_seg >> 5);
if (segfeature_active(&cm->seg, segment_id, SEG_LVL_ALT_LF)) {
const int data = get_segdata(&cm->seg, segment_id, SEG_LVL_ALT_LF);
lvl_seg =
clamp(cm->seg.abs_delta == SEGMENT_ABSDATA ? data : lvl_seg + data, 0,
MAX_LOOP_FILTER);
}
if (cm->lf.mode_ref_delta_enabled) {
lvl_seg += cm->lf.ref_deltas[mbmi->ref_frame[0]] * scale;
if (mbmi->ref_frame[0] > INTRA_FRAME)
lvl_seg += cm->lf.mode_deltas[mode_lf_lut[mbmi->mode]] * scale;
lvl_seg = clamp(lvl_seg, 0, MAX_LOOP_FILTER);
}
return lvl_seg;
} else {
return lfi_n->lvl[segment_id][mbmi->ref_frame[0]][mode_lf_lut[mbmi->mode]];
}
}
#else
static uint8_t get_filter_level(const loop_filter_info_n *lfi_n,
const MB_MODE_INFO *mbmi) {
#if CONFIG_SUPERTX
......@@ -308,6 +343,7 @@ static uint8_t get_filter_level(const loop_filter_info_n *lfi_n,
#endif // CONFIG_SUPERTX
return lfi_n->lvl[segment_id][mbmi->ref_frame[0]][mode_lf_lut[mbmi->mode]];
}
#endif
#define NELEMENTS(x) (sizeof((x)) / sizeof((x)[0]))
......@@ -763,9 +799,12 @@ static void highbd_filter_selectively_horiz(
// block we are currently looking at. Shift is used to position the
// 1's we produce.
// TODO(JBB) Need another function for different resolution color..
static void build_masks(const loop_filter_info_n *const lfi_n,
const MODE_INFO *mi, const int shift_y,
const int shift_uv, LOOP_FILTER_MASK *lfm) {
static void build_masks(
#if CONFIG_EXT_DELTA_Q
AV1_COMMON *const cm,
#endif
const loop_filter_info_n *const lfi_n, const MODE_INFO *mi,
const int shift_y, const int shift_uv, LOOP_FILTER_MASK *lfm) {
const MB_MODE_INFO *mbmi = &mi->mbmi;
const BLOCK_SIZE block_size = mbmi->sb_type;
// TODO(debargha): Check if masks can be setup correctly when
......@@ -779,7 +818,11 @@ static void build_masks(const loop_filter_info_n *const lfi_n,
txsize_horz_map[uv_txsize_lookup[block_size][mbmi->tx_size][1][1]];
const TX_SIZE tx_size_uv_above =
txsize_vert_map[uv_txsize_lookup[block_size][mbmi->tx_size][1][1]];
#if CONFIG_EXT_DELTA_Q
const int filter_level = get_filter_level(cm, lfi_n, mbmi);
#else
const int filter_level = get_filter_level(lfi_n, mbmi);
#endif
uint64_t *const left_y = &lfm->left_y[tx_size_y_left];
uint64_t *const above_y = &lfm->above_y[tx_size_y_above];
uint64_t *const int_4x4_y = &lfm->int_4x4_y;
......@@ -851,12 +894,16 @@ static void build_masks(const loop_filter_info_n *const lfi_n,
// This function does the same thing as the one above with the exception that
// it only affects the y masks. It exists because for blocks < 16x16 in size,
// we only update u and v masks on the first block.
static void build_y_mask(const loop_filter_info_n *const lfi_n,
const MODE_INFO *mi, const int shift_y,
static void build_y_mask(
#if CONFIG_EXT_DELTA_Q
AV1_COMMON *const cm,
#endif
const loop_filter_info_n *const lfi_n, const MODE_INFO *mi,
const int shift_y,
#if CONFIG_SUPERTX
int supertx_enabled,
int supertx_enabled,
#endif // CONFIG_SUPERTX
LOOP_FILTER_MASK *lfm) {
LOOP_FILTER_MASK *lfm) {
const MB_MODE_INFO *mbmi = &mi->mbmi;
const TX_SIZE tx_size_y = txsize_sqr_map[mbmi->tx_size];
const TX_SIZE tx_size_y_left = txsize_horz_map[mbmi->tx_size];
......@@ -867,7 +914,11 @@ static void build_y_mask(const loop_filter_info_n *const lfi_n,
#else
const BLOCK_SIZE block_size = mbmi->sb_type;
#endif
#if CONFIG_EXT_DELTA_Q
const int filter_level = get_filter_level(cm, lfi_n, mbmi);
#else
const int filter_level = get_filter_level(lfi_n, mbmi);
#endif
uint64_t *const left_y = &lfm->left_y[tx_size_y_left];
uint64_t *const above_y = &lfm->above_y[tx_size_y_above];
uint64_t *const int_4x4_y = &lfm->int_4x4_y;
......@@ -971,27 +1022,48 @@ void av1_setup_mask(AV1_COMMON *const cm, const int mi_row, const int mi_col,
// loop and storing lfm in the mbmi structure so that we don't have to go
// through the recursive loop structure multiple times.
switch (mip[0]->mbmi.sb_type) {
#if CONFIG_EXT_DELTA_Q
case BLOCK_64X64: build_masks(cm, lfi_n, mip[0], 0, 0, lfm); break;
case BLOCK_64X32: build_masks(cm, lfi_n, mip[0], 0, 0, lfm);
#else
case BLOCK_64X64: build_masks(lfi_n, mip[0], 0, 0, lfm); break;
case BLOCK_64X32: build_masks(lfi_n, mip[0], 0, 0, lfm);
#endif
#if CONFIG_SUPERTX && CONFIG_TX64X64
if (supertx_enabled(&mip[0]->mbmi)) break;
#endif // CONFIG_SUPERTX && CONFIG_TX64X64
mip2 = mip + mode_info_stride * 4;
if (4 >= max_rows) break;
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip2[0], 32, 8, lfm);
#else
build_masks(lfi_n, mip2[0], 32, 8, lfm);
#endif
break;
#if CONFIG_EXT_DELTA_Q
case BLOCK_32X64: build_masks(cm, lfi_n, mip[0], 0, 0, lfm);
#else
case BLOCK_32X64: build_masks(lfi_n, mip[0], 0, 0, lfm);
#endif
#if CONFIG_SUPERTX && CONFIG_TX64X64
if (supertx_enabled(&mip[0]->mbmi)) break;
#endif // CONFIG_SUPERTX && CONFIG_TX64X64
mip2 = mip + 4;
if (4 >= max_cols) break;
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip2[0], 4, 2, lfm);
#else
build_masks(lfi_n, mip2[0], 4, 2, lfm);
#endif
break;
default:
#if CONFIG_SUPERTX && CONFIG_TX64X64
if (mip[0]->mbmi.tx_size == TX_64X64) {
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], 0, 0, lfm);
#else
build_masks(lfi_n, mip[0], 0, 0, lfm);
#endif
} else {
#endif // CONFIG_SUPERTX && CONFIG_TX64X64
for (idx_32 = 0; idx_32 < 4; mip += offset_32[idx_32], ++idx_32) {
......@@ -1003,31 +1075,56 @@ void av1_setup_mask(AV1_COMMON *const cm, const int mi_row, const int mi_col,
continue;
switch (mip[0]->mbmi.sb_type) {
case BLOCK_32X32:
build_masks(lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#endif
break;
case BLOCK_32X16:
build_masks(lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#endif
#if CONFIG_SUPERTX
if (supertx_enabled(&mip[0]->mbmi)) break;
#endif
if (mi_32_row_offset + 2 >= max_rows) continue;
mip2 = mip + mode_info_stride * 2;
build_masks(lfi_n, mip2[0], shift_y_32 + 16, shift_uv_32 + 4,
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip2[0], shift_y_32 + 16, shift_uv_32 + 4,
lfm);
#else
build_masks(lfi_n, mip2[0], shift_y_32 + 16, shift_uv_32 + 4, lfm);
#endif
break;
case BLOCK_16X32:
build_masks(lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#endif
#if CONFIG_SUPERTX
if (supertx_enabled(&mip[0]->mbmi)) break;
#endif
if (mi_32_col_offset + 2 >= max_cols) continue;
mip2 = mip + 2;
build_masks(lfi_n, mip2[0], shift_y_32 + 2, shift_uv_32 + 1, lfm);
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip2[0], shift_y_32 + 2, shift_uv_32 + 1,
lfm);
#else
build_masks(lfi_n, mip2[0], shift_y_32 + 2, shift_uv_32 + 1, lfm);
#endif
break;
default:
#if CONFIG_SUPERTX
if (mip[0]->mbmi.tx_size == TX_32X32) {
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
#endif
break;
}
#endif
......@@ -1045,49 +1142,82 @@ void av1_setup_mask(AV1_COMMON *const cm, const int mi_row, const int mi_col,
switch (mip[0]->mbmi.sb_type) {
case BLOCK_16X16:
build_masks(lfi_n, mip[0], shift_y_32_16, shift_uv_32_16,
lfm);
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32_16,
shift_uv_32_16, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32_16, shift_uv_32_16,
lfm);
#endif
break;
case BLOCK_16X8:
#if CONFIG_SUPERTX
if (supertx_enabled(&mip[0]->mbmi)) break;
#endif
build_masks(lfi_n, mip[0], shift_y_32_16, shift_uv_32_16,
lfm);
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32_16,
shift_uv_32_16, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32_16, shift_uv_32_16,
lfm);
#endif
if (mi_16_row_offset + 1 >= max_rows) continue;
mip2 = mip + mode_info_stride;
build_y_mask(lfi_n, mip2[0], shift_y_32_16 + 8,
build_y_mask(
#if CONFIG_EXT_DELTA_Q
cm,
#endif
lfi_n, mip2[0], shift_y_32_16 + 8,
#if CONFIG_SUPERTX
0,
0,
#endif
lfm);
lfm);
break;
case BLOCK_8X16:
#if CONFIG_SUPERTX
if (supertx_enabled(&mip[0]->mbmi)) break;
#endif
build_masks(lfi_n, mip[0], shift_y_32_16, shift_uv_32_16,
lfm);
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32_16,
shift_uv_32_16, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32_16, shift_uv_32_16,
lfm);
#endif
if (mi_16_col_offset + 1 >= max_cols) continue;
mip2 = mip + 1;
build_y_mask(lfi_n, mip2[0], shift_y_32_16 + 1,
build_y_mask(
#if CONFIG_EXT_DELTA_Q
cm,
#endif
lfi_n, mip2[0], shift_y_32_16 + 1,
#if CONFIG_SUPERTX
0,
0,
#endif
lfm);
lfm);
break;
default: {
const int shift_y_32_16_8_zero =
shift_y_32_16 + shift_8_y[0];
#if CONFIG_SUPERTX
if (mip[0]->mbmi.tx_size == TX_16X16) {
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32_16_8_zero,
shift_uv_32_16, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32_16_8_zero,
shift_uv_32_16, lfm);
#endif
break;
}
#endif
build_masks(lfi_n, mip[0], shift_y_32_16_8_zero,
#if CONFIG_EXT_DELTA_Q
build_masks(cm, lfi_n, mip[0], shift_y_32_16_8_zero,
shift_uv_32_16, lfm);
#else
build_masks(lfi_n, mip[0], shift_y_32_16_8_zero,
shift_uv_32_16, lfm);
#endif
mip += offset[0];
for (idx_8 = 1; idx_8 < 4; mip += offset[idx_8], ++idx_8) {
const int shift_y_32_16_8 =
......@@ -1100,11 +1230,15 @@ void av1_setup_mask(AV1_COMMON *const cm, const int mi_row, const int mi_col,
if (mi_8_col_offset >= max_cols ||
mi_8_row_offset >= max_rows)
continue;
build_y_mask(lfi_n, mip[0], shift_y_32_16_8,
build_y_mask(
#if CONFIG_EXT_DELTA_Q
cm,
#endif
lfi_n, mip[0], shift_y_32_16_8,
#if CONFIG_SUPERTX
supertx_enabled(&mip[0]->mbmi),
supertx_enabled(&mip[0]->mbmi),
#endif
lfm);
lfm);
}
break;
}
......@@ -1380,8 +1514,13 @@ void av1_filter_block_plane_non420_ver(AV1_COMMON *cm,
: mb_tx_size;
#endif
// Filter level can vary per MI
// Filter level can vary per MI
#if CONFIG_EXT_DELTA_Q
if (!(lfl[r][c_step] = get_filter_level(cm, &cm->lf_info, mbmi)))
continue;
#else
if (!(lfl[r][c_step] = get_filter_level(&cm->lf_info, mbmi))) continue;
#endif
#if CONFIG_VAR_TX
tx_size_r = AOMMIN(tx_size, cm->above_txfm_context[mi_col + c]);
......@@ -1574,8 +1713,13 @@ void av1_filter_block_plane_non420_hor(AV1_COMMON *cm,
}
#endif
// Filter level can vary per MI
// Filter level can vary per MI
#if CONFIG_EXT_DELTA_Q
if (!(lfl[r][c_step] = get_filter_level(cm, &cm->lf_info, mbmi)))
continue;
#else
if (!(lfl[r][c_step] = get_filter_level(&cm->lf_info, mbmi))) continue;
#endif
#if CONFIG_VAR_TX
tx_size_r = AOMMIN(tx_size, cm->above_txfm_context[mi_col + c]);
......@@ -2400,6 +2544,9 @@ void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
MACROBLOCKD *xd, int frame_filter_level, int y_only,
int partial_frame) {
int start_mi_row, end_mi_row, mi_rows_to_filter;
#if CONFIG_EXT_DELTA_Q
int orig_filter_level = cm->lf.filter_level;
#endif
if (!frame_filter_level) return;
start_mi_row = 0;
mi_rows_to_filter = cm->mi_rows;
......@@ -2410,7 +2557,13 @@ void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
}
end_mi_row = start_mi_row + mi_rows_to_filter;
av1_loop_filter_frame_init(cm, frame_filter_level);
#if CONFIG_EXT_DELTA_Q
cm->lf.filter_level = frame_filter_level;
#endif
av1_loop_filter_rows(frame, cm, xd->plane, start_mi_row, end_mi_row, y_only);
#if CONFIG_EXT_DELTA_Q
cm->lf.filter_level = orig_filter_level;
#endif
}
void av1_loop_filter_data_reset(
......
......@@ -389,6 +389,9 @@ typedef struct {
int8_t cdef_strength;
#if CONFIG_DELTA_Q
int current_q_index;
#if CONFIG_EXT_DELTA_Q
int current_delta_lf_from_base;
#endif
#endif
#if CONFIG_RD_DEBUG
RD_STATS rd_stats;
......@@ -617,6 +620,16 @@ typedef struct macroblockd {
int prev_qindex;
int delta_qindex;
int current_qindex;
#if CONFIG_EXT_DELTA_Q
// Since actual frame level loop filtering level value is not available
// at the beginning of the tile (only available during actual filtering)
// at encoder side.we record the delta_lf (against the frame level loop
// filtering level) and code the delta between previous superblock's delta
// lf and current delta lf. It is equivalent to the delta between previous
// superblock's actual lf and current lf.
int prev_delta_lf_from_base;
int current_delta_lf_from_base;
#endif
#endif
#if CONFIG_ADAPT_SCAN
const EobThresholdMD *eob_threshold_md;
......
......@@ -6327,6 +6327,9 @@ void av1_average_tile_intra_cdfs(FRAME_CONTEXT *fc, FRAME_CONTEXT *ec_ctxs[],
#if CONFIG_DELTA_Q
AVERAGE_TILE_CDFS(delta_q_cdf)
#if CONFIG_EXT_DELTA_Q
AVERAGE_TILE_CDFS(delta_lf_cdf)
#endif
#endif
#if CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP
AVERAGE_TILE_CDFS(intra_filter_cdf)
......
......@@ -909,6 +909,15 @@ static const aom_cdf_prob default_delta_q_cdf[CDF_SIZE(DELTA_Q_PROBS + 1)] = {
AOM_ICDF(28160), AOM_ICDF(32120), AOM_ICDF(32677), AOM_ICDF(32768), 0
};
#endif
#if CONFIG_EXT_DELTA_Q
static const aom_prob default_delta_lf_probs[DELTA_LF_PROBS] = { 220, 220,
220 };
#if CONFIG_EC_MULTISYMBOL
static const aom_cdf_prob default_delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)] = {
28160, 32120, 32677, 32768, 0
};
#endif
#endif
#endif
#if CONFIG_EC_MULTISYMBOL
int av1_intra_mode_ind[INTRA_MODES];
......@@ -3279,6 +3288,12 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
#if CONFIG_EC_MULTISYMBOL
av1_copy(fc->delta_q_cdf, default_delta_q_cdf);
#endif // CONFIG_EC_MULTISYMBOL
#if CONFIG_EXT_DELTA_Q
av1_copy(fc->delta_lf_prob, default_delta_lf_probs);
#if CONFIG_EC_MULTISYMBOL
av1_copy(fc->delta_lf_cdf, default_delta_lf_cdf);
#endif // CONFIG_EC_MULTISYMBOL
#endif
#endif // CONFIG_DELTA_Q
}
......@@ -3628,6 +3643,11 @@ void av1_adapt_intra_frame_probs(AV1_COMMON *cm) {
for (i = 0; i < DELTA_Q_PROBS; ++i)
fc->delta_q_prob[i] =
mode_mv_merge_probs(pre_fc->delta_q_prob[i], counts->delta_q[i]);
#if CONFIG_EXT_DELTA_Q
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_EXT_DELTA_Q
#endif
#if CONFIG_EXT_INTRA
#if CONFIG_INTRA_INTERP
......
......@@ -271,6 +271,9 @@ typedef struct frame_contexts {
[CDF_SIZE(MAX_TX_DEPTH + 1)];
#if CONFIG_DELTA_Q
aom_cdf_prob delta_q_cdf[CDF_SIZE(DELTA_Q_PROBS + 1)];
#if CONFIG_EXT_DELTA_Q
aom_cdf_prob delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)];
#endif
#endif // CONFIG_DELTA_Q
#if CONFIG_EXT_TX
aom_cdf_prob intra_ext_tx_cdf[EXT_TX_SETS_INTRA][EXT_TX_SIZES][INTRA_MODES]
......@@ -287,6 +290,9 @@ typedef struct frame_contexts {
#endif // CONFIG_EC_MULTISYMBOL
#if CONFIG_DELTA_Q
aom_prob delta_q_prob[DELTA_Q_PROBS];
#if CONFIG_EXT_DELTA_Q
aom_prob delta_lf_prob[DELTA_LF_PROBS];
#endif
#endif
#if CONFIG_PVQ
// TODO(any): If PVQ is enabled, most of coefficient related cdf,
......@@ -393,6 +399,9 @@ typedef struct FRAME_COUNTS {
#endif
#if CONFIG_DELTA_Q
unsigned int delta_q[DELTA_Q_PROBS][2];
#if CONFIG_EXT_DELTA_Q
unsigned int delta_lf[DELTA_LF_PROBS][2];
#endif
#endif
#if CONFIG_EXT_TX
#if CONFIG_RECT_TX
......
......@@ -427,6 +427,11 @@ typedef enum {
#define DELTA_Q_SMALL 3
#define DELTA_Q_PROBS (DELTA_Q_SMALL)
#define DEFAULT_DELTA_Q_RES 4
#if CONFIG_EXT_DELTA_Q
#define DELTA_LF_SMALL 3
#define DELTA_LF_PROBS (DELTA_LF_SMALL)
#define DEFAULT_DELTA_LF_RES 2
#endif
#endif
/* Segment Feature Masks */
......
......@@ -417,6 +417,11 @@ typedef struct AV1Common {
int delta_q_present_flag;
// Resolution of delta quant
int delta_q_res;
#if CONFIG_EXT_DELTA_Q
int delta_lf_present_flag;
// Resolution of delta lf level
int delta_lf_res;
#endif
#endif
#if CONFIG_TILE_GROUPS
int num_tg;
......
......@@ -4357,6 +4357,9 @@ static size_t read_uncompressed_header(AV1Decoder *pbi,
}
cm->delta_q_res = 1;
#if CONFIG_EXT_DELTA_Q
cm->delta_lf_res = 1;
#endif
if (segment_quantizer_active == 0 && cm->base_qindex > 0) {
cm->delta_q_present_flag = aom_rb_read_bit(rb);
} else {
......@@ -4365,6 +4368,18 @@ static size_t read_uncompressed_header(AV1Decoder *pbi,
if (cm->delta_q_present_flag) {
xd->prev_qindex = cm->base_qindex;
cm->delta_q_res = 1 << aom_rb_read_literal(rb, 2);
#if CONFIG_EXT_DELTA_Q
if (segment_quantizer_active) {
assert(seg->abs_delta == SEGMENT_DELTADATA);
}
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);
} else {
cm->delta_lf_present_flag = 0;
}
#endif // CONFIG_EXT_DELTA_Q
}
}
#endif
......@@ -4598,6 +4613,12 @@ static int read_compressed_header(AV1Decoder *pbi, const uint8_t *data,
for (k = 0; k < DELTA_Q_PROBS; ++k)
av1_diff_update_prob(&r, &fc->delta_q_prob[k], ACCT_STR);
}
#if CONFIG_EXT_DELTA_Q
if (cm->delta_lf_present_flag) {
for (k = 0; k < DELTA_LF_PROBS; ++k)
av1_diff_update_prob(&r, &fc->delta_lf_prob[k], ACCT_STR);
}
#endif
#endif
#if !CONFIG_EC_ADAPT
......
......@@ -109,6 +109,59 @@ static int read_delta_qindex(AV1_COMMON *cm, MACROBLOCKD *xd, aom_reader *r,
}
return reduced_delta_qindex;
}
#if CONFIG_EXT_DELTA_Q
static int read_delta_lflevel(AV1_COMMON *cm, MACROBLOCKD *xd, aom_reader *r,
MB_MODE_INFO *const mbmi, int mi_col,
int mi_row) {
FRAME_COUNTS *counts = xd->counts;
int sign, abs, reduced_delta_lflevel = 0;
BLOCK_SIZE bsize = mbmi->sb_type;
const int b_col = mi_col & MAX_MIB_MASK;
const int b_row = mi_row & MAX_MIB_MASK;
const int read_delta_lf_flag = (b_col == 0 && b_row == 0);
int rem_bits, thr;
int i, smallval;
#if CONFIG_EC_ADAPT
FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
(void)cm;
#else
FRAME_CONTEXT *ec_ctx = cm->fc;
#endif
if ((bsize != BLOCK_64X64 || mbmi->skip == 0) && read_delta_lf_flag) {
#if !CONFIG_EC_MULTISYMBOL
int bit = 1;
abs = 0;
while (abs < DELTA_LF_SMALL && bit) {
bit = aom_read(r, ec_ctx->delta_lf_prob[abs], ACCT_STR);
abs += bit;
}
#else
abs =
aom_read_symbol(r, ec_ctx->delta_lf_cdf, DELTA_LF_PROBS + 1, ACCT_STR);
#endif
smallval = (abs < DELTA_LF_SMALL);
if (counts) {
for (i = 0; i < abs; ++i) counts->delta_lf[i][1]++;
if (smallval) counts->delta_lf[abs][0]++;
}
if (!smallval) {
rem_bits = aom_read_literal(r, 3, ACCT_STR);
thr = (1 << rem_bits) + 1;
abs = aom_read_literal(r, rem_bits, ACCT_STR) + thr;
}
if (abs) {
sign = aom_read_bit(r, ACCT_STR);
} else {
sign = 1;
}
reduced_delta_lflevel = sign ? -abs : abs;
}
return reduced_delta_lflevel;
}
#endif
#endif
static PREDICTION_MODE read_intra_mode_y(AV1_COMMON *cm, MACROBLOCKD *xd,
......@@ -961,6 +1014,15 @@ static void read_intra_frame_mode_info(AV1_COMMON *const cm,
/* Normative: Clamp to [1,MAXQ] to not interfere with lossless mode */
xd->current_qindex = clamp(xd->current_qindex, 1, MAXQ);
xd->prev_qindex = xd->current_qindex;
#if CONFIG_EXT_DELTA_Q
if (cm->delta_lf_present_flag) {
mbmi->current_delta_lf_from_base = xd->current_delta_lf_from_base =
xd->prev_delta_lf_from_base +
read_delta_lflevel(cm, xd, r, mbmi, mi_col, mi_row) *
cm->delta_lf_res;
xd->prev_delta_lf_from_base = xd->current_delta_lf_from_base;
}
#endif