ref: 03e8f13337b26bf7940814065f909704c579bb30
parent: d203a91a0989d84a0887bfc8569f1c79289e80c2
author: Marco <marpan@google.com>
date: Thu Sep 21 06:59:33 EDT 2017
vp9: Modification to adapt the ARF usage for 1 pass vbr Add stats for past ARF usage, and use it to disable ARF usage based on some conditions. Overall improvement on ytlive set, reduces the regression on the problem clips for this feature. Only affects when sf->use_altref_onepass is enabled (currently off by default). Change-Id: I66267f227ea132dc86acb730e9882f85bead2cdb
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -189,6 +189,9 @@
// 32x32, 9~24 for 16x16.
uint8_t variance_low[25];
+ uint8_t arf_frame_usage;
+ uint8_t lastgolden_frame_usage;
+
void (*fwd_txfm4x4)(const int16_t *input, tran_low_t *output, int stride);
void (*inv_txfm_add)(const tran_low_t *input, uint8_t *dest, int stride,
int eob);
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -4163,6 +4163,8 @@
x->sb_mvcol_part = 0;
x->sb_mvrow_part = 0;
x->sb_pickmode_part = 0;
+ x->arf_frame_usage = 0;
+ x->lastgolden_frame_usage = 0;
if (seg->enabled) {
const uint8_t *const map =
@@ -4239,6 +4241,17 @@
break;
default: assert(0); break;
+ }
+
+ // Update ref_frame usage for inter frame if this group is ARF group.
+ if (!cpi->rc.is_src_frame_alt_ref && !cpi->refresh_golden_frame &&
+ !cpi->refresh_alt_ref_frame && cpi->rc.alt_ref_gf_group &&
+ cpi->sf.use_altref_onepass) {
+ int sboffset = ((cm->mi_cols + 7) >> 3) * (mi_row >> 3) + (mi_col >> 3);
+ if (cpi->count_arf_frame_usage != NULL)
+ cpi->count_arf_frame_usage[sboffset] = x->arf_frame_usage;
+ if (cpi->count_lastgolden_frame_usage != NULL)
+ cpi->count_lastgolden_frame_usage[sboffset] = x->lastgolden_frame_usage;
}
(*(cpi->row_mt_sync_write_ptr))(&tile_data->row_mt_sync, sb_row,
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -798,6 +798,11 @@
vpx_free(cpi->content_state_sb_fd);
cpi->content_state_sb_fd = NULL;
+ vpx_free(cpi->count_arf_frame_usage);
+ cpi->count_arf_frame_usage = NULL;
+ vpx_free(cpi->count_lastgolden_frame_usage);
+ cpi->count_lastgolden_frame_usage = NULL;
+
vp9_cyclic_refresh_free(cpi->cyclic_refresh);
cpi->cyclic_refresh = NULL;
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -717,6 +717,9 @@
int compute_source_sad_onepass;
LevelConstraint level_constraint;
+
+ uint8_t *count_arf_frame_usage;
+ uint8_t *count_lastgolden_frame_usage;
} VP9_COMP;
void vp9_initialize_enc(void);
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -2288,6 +2288,11 @@
}
#endif
+ if (best_ref_frame == ALTREF_FRAME)
+ x->arf_frame_usage++;
+ else if (best_ref_frame != INTRA_FRAME)
+ x->lastgolden_frame_usage++;
+
if (cpi->sf.adaptive_rd_thresh) {
THR_MODES best_mode_idx = mode_idx[best_ref_frame][mode_offset(mi->mode)];
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -591,12 +591,6 @@
q = clamp(q, VPXMIN(cpi->rc.q_1_frame, cpi->rc.q_2_frame),
VPXMAX(cpi->rc.q_1_frame, cpi->rc.q_2_frame));
}
- if (cpi->sf.use_altref_onepass && cpi->oxcf.enable_auto_arf &&
- cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_VBR &&
- cpi->oxcf.lag_in_frames > 0 && cpi->rc.is_src_frame_alt_ref &&
- !cpi->rc.alt_ref_gf_group) {
- q = VPXMIN(q, (q + cpi->rc.last_boosted_qindex) >> 1);
- }
return q;
}
@@ -1337,6 +1331,28 @@
}
}
+static void update_altref_usage(VP9_COMP *const cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ int sum_ref_frame_usage = 0;
+ int arf_frame_usage = 0;
+ int mi_row, mi_col;
+ if (cpi->rc.alt_ref_gf_group && !cpi->rc.is_src_frame_alt_ref &&
+ !cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame)
+ for (mi_row = 0; mi_row < cm->mi_rows; mi_row += 8) {
+ for (mi_col = 0; mi_col < cm->mi_cols; mi_col += 8) {
+ int sboffset = ((cm->mi_cols + 7) >> 3) * (mi_row >> 3) + (mi_col >> 3);
+ sum_ref_frame_usage += cpi->count_arf_frame_usage[sboffset] +
+ cpi->count_lastgolden_frame_usage[sboffset];
+ arf_frame_usage += cpi->count_arf_frame_usage[sboffset];
+ }
+ }
+ if (sum_ref_frame_usage > 0) {
+ double altref_count = 100.0 * arf_frame_usage / sum_ref_frame_usage;
+ cpi->rc.perc_arf_usage =
+ 0.75 * cpi->rc.perc_arf_usage + 0.25 * altref_count;
+ }
+}
+
static void compute_frame_low_motion(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
int mi_row, mi_col;
@@ -1460,7 +1476,10 @@
}
if (oxcf->pass == 0) {
- if (cm->frame_type != KEY_FRAME) compute_frame_low_motion(cpi);
+ if (cm->frame_type != KEY_FRAME) {
+ compute_frame_low_motion(cpi);
+ if (cpi->sf.use_altref_onepass) update_altref_usage(cpi);
+ }
}
if (cm->frame_type != KEY_FRAME) rc->reset_high_source_sad = 0;
}
@@ -2202,9 +2221,15 @@
rc->gfu_boost = DEFAULT_GF_BOOST >> 2;
}
if (cpi->sf.use_altref_onepass && cpi->oxcf.enable_auto_arf) {
- // Don't use alt-ref if there is a scene cut within the group,
- // or content is not low.
- if ((rc->high_source_sad_lagindex > 0 &&
+ // Flag to disable usage of ARF based on past usage, only allow this
+ // disabling if current frame/group does not start with key frame or
+ // scene cut. Note perc_arf_usage is only computed for speed >= 5.
+ int arf_usage_low =
+ (cm->frame_type != KEY_FRAME && !rc->high_source_sad &&
+ cpi->rc.perc_arf_usage < 15 && cpi->oxcf.speed >= 5);
+ // Don't use alt-ref for this group under certain conditions.
+ if (arf_usage_low ||
+ (rc->high_source_sad_lagindex > 0 &&
rc->high_source_sad_lagindex <= rc->frames_till_gf_update_due) ||
(avg_source_sad_lag > 3 * sad_thresh1 >> 3)) {
rc->source_alt_ref_pending = 0;
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -170,6 +170,7 @@
int af_ratio_onepass_vbr;
int force_qpmin;
int reset_high_source_sad;
+ double perc_arf_usage;
} RATE_CONTROL;
struct VP9_COMP;
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -525,9 +525,13 @@
if (speed >= 6) {
sf->partition_search_type = VAR_BASED_PARTITION;
if (cpi->oxcf.rc_mode == VPX_VBR && cpi->oxcf.lag_in_frames > 0 &&
- cpi->rc.is_src_frame_alt_ref && !is_keyframe) {
- sf->partition_search_type = FIXED_PARTITION;
- sf->always_this_block_size = BLOCK_64X64;
+ !is_keyframe) {
+ if (cpi->rc.is_src_frame_alt_ref) {
+ sf->partition_search_type = FIXED_PARTITION;
+ sf->always_this_block_size = BLOCK_64X64;
+ } else if (sf->use_altref_onepass && cpi->refresh_alt_ref_frame) {
+ sf->partition_search_type = REFERENCE_PARTITION;
+ }
}
// Turn on this to use non-RD key frame coding mode.
sf->use_nonrd_pick_mode = 1;
@@ -631,6 +635,16 @@
}
sf->limit_newmv_early_exit = 0;
sf->use_simple_block_yrd = 1;
+ }
+ if (sf->use_altref_onepass) {
+ if (cpi->count_arf_frame_usage == NULL)
+ cpi->count_arf_frame_usage =
+ (uint8_t *)vpx_calloc((cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1),
+ sizeof(*cpi->count_arf_frame_usage));
+ if (cpi->count_lastgolden_frame_usage == NULL)
+ cpi->count_lastgolden_frame_usage =
+ (uint8_t *)vpx_calloc((cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1),
+ sizeof(*cpi->count_lastgolden_frame_usage));
}
}