summaryrefslogtreecommitdiff
path: root/vp8/encoder
diff options
context:
space:
mode:
authorPaul Wilkins <paulwilkins@google.com>2011-03-07 15:11:09 +0000
committerPaul Wilkins <paulwilkins@google.com>2011-03-07 15:11:09 +0000
commit9fc8cb39aaa19ecf4434b7d02a7bd33f496f81e3 (patch)
tree2494804797d20e78bff22a98d808dc36232dd4f8 /vp8/encoder
parent3fae3283e6037a0b20f5e32402ba8e50d7ef859e (diff)
downloadlibvpx-9fc8cb39aaa19ecf4434b7d02a7bd33f496f81e3.tar
libvpx-9fc8cb39aaa19ecf4434b7d02a7bd33f496f81e3.tar.gz
libvpx-9fc8cb39aaa19ecf4434b7d02a7bd33f496f81e3.tar.bz2
libvpx-9fc8cb39aaa19ecf4434b7d02a7bd33f496f81e3.zip
Improved KF insertion after fades to still.
This code extends what was previously done for GFs, to pick cases where insertion of a key frame after a fade (or other transition or complex motion) followed by a still section, will be beneficial and will reduce the number of forced key frames. Change-Id: If8bca00457f0d5f83dc3318a587f61c17d90f135
Diffstat (limited to 'vp8/encoder')
-rw-r--r--vp8/encoder/firstpass.c157
1 files changed, 86 insertions, 71 deletions
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index e0b2a8a45..60b352859 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -1341,7 +1341,7 @@ void vp8_end_second_pass(VP8_COMP *cpi)
// This function gives and estimate of how badly we believe
// the predicition quality is decaying from frame to frame.
-double gf_prediction_decay_rate(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
+double get_prediction_decay_rate(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
{
double prediction_decay_rate;
double motion_decay;
@@ -1375,6 +1375,51 @@ double gf_prediction_decay_rate(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
return prediction_decay_rate;
}
+// Funtion to test for a condition where a complex transition is followe
+// by a static section. For example in slide shows where there is a fade
+// between slides. This is to help with more optimal kf and gf positioning.
+BOOL detect_transition_to_still(
+ VP8_COMP *cpi,
+ int frame_interval,
+ int still_interval,
+ double loop_decay_rate,
+ double decay_accumulator )
+{
+ BOOL trans_to_still = FALSE;
+
+ // Break clause to detect very still sections after motion
+ // For example a staic image after a fade or other transition
+ // instead of a clean scene cut.
+ if ( (frame_interval > MIN_GF_INTERVAL) &&
+ (loop_decay_rate >= 0.999) &&
+ (decay_accumulator < 0.9) )
+ {
+ int j;
+ FIRSTPASS_STATS * position = cpi->stats_in;
+ FIRSTPASS_STATS tmp_next_frame;
+ double decay_rate;
+
+ // Look ahead a few frames to see if static condition
+ // persists...
+ for ( j = 0; j < still_interval; j++ )
+ {
+ if (EOF == vp8_input_stats(cpi, &tmp_next_frame))
+ break;
+
+ decay_rate = get_prediction_decay_rate(cpi, &tmp_next_frame);
+ if ( decay_rate < 0.999 )
+ break;
+ }
+ // Reset file position
+ reset_fpf_position(cpi, position);
+
+ // Only if it does do we signal a transition to still
+ if ( j == still_interval )
+ trans_to_still = TRUE;
+ }
+
+ return trans_to_still;
+}
// Analyse and define a gf/arf group .
static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
@@ -1528,7 +1573,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
if (r > GF_RMAX)
r = GF_RMAX;
- loop_decay_rate = gf_prediction_decay_rate(cpi, &next_frame);
+ loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
// Cumulative effect of decay
decay_accumulator = decay_accumulator * loop_decay_rate;
@@ -1537,48 +1582,13 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
boost_score += (decay_accumulator * r);
// Break clause to detect very still sections after motion
- // For example a staic image after a fade or other transition
- // instead of a clean key frame.
- if ( (i > MIN_GF_INTERVAL) &&
- (loop_decay_rate >= 0.999) &&
- (decay_accumulator < 0.9) )
+ // For example a staic image after a fade or other transition.
+ if ( detect_transition_to_still( cpi, i, 5,
+ loop_decay_rate, decay_accumulator ) )
{
- int j;
- FIRSTPASS_STATS * position = cpi->stats_in;
- FIRSTPASS_STATS tmp_next_frame;
- double decay_rate;
-
- // Look ahead a few frames to see if static condition
- // persists...
- for ( j = 0; j < 4; j++ )
- {
- if (EOF == vp8_input_stats(cpi, &tmp_next_frame))
- break;
-
- decay_rate = gf_prediction_decay_rate(cpi, &tmp_next_frame);
- if ( decay_rate < 0.999 )
- break;
- }
- reset_fpf_position(cpi, position); // Reset file position
-
- // Force GF not alt ref
- if ( j == 4 )
- {
- if (0)
- {
- FILE *f = fopen("fadegf.stt", "a");
- fprintf(f, " %8d %8d %10.4f %10.4f %10.4f\n",
- cpi->common.current_video_frame+i, i,
- loop_decay_rate, decay_accumulator,
- boost_score );
- fclose(f);
- }
-
- allow_alt_ref = FALSE;
-
- boost_score = old_boost_score;
- break;
- }
+ allow_alt_ref = FALSE;
+ boost_score = old_boost_score;
+ break;
}
// Break out conditions.
@@ -2363,13 +2373,13 @@ static BOOL test_candidate_kf(VP8_COMP *cpi, FIRSTPASS_STATS *last_frame, FIRST
}
void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
{
- int i;
+ int i,j;
FIRSTPASS_STATS last_frame;
FIRSTPASS_STATS first_frame;
FIRSTPASS_STATS next_frame;
FIRSTPASS_STATS *start_position;
- double decay_accumulator = 0;
+ double decay_accumulator = 1.0;
double boost_score = 0;
double old_boost_score = 0.0;
double loop_decay_rate;
@@ -2379,6 +2389,7 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
double kf_group_intra_err = 0.0;
double kf_group_coded_err = 0.0;
double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+ double recent_loop_decay[8] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
@@ -2407,6 +2418,7 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
kf_mod_err = calculate_modified_err(cpi, this_frame);
// find the next keyframe
+ i = 0;
while (cpi->stats_in < cpi->stats_in_end)
{
// Accumulate kf group error
@@ -2425,9 +2437,34 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
if (cpi->oxcf.auto_key
&& lookup_next_frame_stats(cpi, &next_frame) != EOF)
{
+ // Normal scene cut check
if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
break;
+ // How fast is prediction quality decaying
+ loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+
+ // We want to know something about the recent past... rather than
+ // as used elsewhere where we are concened with decay in prediction
+ // quality since the last GF or KF.
+ recent_loop_decay[i%8] = loop_decay_rate;
+ decay_accumulator = 1.0;
+ for (j = 0; j < 8; j++)
+ {
+ decay_accumulator = decay_accumulator * recent_loop_decay[j];
+ }
+
+ // Special check for transition or high motion followed by a
+ // to a static scene.
+ if ( detect_transition_to_still( cpi, i,
+ (cpi->key_frame_frequency-i),
+ loop_decay_rate,
+ decay_accumulator ) )
+ {
+ break;
+ }
+
+
// Step on to the next frame
cpi->frames_to_key ++;
@@ -2437,6 +2474,8 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
break;
} else
cpi->frames_to_key ++;
+
+ i++;
}
// If there is a max kf interval set by the user we must obey it.
@@ -2588,32 +2627,8 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
if (r > RMAX)
r = RMAX;
- // Adjust loop decay rate
- //if ( next_frame.pcnt_inter < loop_decay_rate )
- loop_decay_rate = next_frame.pcnt_inter;
-
- // High % motion -> somewhat higher decay rate
- motion_pct = next_frame.pcnt_motion;
- 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;
- }
+ // How fast is prediction quality decaying
+ loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
decay_accumulator = decay_accumulator * loop_decay_rate;
decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator;