ref: 3b8cc214ef2b2771230d340d2872b89a4bd2a54e
parent: c493ea1a6b7ade049ac22d8d063b73f12d65bbea
parent: 03e8f13337b26bf7940814065f909704c579bb30
author: Marco Paniconi <marpan@google.com>
date: Thu Sep 28 12:52:28 EDT 2017
Merge "vp9: Modification to adapt the ARF usage for 1 pass vbr"
--- 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));
}
}