Commit c239a1b6 authored by Paul Wilkins's avatar Paul Wilkins Committed by John Koleszar

Improved Force Key Frame Behaviour

These changes improve the behaviour of the code with
forced key frames sent in by a calling application.

The sizing of the frames is still suboptimal for two pass in
particular but the behaviour is much better than it was.

Change-Id: I35fae610c67688ccc69d11f385e87dfc884e65a1
parent 0b94f5d6
......@@ -2095,33 +2095,34 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
kf_group_intra_err += this_frame->intra_error;
kf_group_coded_err += this_frame->coded_error;
// load a the next frame's stats
vpx_memcpy(&last_frame, this_frame, sizeof(*this_frame));
vp8_input_stats(cpi, this_frame);
// Provided that we are not at the end of the file...
if (EOF != vp8_input_stats(cpi, this_frame))
if (cpi->oxcf.auto_key
&& lookup_next_frame_stats(cpi, &next_frame) != EOF)
{
if (lookup_next_frame_stats(cpi, &next_frame) != EOF)
{
if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
break;
}
}
// Step on to the next frame
cpi->frames_to_key ++;
if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
break;
// If we don't have a real key frame within the next two
// forcekeyframeevery intervals then break out of the loop.
if (cpi->frames_to_key >= 2 *(int)cpi->key_frame_frequency)
break;
// Step on to the next frame
cpi->frames_to_key ++;
// If we don't have a real key frame within the next two
// forcekeyframeevery intervals then break out of the loop.
if (cpi->frames_to_key >= 2 *(int)cpi->key_frame_frequency)
break;
} else
cpi->frames_to_key ++;
}
// If there is a max kf interval set by the user we must obey it.
// We already breakout of the loop above at 2x max.
// This code centers the extra kf if the actual natural
// interval is between 1x and 2x
if ( cpi->frames_to_key > (int)cpi->key_frame_frequency )
if (cpi->oxcf.auto_key
&& cpi->frames_to_key > (int)cpi->key_frame_frequency )
{
cpi->frames_to_key /= 2;
......@@ -2388,23 +2389,34 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
cpi->kf_bits = (3 * cpi->buffer_level) >> 2;
}
// If the key frame is actually easier than the average for the kf group (which does sometimes happen... eg a blank intro frame)
// Then use an alternate calculation based on the kf error score which should give a smaller key frame.
// If the key frame is actually easier than the average for the
// kf group (which does sometimes happen... eg a blank intro frame)
// Then use an alternate calculation based on the kf error score
// which should give a smaller key frame.
if (kf_mod_err < kf_group_err / cpi->frames_to_key)
{
double alt_kf_grp_bits = ((double)cpi->bits_left * (kf_mod_err * (double)cpi->frames_to_key) / cpi->modified_total_error_left) ;
double alt_kf_grp_bits =
((double)cpi->bits_left *
(kf_mod_err * (double)cpi->frames_to_key) /
DOUBLE_DIVIDE_CHECK(cpi->modified_total_error_left));
alt_kf_bits = (int)((double)kf_boost * (alt_kf_grp_bits / (double)allocation_chunks));
alt_kf_bits = (int)((double)kf_boost *
(alt_kf_grp_bits / (double)allocation_chunks));
if (cpi->kf_bits > alt_kf_bits)
{
cpi->kf_bits = alt_kf_bits;
}
}
// Else if it is much harder than other frames in the group make sure it at least receives an allocation in keeping with its relative error score
// Else if it is much harder than other frames in the group make sure
// it at least receives an allocation in keeping with its relative
// error score
else
{
alt_kf_bits = (int)((double)cpi->bits_left * (kf_mod_err / cpi->modified_total_error_left));
alt_kf_bits =
(int)((double)cpi->bits_left *
(kf_mod_err /
DOUBLE_DIVIDE_CHECK(cpi->modified_total_error_left)));
if (alt_kf_bits > cpi->kf_bits)
{
......
......@@ -2818,23 +2818,17 @@ static int pick_frame_size(VP8_COMP *cpi)
cm->frame_type = KEY_FRAME;
}
// Auto key frames (Only two pass will enter here)
else if (cm->frame_type == KEY_FRAME)
{
vp8_calc_auto_iframe_target_size(cpi);
}
// Forced key frames (by interval or an external signal)
else if ((cm->frame_flags & FRAMEFLAGS_KEY) ||
(cpi->oxcf.auto_key && (cpi->frames_since_key % cpi->key_frame_frequency == 0)))
// Special case for forced key frames
// The frame sizing here is still far from ideal for 2 pass.
else if (cm->frame_flags & FRAMEFLAGS_KEY)
{
// Key frame from VFW/auto-keyframe/first frame
cm->frame_type = KEY_FRAME;
resize_key_frame(cpi);
// Compute target frame size
if (cpi->pass != 2)
vp8_calc_iframe_target_size(cpi);
vp8_calc_iframe_target_size(cpi);
}
else if (cm->frame_type == KEY_FRAME)
{
vp8_calc_auto_iframe_target_size(cpi);
}
else
{
......
......@@ -1444,6 +1444,9 @@ void vp8_adjust_key_frame_context(VP8_COMP *cpi)
}
else
{
int last_kf_interval =
(cpi->frames_since_key > 0) ? cpi->frames_since_key : 1;
// reset keyframe context and calculate weighted average of last KEY_FRAME_CONTEXT keyframes
for (i = 0; i < KEY_FRAME_CONTEXT; i++)
{
......@@ -1454,8 +1457,8 @@ void vp8_adjust_key_frame_context(VP8_COMP *cpi)
}
else
{
cpi->prior_key_frame_size[KEY_FRAME_CONTEXT - 1] = cpi->projected_frame_size;
cpi->prior_key_frame_distance[KEY_FRAME_CONTEXT - 1] = cpi->frames_since_key;
cpi->prior_key_frame_size[i] = cpi->projected_frame_size;
cpi->prior_key_frame_distance[i] = last_kf_interval;
}
av_key_frame_bits += prior_key_frame_weight[i] * cpi->prior_key_frame_size[i];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment