From e3e6e06155e3bdefac9775b6b50d84aaf1aca06c Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Thu, 3 Jul 2014 14:55:14 +0100 Subject: [PATCH] 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 --- vp9/encoder/vp9_encoder.c | 4 +- vp9/encoder/vp9_temporal_filter.c | 204 ++++++++++++-------------------------- vp9/encoder/vp9_temporal_filter.h | 5 +- 3 files changed, 68 insertions(+), 145 deletions(-) diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index e0e0561..1c514ba 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -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; } diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c index c090731..f4b4e04 100644 --- a/vp9/encoder/vp9_temporal_filter.c +++ b/vp9/encoder/vp9_temporal_filter.c @@ -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; - } +// 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; - temporal_filter_iterate_c(cpi, frames_to_blur, frames_to_blur_backward, - strength, &sf); -} + // 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; -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; + frames_bwd = frames_fwd; - // 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; - - switch (cpi->oxcf.arnr_type) { - case 1: // Backward filter - frames_fwd = 0; - if (frames_bwd > half_gf_int) - frames_bwd = half_gf_int; - break; - - 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); } diff --git a/vp9/encoder/vp9_temporal_filter.h b/vp9/encoder/vp9_temporal_filter.h index 9453dc1..a971e0a 100644 --- a/vp9/encoder/vp9_temporal_filter.h +++ b/vp9/encoder/vp9_temporal_filter.h @@ -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" -- 2.7.4