Prelimanry version of objective delta q mode
This prelimanry version of objective deltaq mode uses the temporal
dependency model to derive a qindex offset for use with the
deltaq mode in AV1.
When this mode is turned on (--deltaq-mode=1) currently we get
+0.04% BDRATE as tested on lowres (20 frams, cpu-used 0, end-usage q).
To be improved.
Change-Id: I89bf324cfd3a9ed46ec12cf5d05bd01e62a94680
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 9a0bb20..a6b9d3c 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4237,6 +4237,53 @@
return dr;
}
+static int get_q_for_deltaq_objective(AV1_COMP *const cpi, BLOCK_SIZE bsize,
+ int mi_row, int mi_col) {
+ AV1_COMMON *const cm = &cpi->common;
+ TplDepFrame *tpl_frame = &cpi->tpl_stats[cpi->twopass.gf_group.index];
+ TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
+ int tpl_stride = tpl_frame->stride;
+ int64_t intra_cost = 0;
+ int64_t mc_dep_cost = 0;
+ int mi_wide = mi_size_wide[bsize];
+ int mi_high = mi_size_high[bsize];
+ int row, col;
+
+ double r0, rk, beta;
+
+ if (tpl_frame->is_valid == 0) return cm->base_qindex;
+
+ if (cpi->common.show_frame) return cm->base_qindex;
+
+ if (cpi->twopass.gf_group.index >= MAX_LAG_BUFFERS) return cm->base_qindex;
+
+ for (row = mi_row; row < mi_row + mi_high; ++row) {
+ for (col = mi_col; col < mi_col + mi_wide; ++col) {
+ TplDepStats *this_stats = &tpl_stats[row * tpl_stride + col];
+
+ if (row >= cm->mi_rows || col >= cm->mi_cols) continue;
+
+ intra_cost += this_stats->intra_cost;
+ mc_dep_cost += this_stats->mc_dep_cost;
+ }
+ }
+
+ aom_clear_system_state();
+
+ r0 = cpi->rd.r0;
+ rk = (double)intra_cost / mc_dep_cost;
+ beta = r0 / rk;
+
+ int offset = -(int)(log(beta) * 16.0);
+ offset = AOMMIN(offset, 16);
+ offset = AOMMAX(offset, -16);
+ int qindex = cm->base_qindex + offset;
+ qindex = AOMMIN(qindex, MAXQ);
+ qindex = AOMMAX(qindex, MINQ);
+
+ return qindex;
+}
+
static void setup_delta_q(AV1_COMP *const cpi, MACROBLOCK *const x,
const TileInfo *const tile_info, int mi_row,
int mi_col, int num_planes) {
@@ -4249,21 +4296,28 @@
// Delta-q modulation based on variance
av1_setup_src_planes(x, cpi->source, mi_row, mi_col, num_planes, sb_size);
- int current_qindex;
- if (DELTA_Q_PERCEPTUAL_MODULATION == 1) {
- const int block_wavelet_energy_level =
- av1_block_wavelet_energy_level(cpi, x, sb_size);
- x->sb_energy_level = block_wavelet_energy_level;
- current_qindex = av1_compute_q_from_energy_level_deltaq_mode(
- cpi, block_wavelet_energy_level);
- } else {
- const int block_var_level = av1_log_block_var(cpi, x, sb_size);
- x->sb_energy_level = block_var_level;
- current_qindex =
- av1_compute_q_from_energy_level_deltaq_mode(cpi, block_var_level);
+ int current_qindex = cm->base_qindex;
+ if (cpi->oxcf.deltaq_mode == DELTA_Q_PERCEPTUAL) {
+ if (DELTA_Q_PERCEPTUAL_MODULATION == 1) {
+ const int block_wavelet_energy_level =
+ av1_block_wavelet_energy_level(cpi, x, sb_size);
+ x->sb_energy_level = block_wavelet_energy_level;
+ current_qindex = av1_compute_q_from_energy_level_deltaq_mode(
+ cpi, block_wavelet_energy_level);
+ } else {
+ const int block_var_level = av1_log_block_var(cpi, x, sb_size);
+ x->sb_energy_level = block_var_level;
+ current_qindex =
+ av1_compute_q_from_energy_level_deltaq_mode(cpi, block_var_level);
+ }
+ } else if (cpi->oxcf.deltaq_mode == DELTA_Q_OBJECTIVE) {
+ assert(cpi->oxcf.enable_tpl_model);
+ // Setup deltaq based on tpl stats
+ current_qindex = get_q_for_deltaq_objective(cpi, sb_size, mi_row, mi_col);
}
+
const int qmask = ~(delta_q_info->delta_q_res - 1);
- current_qindex = clamp(current_qindex, -delta_q_info->delta_q_res,
+ current_qindex = clamp(current_qindex, delta_q_info->delta_q_res,
256 - delta_q_info->delta_q_res);
current_qindex =
((current_qindex - xd->current_qindex + delta_q_info->delta_q_res / 2) &
@@ -4275,6 +4329,8 @@
set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
xd->mi[0]->current_qindex = current_qindex;
av1_init_plane_quantizers(cpi, x, xd->mi[0]->segment_id);
+ x->rdmult = set_deltaq_rdmult(cpi, xd);
+
if (cpi->oxcf.deltaq_mode != NO_DELTA_Q && cpi->oxcf.deltalf_mode) {
const int lfmask = ~(delta_q_info->delta_lf_res - 1);
const int delta_lf_from_base =
@@ -4549,6 +4605,19 @@
CFL_ALPHABET_SIZE);
}
+static void adjust_rdmult_tpl_model(AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
+ int mi_col) {
+ const BLOCK_SIZE sb_size = cpi->common.seq_params.sb_size;
+ const int orig_rdmult = cpi->rd.RDMULT;
+ x->cb_rdmult = orig_rdmult;
+ if (cpi->twopass.gf_group.index > 0 && cpi->oxcf.enable_tpl_model &&
+ cpi->oxcf.aq_mode == NO_AQ && cpi->oxcf.deltaq_mode == NO_DELTA_Q) {
+ const int dr = get_rdmult_delta(cpi, sb_size, mi_row, mi_col, orig_rdmult);
+ x->rdmult = dr;
+ x->cb_rdmult = x->rdmult;
+ }
+}
+
static void encode_sb_row(AV1_COMP *cpi, ThreadData *td, TileDataEnc *tile_data,
int mi_row, TOKENEXTRA **tp, int use_nonrd_mode) {
AV1_COMMON *const cm = &cpi->common;
@@ -4684,12 +4753,14 @@
x->source_variance = UINT_MAX;
x->simple_motion_pred_sse = UINT_MAX;
if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {
+ adjust_rdmult_tpl_model(cpi, x, mi_row, mi_col);
set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
const BLOCK_SIZE bsize = seg_skip ? sb_size : sf->always_this_block_size;
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
&dummy_rate, &dummy_dist, 1, pc_root);
} else if (cpi->partition_search_skippable_frame) {
+ adjust_rdmult_tpl_model(cpi, x, mi_row, mi_col);
set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
const BLOCK_SIZE bsize =
get_rd_var_based_fixed_partition(cpi, x, mi_row, mi_col);
@@ -4704,17 +4775,7 @@
nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
pc_root);
} else {
- const int orig_rdmult = cpi->rd.RDMULT;
- x->cb_rdmult = orig_rdmult;
- if (cpi->twopass.gf_group.index > 0 && cpi->oxcf.enable_tpl_model &&
- cpi->oxcf.aq_mode == NO_AQ && cpi->oxcf.deltaq_mode == NO_DELTA_Q) {
- const int dr =
- get_rdmult_delta(cpi, BLOCK_128X128, mi_row, mi_col, orig_rdmult);
-
- x->cb_rdmult = dr;
- x->rdmult = x->cb_rdmult;
- }
-
+ adjust_rdmult_tpl_model(cpi, x, mi_row, mi_col);
reset_partition(pc_root, sb_size);
x->use_cb_search_range = 0;
#if CONFIG_COLLECT_COMPONENT_TIMING