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,
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,
}
}
+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;
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;
"%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,
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);
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
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) {
--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