summaryrefslogtreecommitdiff
path: root/vp8/encoder/firstpass.c
diff options
context:
space:
mode:
Diffstat (limited to 'vp8/encoder/firstpass.c')
-rw-r--r--vp8/encoder/firstpass.c224
1 files changed, 163 insertions, 61 deletions
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index c59613838..3e67bf53c 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -1316,6 +1316,43 @@ 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 prediction_decay_rate;
+ double motion_decay;
+ double motion_pct = next_frame->pcnt_motion;
+
+
+ // Initial basis is the % mbs inter coded
+ prediction_decay_rate = next_frame->pcnt_inter;
+
+ // High % motion -> somewhat higher decay rate
+ motion_decay = (1.0 - (motion_pct / 20.0));
+ if (motion_decay < prediction_decay_rate)
+ prediction_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 < prediction_decay_rate)
+ prediction_decay_rate = distance_factor;
+ }
+
+ return prediction_decay_rate;
+}
+
// Analyse and define a gf/arf group .
static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
{
@@ -1337,17 +1374,20 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
double decay_accumulator = 1.0;
double boost_factor = IIFACTOR;
- double loop_decay_rate = 1.00; // Starting decay rate
+ double loop_decay_rate = 1.00; // Starting decay rate
double this_frame_mv_in_out = 0.0;
double mv_in_out_accumulator = 0.0;
double abs_mv_in_out_accumulator = 0.0;
double mod_err_per_mb_accumulator = 0.0;
- int max_bits = frame_max_bits(cpi); // Max for a single frame
+ int max_bits = frame_max_bits(cpi); // Max for a single frame
unsigned char *fpmm_pos;
+ unsigned int allow_alt_ref =
+ cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
+
cpi->gf_group_bits = 0;
cpi->gf_decay_rate = 0;
@@ -1362,47 +1402,57 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// Preload the stats for the next frame.
mod_frame_err = calculate_modified_err(cpi, this_frame);
- // Note the error of the frame at the start of the group (this will be the GF frame error if we code a normal gf
+ // Note the error of the frame at the start of the group (this will be
+ // the GF frame error if we code a normal gf
gf_first_frame_err = mod_frame_err;
- // Special treatment if the current frame is a key frame (which is also a gf).
- // If it is then its error score (and hence bit allocation) need to be subtracted out
- // from the calculation for the GF group
+ // Special treatment if the current frame is a key frame (which is also
+ // a gf). If it is then its error score (and hence bit allocation) need
+ // to be subtracted out from the calculation for the GF group
if (cpi->common.frame_type == KEY_FRAME)
gf_group_err -= gf_first_frame_err;
- // Scan forward to try and work out how many frames the next gf group should contain and
- // what level of boost is appropriate for the GF or ARF that will be coded with the group
+ // Scan forward to try and work out how many frames the next gf group
+ // should contain and what level of boost is appropriate for the GF
+ // or ARF that will be coded with the group
i = 0;
- while (((i < cpi->max_gf_interval) || ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) && (i < cpi->frames_to_key))
+ while (((i < cpi->static_scene_max_gf_interval) ||
+ ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) &&
+ (i < cpi->frames_to_key))
{
double r;
double this_frame_mvr_ratio;
double this_frame_mvc_ratio;
double motion_decay;
- double motion_pct = next_frame.pcnt_motion;
+ //double motion_pct = next_frame.pcnt_motion;
+ double motion_pct;
- i++; // Increment the loop counter
+ i++; // Increment the loop counter
// Accumulate error score of frames in this gf group
mod_frame_err = calculate_modified_err(cpi, this_frame);
gf_group_err += mod_frame_err;
- mod_err_per_mb_accumulator += mod_frame_err / DOUBLE_DIVIDE_CHECK((double)cpi->common.MBs);
+ mod_err_per_mb_accumulator +=
+ mod_frame_err / DOUBLE_DIVIDE_CHECK((double)cpi->common.MBs);
if (EOF == vp8_input_stats(cpi, &next_frame))
break;
// Accumulate motion stats.
+ motion_pct = next_frame.pcnt_motion;
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;
- mv_in_out_accumulator += next_frame.mv_in_out_count * next_frame.pcnt_motion;
- abs_mv_in_out_accumulator += fabs(next_frame.mv_in_out_count * next_frame.pcnt_motion);
+ this_frame_mv_in_out =
+ next_frame.mv_in_out_count * motion_pct;
+ mv_in_out_accumulator +=
+ next_frame.mv_in_out_count * motion_pct;
+ abs_mv_in_out_accumulator +=
+ fabs(next_frame.mv_in_out_count * motion_pct);
// If there is a significant amount of motion
if (motion_pct > 0.05)
@@ -1431,7 +1481,9 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
}
// Underlying boost factor is based on inter intra error ratio
- r = (boost_factor * (next_frame.intra_error / DOUBLE_DIVIDE_CHECK(next_frame.coded_error)));
+ r = ( boost_factor *
+ ( next_frame.intra_error /
+ DOUBLE_DIVIDE_CHECK(next_frame.coded_error)));
if (next_frame.intra_error > cpi->gf_intra_err_min)
r = (IIKFACTOR2 * next_frame.intra_error /
@@ -1440,63 +1492,87 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
r = (IIKFACTOR2 * cpi->gf_intra_err_min /
DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
- // Increase boost for frames where new data coming into frame (eg zoom out)
- // Slightly reduce boost if there is a net balance of motion out of the frame (zoom in)
+ // Increase boost for frames where new data coming into frame
+ // (eg zoom out). Slightly reduce boost if there is a net balance
+ // of motion out of the frame (zoom in).
// The range for this_frame_mv_in_out is -1.0 to +1.0
if (this_frame_mv_in_out > 0.0)
r += r * (this_frame_mv_in_out * 2.0);
+ // In extreme case boost is halved
else
- r += r * (this_frame_mv_in_out / 2.0); // In extreme case boost is halved
+ r += r * (this_frame_mv_in_out / 2.0);
if (r > GF_RMAX)
r = GF_RMAX;
- // Adjust loop decay rate
- //if ( next_frame.pcnt_inter < loop_decay_rate )
- loop_decay_rate = next_frame.pcnt_inter;
+ loop_decay_rate = gf_prediction_decay_rate(cpi, &next_frame);
- // 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;
+ // Cumulative effect of decay
+ decay_accumulator = decay_accumulator * loop_decay_rate;
+ decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
- // Adjustment to decay rate based on speed of motion
+ 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) )
{
- double this_mv_rabs;
- double this_mv_cabs;
- double distance_factor;
+ 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;
- this_mv_rabs = fabs(next_frame.mvr_abs * motion_pct);
- this_mv_cabs = fabs(next_frame.mvc_abs * motion_pct);
+ decay_rate = gf_prediction_decay_rate(cpi, &tmp_next_frame);
+ if ( decay_rate < 0.999 )
+ break;
+ }
+ reset_fpf_position(cpi, position); // Reset file position
- 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;
- }
+ // 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);
+ }
- // Cumulative effect of decay
- decay_accumulator = decay_accumulator * loop_decay_rate;
- decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
- //decay_accumulator = ( loop_decay_rate < decay_accumulator ) ? loop_decay_rate : decay_accumulator;
+ allow_alt_ref = FALSE;
- boost_score += (decay_accumulator * r);
+ boost_score = old_boost_score;
+ break;
+ }
+ }
// Break out conditions.
- if ( /* i>4 || */
+ if ( /* i>4 || */
+ // Break at cpi->max_gf_interval unless almost totally static
+ (i >= cpi->max_gf_interval && (decay_accumulator < 0.995)) ||
(
- (i > MIN_GF_INTERVAL) && // Dont break out with a very short interval
- ((cpi->frames_to_key - i) >= MIN_GF_INTERVAL) && // Dont break out very close to a key frame
+ // Dont break out with a very short interval
+ (i > MIN_GF_INTERVAL) &&
+ // Dont break out very close to a key frame
+ ((cpi->frames_to_key - i) >= MIN_GF_INTERVAL) &&
((boost_score > 20.0) || (next_frame.pcnt_inter < 0.75)) &&
((mv_ratio_accumulator > 100.0) ||
(abs_mv_in_out_accumulator > 3.0) ||
(mv_in_out_accumulator < -2.0) ||
- ((boost_score - old_boost_score) < 2.0)
- )
- )
- )
+ ((boost_score - old_boost_score) < 2.0))
+ ) )
{
boost_score = old_boost_score;
break;
@@ -1507,7 +1583,8 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
old_boost_score = boost_score;
}
- cpi->gf_decay_rate = (i > 0) ? (int)(100.0 * (1.0 - decay_accumulator)) / i : 0;
+ cpi->gf_decay_rate =
+ (i > 0) ? (int)(100.0 * (1.0 - decay_accumulator)) / i : 0;
// When using CBR apply additional buffer related upper limits
if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
@@ -1517,7 +1594,8 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// For cbr apply buffer related limits
if (cpi->drop_frames_allowed)
{
- int df_buffer_level = cpi->oxcf.drop_frames_water_mark * (cpi->oxcf.optimal_buffer_level / 100);
+ int df_buffer_level = cpi->oxcf.drop_frames_water_mark *
+ (cpi->oxcf.optimal_buffer_level / 100);
if (cpi->buffer_level > df_buffer_level)
max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
@@ -1540,10 +1618,10 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
cpi->gfu_boost = (int)(boost_score * 100.0) >> 4;
// Should we use the alternate refernce frame
- if (cpi->oxcf.play_alternate &&
- cpi->oxcf.lag_in_frames &&
+ if (allow_alt_ref &&
(i >= MIN_GF_INTERVAL) &&
- (i <= (cpi->frames_to_key - MIN_GF_INTERVAL)) && // dont use ARF very near next kf
+ // dont use ARF very near next kf
+ (i <= (cpi->frames_to_key - MIN_GF_INTERVAL)) &&
(((next_frame.pcnt_inter > 0.75) &&
((mv_in_out_accumulator / (double)i > -0.2) || (mv_in_out_accumulator > -2.0)) &&
//(cpi->gfu_boost>150) &&
@@ -2345,12 +2423,35 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
if (cpi->oxcf.auto_key
&& cpi->frames_to_key > (int)cpi->key_frame_frequency )
{
+ int current_pos = cpi->stats_in;
+ FIRSTPASS_STATS tmp_frame;
+
cpi->frames_to_key /= 2;
- // Estimate corrected kf group error
- kf_group_err /= 2.0;
- kf_group_intra_err /= 2.0;
- kf_group_coded_err /= 2.0;
+ // Copy first frame details
+ vpx_memcpy(&tmp_frame, &first_frame, sizeof(first_frame));
+
+ // Reset to the start of the group
+ reset_fpf_position(cpi, start_position);
+
+ kf_group_err = 0;
+ kf_group_intra_err = 0;
+ kf_group_coded_err = 0;
+
+ // Rescan to get the correct error data for the forced kf group
+ for( i = 0; i < cpi->frames_to_key; i++ )
+ {
+ // Accumulate kf group errors
+ kf_group_err += calculate_modified_err(cpi, &tmp_frame);
+ kf_group_intra_err += tmp_frame.intra_error;
+ kf_group_coded_err += tmp_frame.coded_error;
+
+ // Load a the next frame's stats
+ vp8_input_stats(cpi, &tmp_frame);
+ }
+
+ // Reset to the start of the group
+ reset_fpf_position(cpi, current_pos);
cpi->next_key_frame_forced = TRUE;
}
@@ -2449,7 +2550,7 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
{
double r;
double motion_decay;
- double motion_pct = next_frame.pcnt_motion;
+ double motion_pct;
if (EOF == vp8_input_stats(cpi, &next_frame))
break;
@@ -2469,6 +2570,7 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
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;