Enables alt-ref frames in one pass mode

Includes a few fixes and clean-ups that adds the ability
to use alt-ref frames in one-pass mode.
Whether alt-refs are actually used or not is controlled by a
macro USE_ALTREF_FOR_ONE_PASS in vp9_firstpass.c.

This first cut seems to improve derf by 15+% in 1-pass mode.
But further experiments with parameters are underway.

Change-Id: I78254421435478003367c788c7930d2dc4ee2816
This commit is contained in:
Deb Mukherjee 2014-01-22 18:00:08 -08:00
parent 00bfacb769
commit 50bf8fd4f5
6 changed files with 58 additions and 56 deletions

View File

@ -2328,6 +2328,7 @@ void vp9_get_svc_params(VP9_COMP *cpi) {
(cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
cpi->key_frame_frequency == 0))) {
cm->frame_type = KEY_FRAME;
cpi->rc.source_alt_ref_active = 0;
} else {
cm->frame_type = INTER_FRAME;
}
@ -2335,6 +2336,9 @@ void vp9_get_svc_params(VP9_COMP *cpi) {
cpi->rc.baseline_gf_interval = INT_MAX;
}
// Use this macro to turn on/off use of alt-refs in one-pass mode.
#define USE_ALTREF_FOR_ONE_PASS 1
void vp9_get_one_pass_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
if (!cpi->refresh_alt_ref_frame &&
@ -2346,13 +2350,20 @@ void vp9_get_one_pass_params(VP9_COMP *cpi) {
cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
cpi->rc.frames_to_key == 0;
cpi->rc.frames_to_key = cpi->key_frame_frequency;
cpi->rc.kf_boost = 300;
cpi->rc.kf_boost = 2000;
cpi->rc.source_alt_ref_active = 0;
} else {
cm->frame_type = INTER_FRAME;
}
if (cpi->rc.frames_till_gf_update_due == 0) {
cpi->rc.baseline_gf_interval = DEFAULT_GF_INTERVAL;
cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
// NOTE: frames_till_gf_update_due must be <= frames_to_key.
if (cpi->rc.frames_till_gf_update_due > cpi->rc.frames_to_key)
cpi->rc.frames_till_gf_update_due = cpi->rc.frames_to_key;
cpi->refresh_golden_frame = 1;
cpi->rc.source_alt_ref_pending = USE_ALTREF_FOR_ONE_PASS;
cpi->rc.gfu_boost = 1000;
}
}
@ -2366,7 +2377,8 @@ void vp9_get_one_pass_cbr_params(VP9_COMP *cpi) {
cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
cpi->rc.frames_to_key == 0;
cpi->rc.frames_to_key = cpi->key_frame_frequency;
cpi->rc.kf_boost = 300;
cpi->rc.kf_boost = 2000;
cpi->rc.source_alt_ref_active = 0;
} else {
cm->frame_type = INTER_FRAME;
}
@ -2400,12 +2412,13 @@ void vp9_get_second_pass_params(VP9_COMP *cpi) {
double this_frame_intra_error;
double this_frame_coded_error;
if (cpi->refresh_alt_ref_frame) {
cpi->common.frame_type = INTER_FRAME;
return;
}
if (!cpi->twopass.stats_in)
return;
if (cpi->refresh_alt_ref_frame) {
cpi->common.frame_type = INTER_FRAME;
rc->per_frame_bandwidth = cpi->twopass.gf_bits;
return;
}
vp9_clear_system_state();

View File

@ -173,7 +173,6 @@ struct lookahead_entry * vp9_lookahead_peek(struct lookahead_ctx *ctx,
int index) {
struct lookahead_entry *buf = NULL;
assert(index < (int)ctx->max_sz);
if (index < (int)ctx->sz) {
index += ctx->read_idx;
if (index >= (int)ctx->max_sz)

View File

@ -2953,15 +2953,6 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
// Clear down mmx registers to allow floating point in what follows.
vp9_clear_system_state();
// For an alt ref frame in 2 pass we skip the call to the second
// pass function that sets the target bandwidth so we must set it here.
if (cpi->refresh_alt_ref_frame) {
// Set a per frame bit target for the alt ref frame.
cpi->rc.per_frame_bandwidth = cpi->twopass.gf_bits;
// Set a per second target bitrate.
cpi->target_bandwidth = (int)(cpi->twopass.gf_bits * cpi->output_framerate);
}
// Clear zbin over-quant value and mode boost values.
cpi->zbin_mode_boost = 0;
@ -3293,7 +3284,6 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size,
vp9_get_second_pass_params(cpi);
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
// vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt");
vp9_twopass_postencode_update(cpi, *size);
}
@ -3442,8 +3432,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
if (cpi->oxcf.arnr_max_frames > 0) {
// Produce the filtered ARF frame.
// TODO(agrange) merge these two functions.
configure_arnr_filter(cpi, cm->current_video_frame + frames_to_arf,
cpi->rc.gfu_boost);
vp9_configure_arnr_filter(cpi, frames_to_arf, cpi->rc.gfu_boost);
vp9_temporal_filter_prepare(cpi, frames_to_arf);
vp9_extend_frame_borders(&cpi->alt_ref_buffer,
cm->subsampling_x, cm->subsampling_y);
@ -3459,7 +3448,9 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
#if CONFIG_MULTIPLE_ARF
if (!cpi->multi_arf_enabled)
#endif
cpi->rc.source_alt_ref_pending = 0; // Clear Pending altf Ref flag.
cpi->rc.source_alt_ref_pending = 0;
} else {
cpi->rc.source_alt_ref_pending = 0;
}
}

View File

@ -218,7 +218,7 @@ static void calc_iframe_target_size(VP9_COMP *cpi) {
vp9_clear_system_state(); // __asm emms;
// For 1-pass.
if (cpi->pass == 0) {
if (cpi->pass == 0 && oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
if (cpi->common.current_video_frame == 0) {
target = oxcf->starting_buffer_level / 2;
} else {
@ -246,7 +246,7 @@ static void calc_iframe_target_size(VP9_COMP *cpi) {
if (oxcf->rc_max_intra_bitrate_pct) {
const int max_rate = rc->per_frame_bandwidth *
oxcf->rc_max_intra_bitrate_pct / 100;
oxcf->rc_max_intra_bitrate_pct / 100;
target = MIN(target, max_rate);
}
rc->this_frame_target = target;
@ -375,27 +375,22 @@ static int target_size_from_buffer_level(const VP9_CONFIG *oxcf,
static void calc_pframe_target_size(VP9_COMP *const cpi) {
RATE_CONTROL *const rc = &cpi->rc;
const VP9_CONFIG *const oxcf = &cpi->oxcf;
int min_frame_target = MAX(rc->min_frame_bandwidth,
rc->av_per_frame_bandwidth >> 5);
if (cpi->refresh_alt_ref_frame) {
// Special alt reference frame case
// Per frame bit target for the alt ref frame
rc->per_frame_bandwidth = cpi->twopass.gf_bits;
rc->this_frame_target = rc->per_frame_bandwidth;
} else {
// Normal frames (gf and inter).
rc->this_frame_target = rc->per_frame_bandwidth;
// Set target frame size based on buffer level, for 1 pass CBR.
if (cpi->pass == 0 && oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
// Need to decide how low min_frame_target should be for 1-pass CBR.
// For now, use: cpi->rc.av_per_frame_bandwidth / 16:
min_frame_target = MAX(rc->av_per_frame_bandwidth >> 4,
FRAME_OVERHEAD_BITS);
rc->this_frame_target = target_size_from_buffer_level(oxcf, rc);
// Adjust qp-max based on buffer level.
rc->active_worst_quality =
adjust_active_worst_quality_from_buffer_level(oxcf, rc);
}
int min_frame_target;
rc->this_frame_target = rc->per_frame_bandwidth;
if (cpi->pass == 0 && oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
// Need to decide how low min_frame_target should be for 1-pass CBR.
// For now, use: cpi->rc.av_per_frame_bandwidth / 16:
min_frame_target = MAX(rc->av_per_frame_bandwidth >> 4,
FRAME_OVERHEAD_BITS);
rc->this_frame_target = target_size_from_buffer_level(oxcf, rc);
// Adjust qp-max based on buffer level.
rc->active_worst_quality =
adjust_active_worst_quality_from_buffer_level(oxcf, rc);
if (rc->this_frame_target < min_frame_target)
rc->this_frame_target = min_frame_target;
return;
}
// Check that the total sum of adjustments is not above the maximum allowed.
@ -404,6 +399,9 @@ static void calc_pframe_target_size(VP9_COMP *const cpi) {
// not capable of recovering all the extra bits we have spent in the KF or GF,
// then the remainder will have to be recovered over a longer time span via
// other buffer / rate control mechanisms.
min_frame_target = MAX(rc->min_frame_bandwidth,
rc->av_per_frame_bandwidth >> 5);
if (rc->this_frame_target < min_frame_target)
rc->this_frame_target = min_frame_target;

View File

@ -392,7 +392,6 @@ void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance) {
const int num_frames_backward = distance;
const int num_frames_forward = vp9_lookahead_depth(cpi->lookahead)
- (num_frames_backward + 1);
struct scale_factors sf;
switch (blur_type) {
@ -408,7 +407,6 @@ void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance) {
case 2:
// Forward Blur
frames_to_blur_forward = num_frames_forward;
if (frames_to_blur_forward >= max_frames)
@ -471,22 +469,24 @@ void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance) {
strength, &sf);
}
void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
const int group_boost) {
void vp9_configure_arnr_filter(VP9_COMP *cpi,
const unsigned int frames_to_arnr,
const int group_boost) {
int half_gf_int;
int frames_after_arf;
int frames_bwd = cpi->oxcf.arnr_max_frames - 1;
int frames_fwd = cpi->oxcf.arnr_max_frames - 1;
int q;
// Define the arnr filter width for this group of frames:
// We only filter frames that lie within a distance of half
// the GF interval from the ARF frame. We also have to trap
// cases where the filter extends beyond the end of clip.
// Note: this_frame->frame has been updated in the loop
// so it now points at the ARF frame.
// Define the arnr filter width for this group of frames. We only
// filter frames that lie within a distance of half the GF interval
// from the ARF frame. We also have to trap cases where the filter
// extends beyond the end of the lookahead buffer.
// Note: frames_to_arnr parameter is the offset of the arnr
// frame from the current frame.
half_gf_int = cpi->rc.baseline_gf_interval >> 1;
frames_after_arf = (int)(cpi->twopass.total_stats.count - this_frame - 1);
frames_after_arf = vp9_lookahead_depth(cpi->lookahead)
- frames_to_arnr - 1;
switch (cpi->oxcf.arnr_type) {
case 1: // Backward filter

View File

@ -16,8 +16,9 @@ extern "C" {
#endif
void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance);
void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
const int group_boost);
void vp9_configure_arnr_filter(VP9_COMP *cpi,
const unsigned int frames_to_arnr,
const int group_boost);
#ifdef __cplusplus
} // extern "C"