Experiment to adapt for net AQ offset.

In Aq mode 1 the segment and AQ delta for each block is based
on spatial variance. There may be a net imbalance between blocks
that have lower Q than the baseline value and those that have higher Q.

This patch monitors that imbalance and extends the allowed baseline
Q range for the frame to accommodate adjustment of that baseline value
to compensate.

Change-Id: Iae8a48c7c01fe2af94a141e149d03acf467237ca
This commit is contained in:
paulwilkins 2016-03-11 10:44:16 +00:00
parent 52889c1016
commit 4b590058c8
5 changed files with 57 additions and 5 deletions

View File

@ -28,6 +28,7 @@ static const int seg_feature_data_max[SEG_LVL_MAX] = {
void vp9_clearall_segfeatures(struct segmentation *seg) {
vp9_zero(seg->feature_data);
vp9_zero(seg->feature_mask);
seg->aq_av_offset = 0;
}
void vp9_enable_segfeature(struct segmentation *seg, int segment_id,

View File

@ -47,6 +47,7 @@ struct segmentation {
int16_t feature_data[MAX_SEGMENTS][SEG_LVL_MAX];
unsigned int feature_mask[MAX_SEGMENTS];
int aq_av_offset;
};
static INLINE int segfeature_active(const struct segmentation *seg,

View File

@ -4137,6 +4137,31 @@ static INTERP_FILTER get_interp_filter(
}
}
static int compute_frame_aq_offset(struct VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
MODE_INFO **mi_8x8_ptr = cm->mi_grid_visible;
struct segmentation *const seg = &cm->seg;
int mi_row, mi_col;
int sum_delta = 0;
int map_index = 0;
int qdelta_index;
int segment_id;
for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) {
MODE_INFO **mi_8x8 = mi_8x8_ptr;
for (mi_col = 0; mi_col < cm->mi_cols; mi_col++, mi_8x8++) {
segment_id = mi_8x8[0]->segment_id;
qdelta_index = get_segdata(seg, segment_id, SEG_LVL_ALT_Q);
sum_delta += qdelta_index;
map_index++;
}
mi_8x8_ptr += cm->mi_stride;
}
return sum_delta / (cm->mi_rows * cm->mi_cols);
}
void vp9_encode_frame(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
@ -4259,8 +4284,13 @@ void vp9_encode_frame(VP9_COMP *cpi) {
cm->reference_mode = SINGLE_REFERENCE;
encode_frame_internal(cpi);
}
}
// If segmentated AQ is enabled compute the average AQ weighting.
if (cm->seg.enabled && (cpi->oxcf.aq_mode != NO_AQ) &&
(cm->seg.update_map || cm->seg.update_data)) {
cm->seg.aq_av_offset = compute_frame_aq_offset(cpi);
}
}
static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) {
const PREDICTION_MODE y_mode = mi->mode;
const PREDICTION_MODE uv_mode = mi->uv_mode;

View File

@ -3137,7 +3137,7 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
"%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf"
"%6d %6d %5d %5d %5d "
"%10"PRId64" %10.3lf"
"%10lf %8u %10"PRId64" %10d %10d %10d %10d\n",
"%10lf %8u %10"PRId64" %10d %10d %10d %10d %10d\n",
cpi->common.current_video_frame,
cm->width, cm->height,
cpi->td.rd_counts.m_search_count,
@ -3171,7 +3171,8 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
cpi->tot_recode_hits, recon_err, cpi->rc.kf_boost,
cpi->twopass.kf_zeromotion_pct,
cpi->twopass.fr_content_type,
cm->lf.filter_level);
cm->lf.filter_level,
cm->seg.aq_av_offset);
}
fclose(f);

View File

@ -2849,6 +2849,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
void vp9_twopass_postencode_update(VP9_COMP *cpi) {
TWO_PASS *const twopass = &cpi->twopass;
RATE_CONTROL *const rc = &cpi->rc;
VP9_COMMON *const cm = &cpi->common;
const int bits_used = rc->base_frame_target;
// VBR correction is done through rc->vbr_bits_off_target. Based on the
@ -2886,6 +2887,22 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) {
rc->worst_quality - twopass->active_worst_quality;
const int minq_adj_limit =
(cpi->oxcf.rc_mode == VPX_CQ ? MINQ_ADJ_LIMIT_CQ : MINQ_ADJ_LIMIT);
int aq_extend_min = 0;
int aq_extend_max = 0;
// Extend min or Max Q range to account for imbalance from the base
// value when using AQ.
if (cpi->oxcf.aq_mode != NO_AQ) {
if (cm->seg.aq_av_offset < 0) {
// The balance of the AQ map tends towarda lowering the average Q.
aq_extend_min = 0;
aq_extend_max = VPXMIN(maxq_adj_limit, -cm->seg.aq_av_offset);
} else {
// The balance of the AQ map tends towards raising the average Q.
aq_extend_min = VPXMIN(minq_adj_limit, cm->seg.aq_av_offset);
aq_extend_max = 0;
}
}
// Undershoot.
if (rc->rate_error_estimate > cpi->oxcf.under_shoot_pct) {
@ -2910,8 +2927,10 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) {
--twopass->extend_maxq;
}
twopass->extend_minq = clamp(twopass->extend_minq, 0, minq_adj_limit);
twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit);
twopass->extend_minq =
clamp(twopass->extend_minq, aq_extend_min, minq_adj_limit);
twopass->extend_maxq =
clamp(twopass->extend_maxq, aq_extend_max, maxq_adj_limit);
// If there is a big and undexpected undershoot then feed the extra
// bits back in quickly. One situation where this may happen is if a