Re-factor and simplify arnr filter.

Use a weaker filter for second level arf frames.
Average gain across all sets and metrics ~0.3%

Remove code for arnr_type which is no longer
supported in VP9 which always uses a centered blur.

Re-factor and some cleanup.

Change-Id: Ieb4b8940e99e4e02b3fcc9fca6f2d4109e6ed639
This commit is contained in:
Paul Wilkins 2014-07-03 14:55:14 +01:00
parent c0061cc24f
commit e3e6e06155
3 changed files with 67 additions and 144 deletions

View File

@ -2578,9 +2578,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
if (cpi->oxcf.arnr_max_frames > 0) {
// Produce the filtered ARF frame.
// TODO(agrange) merge these two functions.
vp9_configure_arnr_filter(cpi, arf_src_index, rc->gfu_boost);
vp9_temporal_filter_prepare(cpi, arf_src_index);
vp9_temporal_filter(cpi, arf_src_index);
vp9_extend_frame_borders(&cpi->alt_ref_buffer);
force_src_buffer = &cpi->alt_ref_buffer;
}

View File

@ -355,150 +355,32 @@ static void temporal_filter_iterate_c(VP9_COMP *cpi,
mbd->plane[i].pre[0].buf = input_buffer[i];
}
void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance) {
VP9_COMMON *const cm = &cpi->common;
int frame = 0;
int frames_to_blur_backward = 0;
int frames_to_blur_forward = 0;
int frames_to_blur = 0;
int start_frame = 0;
int strength = cpi->active_arnr_strength;
int blur_type = cpi->oxcf.arnr_type;
int max_frames = cpi->active_arnr_frames;
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) {
case 1:
// Backward Blur
frames_to_blur_backward = num_frames_backward;
if (frames_to_blur_backward >= max_frames)
frames_to_blur_backward = max_frames - 1;
frames_to_blur = frames_to_blur_backward + 1;
break;
case 2:
// Forward Blur
frames_to_blur_forward = num_frames_forward;
if (frames_to_blur_forward >= max_frames)
frames_to_blur_forward = max_frames - 1;
frames_to_blur = frames_to_blur_forward + 1;
break;
case 3:
default:
// Center Blur
frames_to_blur_forward = num_frames_forward;
frames_to_blur_backward = num_frames_backward;
if (frames_to_blur_forward > frames_to_blur_backward)
frames_to_blur_forward = frames_to_blur_backward;
if (frames_to_blur_backward > frames_to_blur_forward)
frames_to_blur_backward = frames_to_blur_forward;
// When max_frames is even we have 1 more frame backward than forward
if (frames_to_blur_forward > (max_frames - 1) / 2)
frames_to_blur_forward = ((max_frames - 1) / 2);
if (frames_to_blur_backward > (max_frames / 2))
frames_to_blur_backward = (max_frames / 2);
frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
break;
}
start_frame = distance + frames_to_blur_forward;
#ifdef DEBUGFWG
// DEBUG FWG
printf(
"max:%d FBCK:%d FFWD:%d ftb:%d ftbbck:%d ftbfwd:%d sei:%d lasei:%d "
"start:%d",
max_frames, num_frames_backward, num_frames_forward, frames_to_blur,
frames_to_blur_backward, frames_to_blur_forward, cpi->source_encode_index,
cpi->last_alt_ref_sei, start_frame);
#endif
// Setup scaling factors. Scaling on each of the arnr frames is not supported
vp9_setup_scale_factors_for_frame(&sf,
get_frame_new_buffer(cm)->y_crop_width,
get_frame_new_buffer(cm)->y_crop_height,
cm->width, cm->height);
// Setup frame pointers, NULL indicates frame not included in filter
vp9_zero(cpi->frames);
for (frame = 0; frame < frames_to_blur; frame++) {
int which_buffer = start_frame - frame;
struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead,
which_buffer);
cpi->frames[frames_to_blur - 1 - frame] = &buf->img;
}
temporal_filter_iterate_c(cpi, frames_to_blur, frames_to_blur_backward,
strength, &sf);
}
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;
// Apply buffer limits and context specific adjustments to arnr filter.
static void adjust_arnr_filter(VP9_COMP *cpi,
int distance, int group_boost) {
const int frames_after_arf =
vp9_lookahead_depth(cpi->lookahead) - distance - 1;
int frames_fwd = (cpi->oxcf.arnr_max_frames - 1) >> 1;
int frames_bwd;
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 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 = vp9_lookahead_depth(cpi->lookahead)
- frames_to_arnr - 1;
// Define the forward and backwards filter limits for this arnr group.
if (frames_fwd > frames_after_arf)
frames_fwd = frames_after_arf;
if (frames_fwd > distance)
frames_fwd = distance;
switch (cpi->oxcf.arnr_type) {
case 1: // Backward filter
frames_fwd = 0;
if (frames_bwd > half_gf_int)
frames_bwd = half_gf_int;
break;
frames_bwd = frames_fwd;
case 2: // Forward filter
if (frames_fwd > half_gf_int)
frames_fwd = half_gf_int;
if (frames_fwd > frames_after_arf)
frames_fwd = frames_after_arf;
frames_bwd = 0;
break;
case 3: // Centered filter
default:
frames_fwd >>= 1;
if (frames_fwd > frames_after_arf)
frames_fwd = frames_after_arf;
if (frames_fwd > half_gf_int)
frames_fwd = half_gf_int;
frames_bwd = frames_fwd;
// For even length filter there is one more frame backward
// than forward: e.g. len=6 ==> bbbAff, len=7 ==> bbbAfff.
if (frames_bwd < half_gf_int)
frames_bwd += (cpi->oxcf.arnr_max_frames + 1) & 0x1;
break;
}
// For even length filter there is one more frame backward
// than forward: e.g. len=6 ==> bbbAff, len=7 ==> bbbAfff.
if (frames_bwd < distance)
frames_bwd += (cpi->oxcf.arnr_max_frames + 1) & 0x1;
// Set the baseline active filter size.
cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;
// Adjust the strength based on active max q
// Adjust the strength based on active max q.
if (cpi->common.current_video_frame > 1)
q = ((int)vp9_convert_qindex_to_q(
cpi->rc.avg_frame_qindex[INTER_FRAME]));
@ -521,4 +403,50 @@ void vp9_configure_arnr_filter(VP9_COMP *cpi,
if (cpi->active_arnr_strength > (group_boost / 300)) {
cpi->active_arnr_strength = (group_boost / 300);
}
// Adjustments for second level arf in multi arf case.
if (cpi->pass == 2 && cpi->multi_arf_allowed) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
if (gf_group->rf_level[gf_group->index] != GF_ARF_STD) {
cpi->active_arnr_strength >>= 1;
}
}
}
void vp9_temporal_filter(VP9_COMP *cpi, int distance) {
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
int frame;
int frames_to_blur;
int start_frame;
int strength;
int frames_to_blur_backward;
int frames_to_blur_forward;
struct scale_factors sf;
// Apply context specific adjustments to the arnr filter parameters.
adjust_arnr_filter(cpi, distance, rc->gfu_boost);
strength = cpi->active_arnr_strength;
frames_to_blur = cpi->active_arnr_frames;
frames_to_blur_backward = (frames_to_blur / 2);
frames_to_blur_forward = ((frames_to_blur - 1) / 2);
start_frame = distance + frames_to_blur_forward;
// Setup scaling factors. Scaling on each of the arnr frames not supported.
vp9_setup_scale_factors_for_frame(&sf,
get_frame_new_buffer(cm)->y_crop_width,
get_frame_new_buffer(cm)->y_crop_height,
cm->width, cm->height);
// Setup frame pointers, NULL indicates frame not included in filter.
vp9_zero(cpi->frames);
for (frame = 0; frame < frames_to_blur; ++frame) {
const int which_buffer = start_frame - frame;
struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead,
which_buffer);
cpi->frames[frames_to_blur - 1 - frame] = &buf->img;
}
temporal_filter_iterate_c(cpi, frames_to_blur, frames_to_blur_backward,
strength, &sf);
}

View File

@ -16,10 +16,7 @@ extern "C" {
#endif
void vp9_temporal_filter_init();
void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance);
void vp9_configure_arnr_filter(VP9_COMP *cpi,
const unsigned int frames_to_arnr,
const int group_boost);
void vp9_temporal_filter(VP9_COMP *cpi, int distance);
#ifdef __cplusplus
} // extern "C"