From 788c0eb54ef741153557953c22fe3f14bceb13d3 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Sat, 2 Oct 2010 17:31:46 +0100 Subject: Tune effect of motion on KF/GF boost in two pass; This code adjust the impact of the amount and speed of motion on GF and KF boost. Sections with lots of slow motion will tend to have a somewhat bigger boost and sections with fast motion may have less. There is a knock on effect to the selection of the active quantizer range. This will likely require further tuning but helps with a couple of particularly bad edge cases. Change-Id: Ic2449cda7305672b69acf42fc0a845b77ac98d40 --- vp8/encoder/firstpass.c | 86 +++++++++++++++++++++++++++++++++++-------------- vp8/encoder/onyx_if.c | 4 +-- 2 files changed, 64 insertions(+), 26 deletions(-) (limited to 'vp8') diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index 0a6e8c50e..13633e9a4 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -1218,10 +1218,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) double mv_accumulator_rabs = 0.0; double mv_accumulator_cabs = 0.0; - double this_mv_rabs; - double this_mv_cabs; double mv_ratio_accumulator = 0.0; - double distance_factor = 0.0; double decay_accumulator = 1.0; double boost_factor = IIFACTOR; @@ -1270,9 +1267,10 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) while (((i < cpi->max_gf_interval) || ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) && (i < cpi->frames_to_key)) { double r; - double motion_factor; double this_frame_mvr_ratio; double this_frame_mvc_ratio; + double motion_decay; + double motion_pct = next_frame.pcnt_motion; i++; // Increment the loop counter @@ -1287,12 +1285,8 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) break; // Accumulate motion stats. - motion_factor = next_frame.pcnt_motion; - this_mv_rabs = fabs(next_frame.mvr_abs * motion_factor); - this_mv_cabs = fabs(next_frame.mvc_abs * motion_factor); - - mv_accumulator_rabs += fabs(next_frame.mvr_abs * motion_factor); - mv_accumulator_cabs += fabs(next_frame.mvc_abs * motion_factor); + mv_accumulator_rabs += fabs(next_frame.mvr_abs * motion_pct); + mv_accumulator_cabs += fabs(next_frame.mvc_abs * motion_pct); //Accumulate Motion In/Out of frame stats this_frame_mv_in_out = next_frame.mv_in_out_count * next_frame.pcnt_motion; @@ -1300,13 +1294,23 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) abs_mv_in_out_accumulator += fabs(next_frame.mv_in_out_count * next_frame.pcnt_motion); // If there is a significant amount of motion - if (motion_factor > 0.05) + if (motion_pct > 0.05) { - this_frame_mvr_ratio = fabs(next_frame.mvr_abs) / DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVr)); - this_frame_mvc_ratio = fabs(next_frame.mvc_abs) / DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVc)); + this_frame_mvr_ratio = fabs(next_frame.mvr_abs) / + DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVr)); + + this_frame_mvc_ratio = fabs(next_frame.mvc_abs) / + DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVc)); + + mv_ratio_accumulator += + (this_frame_mvr_ratio < next_frame.mvr_abs) + ? (this_frame_mvr_ratio * motion_pct) + : next_frame.mvr_abs * motion_pct; - mv_ratio_accumulator += (this_frame_mvr_ratio < next_frame.mvr_abs) ? (this_frame_mvr_ratio * motion_factor) : next_frame.mvr_abs * motion_factor; - mv_ratio_accumulator += (this_frame_mvc_ratio < next_frame.mvc_abs) ? (this_frame_mvc_ratio * motion_factor) : next_frame.mvc_abs * motion_factor; + mv_ratio_accumulator += + (this_frame_mvc_ratio < next_frame.mvc_abs) + ? (this_frame_mvc_ratio * motion_pct) + : next_frame.mvc_abs * motion_pct; } else { @@ -1334,14 +1338,26 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) loop_decay_rate = next_frame.pcnt_inter; // High % motion -> somewhat higher decay rate - if ((1.0 - (next_frame.pcnt_motion / 10.0)) < loop_decay_rate) - loop_decay_rate = (1.0 - (next_frame.pcnt_motion / 10.0)); + motion_decay = (1.0 - (motion_pct / 20.0)); + if (motion_decay < loop_decay_rate) + loop_decay_rate = motion_decay; - distance_factor = sqrt((this_mv_rabs * this_mv_rabs) + (this_mv_cabs * this_mv_cabs)) / 300.0; - distance_factor = ((distance_factor > 1.0) ? 0.0 : (1.0 - distance_factor)); - - if (distance_factor < loop_decay_rate) - loop_decay_rate = distance_factor; + // Adjustment to decay rate based on speed of motion + { + double this_mv_rabs; + double this_mv_cabs; + double distance_factor; + + this_mv_rabs = fabs(next_frame.mvr_abs * motion_pct); + this_mv_cabs = fabs(next_frame.mvc_abs * motion_pct); + + distance_factor = sqrt((this_mv_rabs * this_mv_rabs) + + (this_mv_cabs * this_mv_cabs)) / 250.0; + distance_factor = ((distance_factor > 1.0) + ? 0.0 : (1.0 - distance_factor)); + if (distance_factor < loop_decay_rate) + loop_decay_rate = distance_factor; + } // Cumulative effect of decay decay_accumulator = decay_accumulator * loop_decay_rate; @@ -2281,6 +2297,8 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) for (i = 0 ; i < cpi->frames_to_key ; i++) { double r; + double motion_decay; + double motion_pct = next_frame.pcnt_motion; if (EOF == vp8_input_stats(cpi, &next_frame)) break; @@ -2294,10 +2312,30 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) //if ( next_frame.pcnt_inter < loop_decay_rate ) loop_decay_rate = next_frame.pcnt_inter; - if ((1.0 - (next_frame.pcnt_motion / 10.0)) < loop_decay_rate) - loop_decay_rate = (1.0 - (next_frame.pcnt_motion / 10.0)); + // High % motion -> somewhat higher decay rate + motion_decay = (1.0 - (motion_pct / 20.0)); + if (motion_decay < loop_decay_rate) + loop_decay_rate = motion_decay; + + // Adjustment to decay rate based on speed of motion + { + double this_mv_rabs; + double this_mv_cabs; + double distance_factor; + + this_mv_rabs = fabs(next_frame.mvr_abs * motion_pct); + this_mv_cabs = fabs(next_frame.mvc_abs * motion_pct); + + distance_factor = sqrt((this_mv_rabs * this_mv_rabs) + + (this_mv_cabs * this_mv_cabs)) / 250.0; + distance_factor = ((distance_factor > 1.0) + ? 0.0 : (1.0 - distance_factor)); + if (distance_factor < loop_decay_rate) + loop_decay_rate = distance_factor; + } decay_accumulator = decay_accumulator * loop_decay_rate; + decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator; boost_score += (decay_accumulator * r); diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 46c283d68..6b7333f1d 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -4247,7 +4247,7 @@ static void encode_frame_to_data_rate if (cpi->avg_frame_qindex < cpi->active_worst_quality) Q = cpi->avg_frame_qindex; - if ( cpi->gfu_boost > 1000 ) + if ( cpi->gfu_boost > 1000 ) cpi->active_best_quality = gf_low_motion_minq[Q]; else if ( cpi->gfu_boost < 400 ) cpi->active_best_quality = gf_high_motion_minq[Q]; @@ -4265,7 +4265,7 @@ static void encode_frame_to_data_rate // KEY FRAMES else { - if (cpi->gfu_boost > 1000) + if (cpi->gfu_boost > 600) cpi->active_best_quality = kf_low_motion_minq[Q]; else cpi->active_best_quality = kf_high_motion_minq[Q]; -- cgit v1.2.3