Index: source/libvpx/vp9/encoder/vp9_firstpass.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_firstpass.c (revision 278778) |
+++ source/libvpx/vp9/encoder/vp9_firstpass.c (working copy) |
@@ -46,6 +46,9 @@ |
#define GF_RMAX 96.0 |
#define ERR_DIVISOR 150.0 |
#define MIN_DECAY_FACTOR 0.1 |
+#define SVC_FACTOR_PT_LOW 0.45 |
+#define FACTOR_PT_LOW 0.5 |
+#define FACTOR_PT_HIGH 0.9 |
#define KF_MB_INTRA_MIN 150 |
#define GF_MB_INTRA_MIN 100 |
@@ -61,9 +64,8 @@ |
#define MIN_GF_INTERVAL 4 |
#endif |
+#define LONG_TERM_VBR_CORRECTION |
-// #define LONG_TERM_VBR_CORRECTION |
- |
static void swap_yv12(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) { |
YV12_BUFFER_CONFIG temp = *a; |
*a = *b; |
@@ -79,12 +81,12 @@ |
// Resets the first pass file to the given position using a relative seek from |
// the current position. |
-static void reset_fpf_position(struct twopass_rc *p, |
+static void reset_fpf_position(TWO_PASS *p, |
const FIRSTPASS_STATS *position) { |
p->stats_in = position; |
} |
-static int lookup_next_frame_stats(const struct twopass_rc *p, |
+static int lookup_next_frame_stats(const TWO_PASS *p, |
FIRSTPASS_STATS *next_frame) { |
if (p->stats_in >= p->stats_in_end) |
return EOF; |
@@ -95,7 +97,7 @@ |
// Read frame stats at an offset from the current position. |
-static int read_frame_stats(const struct twopass_rc *p, |
+static int read_frame_stats(const TWO_PASS *p, |
FIRSTPASS_STATS *frame_stats, int offset) { |
const FIRSTPASS_STATS *fps_ptr = p->stats_in; |
@@ -112,7 +114,7 @@ |
return 1; |
} |
-static int input_stats(struct twopass_rc *p, FIRSTPASS_STATS *fps) { |
+static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) { |
if (p->stats_in >= p->stats_in_end) |
return EOF; |
@@ -135,14 +137,13 @@ |
FILE *fpfile; |
fpfile = fopen("firstpass.stt", "a"); |
- fprintf(fpfile, "%12.0f %12.0f %12.0f %12.0f %12.0f %12.4f %12.4f" |
+ fprintf(fpfile, "%12.0f %12.0f %12.0f %12.0f %12.4f %12.4f" |
"%12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f" |
"%12.0f %12.0f %12.4f %12.0f %12.0f %12.4f\n", |
stats->frame, |
stats->intra_error, |
stats->coded_error, |
stats->sr_coded_error, |
- stats->ssim_weighted_pred_err, |
stats->pcnt_inter, |
stats->pcnt_motion, |
stats->pcnt_second_ref, |
@@ -167,7 +168,6 @@ |
section->intra_error = 0.0; |
section->coded_error = 0.0; |
section->sr_coded_error = 0.0; |
- section->ssim_weighted_pred_err = 0.0; |
section->pcnt_inter = 0.0; |
section->pcnt_motion = 0.0; |
section->pcnt_second_ref = 0.0; |
@@ -192,7 +192,6 @@ |
section->intra_error += frame->intra_error; |
section->coded_error += frame->coded_error; |
section->sr_coded_error += frame->sr_coded_error; |
- section->ssim_weighted_pred_err += frame->ssim_weighted_pred_err; |
section->pcnt_inter += frame->pcnt_inter; |
section->pcnt_motion += frame->pcnt_motion; |
section->pcnt_second_ref += frame->pcnt_second_ref; |
@@ -215,7 +214,6 @@ |
section->intra_error -= frame->intra_error; |
section->coded_error -= frame->coded_error; |
section->sr_coded_error -= frame->sr_coded_error; |
- section->ssim_weighted_pred_err -= frame->ssim_weighted_pred_err; |
section->pcnt_inter -= frame->pcnt_inter; |
section->pcnt_motion -= frame->pcnt_motion; |
section->pcnt_second_ref -= frame->pcnt_second_ref; |
@@ -239,7 +237,6 @@ |
section->intra_error /= section->count; |
section->coded_error /= section->count; |
section->sr_coded_error /= section->count; |
- section->ssim_weighted_pred_err /= section->count; |
section->pcnt_inter /= section->count; |
section->pcnt_second_ref /= section->count; |
section->pcnt_neutral /= section->count; |
@@ -256,86 +253,18 @@ |
// Calculate a modified Error used in distributing bits between easier and |
// harder frames. |
-static double calculate_modified_err(const VP9_COMP *cpi, |
+static double calculate_modified_err(const TWO_PASS *twopass, |
+ const VP9EncoderConfig *oxcf, |
const FIRSTPASS_STATS *this_frame) { |
- const struct twopass_rc *twopass = &cpi->twopass; |
- const SVC *const svc = &cpi->svc; |
- const FIRSTPASS_STATS *stats; |
- double av_err; |
- double modified_error; |
- |
- if (svc->number_spatial_layers > 1 && |
- svc->number_temporal_layers == 1) { |
- twopass = &svc->layer_context[svc->spatial_layer_id].twopass; |
- } |
- |
- stats = &twopass->total_stats; |
- av_err = stats->ssim_weighted_pred_err / stats->count; |
- modified_error = av_err * pow(this_frame->ssim_weighted_pred_err / |
- DOUBLE_DIVIDE_CHECK(av_err), |
- cpi->oxcf.two_pass_vbrbias / 100.0); |
- |
+ const FIRSTPASS_STATS *const stats = &twopass->total_stats; |
+ const double av_err = stats->coded_error / stats->count; |
+ const double modified_error = av_err * |
+ pow(this_frame->coded_error / DOUBLE_DIVIDE_CHECK(av_err), |
+ oxcf->two_pass_vbrbias / 100.0); |
return fclamp(modified_error, |
twopass->modified_error_min, twopass->modified_error_max); |
} |
-static const double weight_table[256] = { |
- 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, |
- 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, |
- 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, |
- 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, |
- 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.031250, 0.062500, |
- 0.093750, 0.125000, 0.156250, 0.187500, 0.218750, 0.250000, 0.281250, |
- 0.312500, 0.343750, 0.375000, 0.406250, 0.437500, 0.468750, 0.500000, |
- 0.531250, 0.562500, 0.593750, 0.625000, 0.656250, 0.687500, 0.718750, |
- 0.750000, 0.781250, 0.812500, 0.843750, 0.875000, 0.906250, 0.937500, |
- 0.968750, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, |
- 1.000000, 1.000000, 1.000000, 1.000000 |
-}; |
- |
-static double simple_weight(const YV12_BUFFER_CONFIG *buf) { |
- int i, j; |
- double sum = 0.0; |
- const int w = buf->y_crop_width; |
- const int h = buf->y_crop_height; |
- const uint8_t *row = buf->y_buffer; |
- |
- for (i = 0; i < h; ++i) { |
- const uint8_t *pixel = row; |
- for (j = 0; j < w; ++j) |
- sum += weight_table[*pixel++]; |
- row += buf->y_stride; |
- } |
- |
- return MAX(0.1, sum / (w * h)); |
-} |
- |
// This function returns the maximum target rate per frame. |
static int frame_max_bits(const RATE_CONTROL *rc, |
const VP9EncoderConfig *oxcf) { |
@@ -468,6 +397,32 @@ |
} |
} |
+static int find_fp_qindex() { |
+ int i; |
+ |
+ for (i = 0; i < QINDEX_RANGE; ++i) |
+ if (vp9_convert_qindex_to_q(i) >= 30.0) |
+ break; |
+ |
+ if (i == QINDEX_RANGE) |
+ i--; |
+ |
+ return i; |
+} |
+ |
+static void set_first_pass_params(VP9_COMP *cpi) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ if (!cpi->refresh_alt_ref_frame && |
+ (cm->current_video_frame == 0 || |
+ (cpi->frame_flags & FRAMEFLAGS_KEY))) { |
+ cm->frame_type = KEY_FRAME; |
+ } else { |
+ cm->frame_type = INTER_FRAME; |
+ } |
+ // Do not use periodic key frames. |
+ cpi->rc.frames_to_key = INT_MAX; |
+} |
+ |
void vp9_first_pass(VP9_COMP *cpi) { |
int mb_row, mb_col; |
MACROBLOCK *const x = &cpi->mb; |
@@ -476,7 +431,7 @@ |
TileInfo tile; |
struct macroblock_plane *const p = x->plane; |
struct macroblockd_plane *const pd = xd->plane; |
- const PICK_MODE_CONTEXT *ctx = &x->pc_root->none; |
+ const PICK_MODE_CONTEXT *ctx = &cpi->pc_root->none; |
int i; |
int recon_yoffset, recon_uvoffset; |
@@ -501,12 +456,15 @@ |
int new_mv_count = 0; |
int sum_in_vectors = 0; |
uint32_t lastmv_as_int = 0; |
- struct twopass_rc *twopass = &cpi->twopass; |
+ TWO_PASS *twopass = &cpi->twopass; |
const MV zero_mv = {0, 0}; |
const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12; |
vp9_clear_system_state(); |
+ set_first_pass_params(cpi); |
+ vp9_set_quantizer(cm, find_fp_qindex()); |
+ |
if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) { |
MV_REFERENCE_FRAME ref_frame = LAST_FRAME; |
const YV12_BUFFER_CONFIG *scaled_ref_buf = NULL; |
@@ -636,8 +594,9 @@ |
// Other than for the first frame do a motion search. |
if (cm->current_video_frame > 0) { |
- int tmp_err, motion_error; |
+ int tmp_err, motion_error, raw_motion_error; |
int_mv mv, tmp_mv; |
+ struct buf_2d unscaled_last_source_buf_2d; |
xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset; |
motion_error = get_prediction_error(bsize, &x->plane[0].src, |
@@ -645,67 +604,82 @@ |
// Assume 0,0 motion with no mv overhead. |
mv.as_int = tmp_mv.as_int = 0; |
- // Test last reference frame using the previous best mv as the |
- // starting point (best reference) for the search. |
- first_pass_motion_search(cpi, x, &best_ref_mv.as_mv, &mv.as_mv, |
- &motion_error); |
- if (cpi->oxcf.aq_mode == VARIANCE_AQ) { |
- vp9_clear_system_state(); |
- motion_error = (int)(motion_error * error_weight); |
- } |
+ // Compute the motion error of the 0,0 motion using the last source |
+ // frame as the reference. Skip the further motion search on |
+ // reconstructed frame if this error is small. |
+ unscaled_last_source_buf_2d.buf = |
+ cpi->unscaled_last_source->y_buffer + recon_yoffset; |
+ unscaled_last_source_buf_2d.stride = |
+ cpi->unscaled_last_source->y_stride; |
+ raw_motion_error = get_prediction_error(bsize, &x->plane[0].src, |
+ &unscaled_last_source_buf_2d); |
- // If the current best reference mv is not centered on 0,0 then do a 0,0 |
- // based search as well. |
- if (best_ref_mv.as_int) { |
- tmp_err = INT_MAX; |
- first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv, |
- &tmp_err); |
+ // TODO(pengchong): Replace the hard-coded threshold |
+ if (raw_motion_error > 25) { |
+ // Test last reference frame using the previous best mv as the |
+ // starting point (best reference) for the search. |
+ first_pass_motion_search(cpi, x, &best_ref_mv.as_mv, &mv.as_mv, |
+ &motion_error); |
if (cpi->oxcf.aq_mode == VARIANCE_AQ) { |
vp9_clear_system_state(); |
- tmp_err = (int)(tmp_err * error_weight); |
+ motion_error = (int)(motion_error * error_weight); |
} |
- if (tmp_err < motion_error) { |
- motion_error = tmp_err; |
- mv.as_int = tmp_mv.as_int; |
+ // If the current best reference mv is not centered on 0,0 then do a |
+ // 0,0 based search as well. |
+ if (best_ref_mv.as_int) { |
+ tmp_err = INT_MAX; |
+ first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv, &tmp_err); |
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) { |
+ vp9_clear_system_state(); |
+ tmp_err = (int)(tmp_err * error_weight); |
+ } |
+ |
+ if (tmp_err < motion_error) { |
+ motion_error = tmp_err; |
+ mv.as_int = tmp_mv.as_int; |
+ } |
} |
- } |
- // Search in an older reference frame. |
- if (cm->current_video_frame > 1 && gld_yv12 != NULL) { |
- // Assume 0,0 motion with no mv overhead. |
- int gf_motion_error; |
+ // Search in an older reference frame. |
+ if (cm->current_video_frame > 1 && gld_yv12 != NULL) { |
+ // Assume 0,0 motion with no mv overhead. |
+ int gf_motion_error; |
- xd->plane[0].pre[0].buf = gld_yv12->y_buffer + recon_yoffset; |
- gf_motion_error = get_prediction_error(bsize, &x->plane[0].src, |
- &xd->plane[0].pre[0]); |
+ xd->plane[0].pre[0].buf = gld_yv12->y_buffer + recon_yoffset; |
+ gf_motion_error = get_prediction_error(bsize, &x->plane[0].src, |
+ &xd->plane[0].pre[0]); |
- first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv, |
- &gf_motion_error); |
- if (cpi->oxcf.aq_mode == VARIANCE_AQ) { |
- vp9_clear_system_state(); |
- gf_motion_error = (int)(gf_motion_error * error_weight); |
- } |
+ first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv, |
+ &gf_motion_error); |
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) { |
+ vp9_clear_system_state(); |
+ gf_motion_error = (int)(gf_motion_error * error_weight); |
+ } |
- if (gf_motion_error < motion_error && gf_motion_error < this_error) |
- ++second_ref_count; |
+ if (gf_motion_error < motion_error && gf_motion_error < this_error) |
+ ++second_ref_count; |
- // Reset to last frame as reference buffer. |
- xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset; |
- xd->plane[1].pre[0].buf = first_ref_buf->u_buffer + recon_uvoffset; |
- xd->plane[2].pre[0].buf = first_ref_buf->v_buffer + recon_uvoffset; |
+ // Reset to last frame as reference buffer. |
+ xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset; |
+ xd->plane[1].pre[0].buf = first_ref_buf->u_buffer + recon_uvoffset; |
+ xd->plane[2].pre[0].buf = first_ref_buf->v_buffer + recon_uvoffset; |
- // In accumulating a score for the older reference frame take the |
- // best of the motion predicted score and the intra coded error |
- // (just as will be done for) accumulation of "coded_error" for |
- // the last frame. |
- if (gf_motion_error < this_error) |
- sr_coded_error += gf_motion_error; |
- else |
- sr_coded_error += this_error; |
+ // In accumulating a score for the older reference frame take the |
+ // best of the motion predicted score and the intra coded error |
+ // (just as will be done for) accumulation of "coded_error" for |
+ // the last frame. |
+ if (gf_motion_error < this_error) |
+ sr_coded_error += gf_motion_error; |
+ else |
+ sr_coded_error += this_error; |
+ } else { |
+ sr_coded_error += motion_error; |
+ } |
} else { |
sr_coded_error += motion_error; |
} |
+ |
// Start by assuming that intra mode is best. |
best_ref_mv.as_int = 0; |
@@ -805,7 +779,6 @@ |
fps.intra_error = (double)(intra_error >> 8); |
fps.coded_error = (double)(coded_error >> 8); |
fps.sr_coded_error = (double)(sr_coded_error >> 8); |
- fps.ssim_weighted_pred_err = fps.coded_error * simple_weight(cpi->Source); |
fps.count = 1.0; |
fps.pcnt_inter = (double)intercount / cm->MBs; |
fps.pcnt_second_ref = (double)second_ref_count / cm->MBs; |
@@ -938,8 +911,8 @@ |
for (q = rc->best_quality; q < rc->worst_quality; ++q) { |
const double factor = |
calc_correction_factor(err_per_mb, ERR_DIVISOR, |
- is_svc_upper_layer ? 0.8 : 0.5, |
- is_svc_upper_layer ? 1.0 : 0.90, q); |
+ is_svc_upper_layer ? SVC_FACTOR_PT_LOW : |
+ FACTOR_PT_LOW, FACTOR_PT_HIGH, q); |
const int bits_per_mb = vp9_rc_bits_per_mb(INTER_FRAME, q, |
factor * speed_term); |
if (bits_per_mb <= target_norm_bits_per_mb) |
@@ -947,7 +920,7 @@ |
} |
// Restriction on active max q for constrained quality mode. |
- if (cpi->oxcf.rc_mode == RC_MODE_CONSTRAINED_QUALITY) |
+ if (cpi->oxcf.rc_mode == VPX_CQ) |
q = MAX(q, oxcf->cq_level); |
return q; |
} |
@@ -960,7 +933,7 @@ |
const VP9EncoderConfig *const oxcf = &cpi->oxcf; |
const int is_spatial_svc = (svc->number_spatial_layers > 1) && |
(svc->number_temporal_layers == 1); |
- struct twopass_rc *const twopass = is_spatial_svc ? |
+ TWO_PASS *const twopass = is_spatial_svc ? |
&svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass; |
double frame_rate; |
FIRSTPASS_STATS *stats; |
@@ -1008,47 +981,22 @@ |
// This variable monitors how far behind the second ref update is lagging. |
twopass->sr_update_lag = 1; |
- // Scan the first pass file and calculate an average Intra / Inter error |
- // score ratio for the sequence. |
- { |
- const FIRSTPASS_STATS *const start_pos = twopass->stats_in; |
- FIRSTPASS_STATS this_frame; |
- double sum_iiratio = 0.0; |
- |
- while (input_stats(twopass, &this_frame) != EOF) { |
- const double iiratio = this_frame.intra_error / |
- DOUBLE_DIVIDE_CHECK(this_frame.coded_error); |
- sum_iiratio += fclamp(iiratio, 1.0, 20.0); |
- } |
- |
- twopass->avg_iiratio = sum_iiratio / |
- DOUBLE_DIVIDE_CHECK((double)stats->count); |
- |
- reset_fpf_position(twopass, start_pos); |
- } |
- |
// Scan the first pass file and calculate a modified total error based upon |
// the bias/power function used to allocate bits. |
{ |
- const FIRSTPASS_STATS *const start_pos = twopass->stats_in; |
- FIRSTPASS_STATS this_frame; |
- const double av_error = stats->ssim_weighted_pred_err / |
- DOUBLE_DIVIDE_CHECK(stats->count); |
- |
- |
- twopass->modified_error_total = 0.0; |
- twopass->modified_error_min = |
- (av_error * oxcf->two_pass_vbrmin_section) / 100; |
- twopass->modified_error_max = |
- (av_error * oxcf->two_pass_vbrmax_section) / 100; |
- |
- while (input_stats(twopass, &this_frame) != EOF) { |
- twopass->modified_error_total += |
- calculate_modified_err(cpi, &this_frame); |
+ const double avg_error = stats->coded_error / |
+ DOUBLE_DIVIDE_CHECK(stats->count); |
+ const FIRSTPASS_STATS *s = twopass->stats_in; |
+ double modified_error_total = 0.0; |
+ twopass->modified_error_min = (avg_error * |
+ oxcf->two_pass_vbrmin_section) / 100; |
+ twopass->modified_error_max = (avg_error * |
+ oxcf->two_pass_vbrmax_section) / 100; |
+ while (s < twopass->stats_in_end) { |
+ modified_error_total += calculate_modified_err(twopass, oxcf, s); |
+ ++s; |
} |
- twopass->modified_error_left = twopass->modified_error_total; |
- |
- reset_fpf_position(twopass, start_pos); |
+ twopass->modified_error_left = modified_error_total; |
} |
// Reset the vbr bits off target counter |
@@ -1073,7 +1021,7 @@ |
// Function to test for a condition where a complex transition is followed |
// 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. |
-static int detect_transition_to_still(struct twopass_rc *twopass, |
+static int detect_transition_to_still(TWO_PASS *twopass, |
int frame_interval, int still_interval, |
double loop_decay_rate, |
double last_decay_rate) { |
@@ -1111,7 +1059,7 @@ |
// This function detects a flash through the high relative pcnt_second_ref |
// score in the frame following a flash frame. The offset passed in should |
// reflect this. |
-static int detect_flash(const struct twopass_rc *twopass, int offset) { |
+static int detect_flash(const TWO_PASS *twopass, int offset) { |
FIRSTPASS_STATS next_frame; |
int flash_detected = 0; |
@@ -1133,52 +1081,45 @@ |
} |
// Update the motion related elements to the GF arf boost calculation. |
-static void accumulate_frame_motion_stats( |
- FIRSTPASS_STATS *this_frame, |
- double *this_frame_mv_in_out, |
- double *mv_in_out_accumulator, |
- double *abs_mv_in_out_accumulator, |
- double *mv_ratio_accumulator) { |
- double motion_pct; |
+static void accumulate_frame_motion_stats(const FIRSTPASS_STATS *stats, |
+ double *mv_in_out, |
+ double *mv_in_out_accumulator, |
+ double *abs_mv_in_out_accumulator, |
+ double *mv_ratio_accumulator) { |
+ const double pct = stats->pcnt_motion; |
- // Accumulate motion stats. |
- motion_pct = this_frame->pcnt_motion; |
- |
// Accumulate Motion In/Out of frame stats. |
- *this_frame_mv_in_out = this_frame->mv_in_out_count * motion_pct; |
- *mv_in_out_accumulator += this_frame->mv_in_out_count * motion_pct; |
- *abs_mv_in_out_accumulator += fabs(this_frame->mv_in_out_count * motion_pct); |
+ *mv_in_out = stats->mv_in_out_count * pct; |
+ *mv_in_out_accumulator += *mv_in_out; |
+ *abs_mv_in_out_accumulator += fabs(*mv_in_out); |
- // Accumulate a measure of how uniform (or conversely how random) |
- // the motion field is (a ratio of absmv / mv). |
- if (motion_pct > 0.05) { |
- const double this_frame_mvr_ratio = fabs(this_frame->mvr_abs) / |
- DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVr)); |
+ // Accumulate a measure of how uniform (or conversely how random) the motion |
+ // field is (a ratio of abs(mv) / mv). |
+ if (pct > 0.05) { |
+ const double mvr_ratio = fabs(stats->mvr_abs) / |
+ DOUBLE_DIVIDE_CHECK(fabs(stats->MVr)); |
+ const double mvc_ratio = fabs(stats->mvc_abs) / |
+ DOUBLE_DIVIDE_CHECK(fabs(stats->MVc)); |
- const double this_frame_mvc_ratio = fabs(this_frame->mvc_abs) / |
- DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVc)); |
- |
- *mv_ratio_accumulator += (this_frame_mvr_ratio < this_frame->mvr_abs) |
- ? (this_frame_mvr_ratio * motion_pct) |
- : this_frame->mvr_abs * motion_pct; |
- |
- *mv_ratio_accumulator += (this_frame_mvc_ratio < this_frame->mvc_abs) |
- ? (this_frame_mvc_ratio * motion_pct) |
- : this_frame->mvc_abs * motion_pct; |
+ *mv_ratio_accumulator += pct * (mvr_ratio < stats->mvr_abs ? |
+ mvr_ratio : stats->mvr_abs); |
+ *mv_ratio_accumulator += pct * (mvc_ratio < stats->mvc_abs ? |
+ mvc_ratio : stats->mvc_abs); |
} |
} |
// Calculate a baseline boost number for the current frame. |
-static double calc_frame_boost(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame, |
+static double calc_frame_boost(const TWO_PASS *twopass, |
+ const FIRSTPASS_STATS *this_frame, |
double this_frame_mv_in_out) { |
double frame_boost; |
// Underlying boost factor is based on inter intra error ratio. |
- if (this_frame->intra_error > cpi->twopass.gf_intra_err_min) |
+ if (this_frame->intra_error > twopass->gf_intra_err_min) |
frame_boost = (IIFACTOR * this_frame->intra_error / |
DOUBLE_DIVIDE_CHECK(this_frame->coded_error)); |
else |
- frame_boost = (IIFACTOR * cpi->twopass.gf_intra_err_min / |
+ frame_boost = (IIFACTOR * twopass->gf_intra_err_min / |
DOUBLE_DIVIDE_CHECK(this_frame->coded_error)); |
// Increase boost for frames where new data coming into frame (e.g. zoom out). |
@@ -1197,7 +1138,7 @@ |
int f_frames, int b_frames, |
int *f_boost, int *b_boost) { |
FIRSTPASS_STATS this_frame; |
- struct twopass_rc *const twopass = &cpi->twopass; |
+ TWO_PASS *const twopass = &cpi->twopass; |
int i; |
double boost_score = 0.0; |
double mv_ratio_accumulator = 0.0; |
@@ -1231,8 +1172,8 @@ |
? MIN_DECAY_FACTOR : decay_accumulator; |
} |
- boost_score += (decay_accumulator * |
- calc_frame_boost(cpi, &this_frame, this_frame_mv_in_out)); |
+ boost_score += decay_accumulator * calc_frame_boost(twopass, &this_frame, |
+ this_frame_mv_in_out); |
} |
*f_boost = (int)boost_score; |
@@ -1268,8 +1209,8 @@ |
? MIN_DECAY_FACTOR : decay_accumulator; |
} |
- boost_score += (decay_accumulator * |
- calc_frame_boost(cpi, &this_frame, this_frame_mv_in_out)); |
+ boost_score += decay_accumulator * calc_frame_boost(twopass, &this_frame, |
+ this_frame_mv_in_out); |
} |
*b_boost = (int)boost_score; |
@@ -1419,37 +1360,29 @@ |
#endif |
// Calculate a section intra ratio used in setting max loop filter. |
-static void calculate_section_intra_ratio(struct twopass_rc *twopass, |
- const FIRSTPASS_STATS *start_pos, |
- int section_length) { |
- FIRSTPASS_STATS next_frame; |
- FIRSTPASS_STATS sectionstats; |
- int i; |
+static int calculate_section_intra_ratio(const FIRSTPASS_STATS *begin, |
+ const FIRSTPASS_STATS *end, |
+ int section_length) { |
+ const FIRSTPASS_STATS *s = begin; |
+ double intra_error = 0.0; |
+ double coded_error = 0.0; |
+ int i = 0; |
- vp9_zero(next_frame); |
- vp9_zero(sectionstats); |
- |
- reset_fpf_position(twopass, start_pos); |
- |
- for (i = 0; i < section_length; ++i) { |
- input_stats(twopass, &next_frame); |
- accumulate_stats(§ionstats, &next_frame); |
+ while (s < end && i < section_length) { |
+ intra_error += s->intra_error; |
+ coded_error += s->coded_error; |
+ ++s; |
+ ++i; |
} |
- avg_stats(§ionstats); |
- |
- twopass->section_intra_rating = |
- (int)(sectionstats.intra_error / |
- DOUBLE_DIVIDE_CHECK(sectionstats.coded_error)); |
- |
- reset_fpf_position(twopass, start_pos); |
+ return (int)(intra_error / DOUBLE_DIVIDE_CHECK(coded_error)); |
} |
// Calculate the total bits to allocate in this GF/ARF group. |
static int64_t calculate_total_gf_group_bits(VP9_COMP *cpi, |
double gf_group_err) { |
const RATE_CONTROL *const rc = &cpi->rc; |
- const struct twopass_rc *const twopass = &cpi->twopass; |
+ const TWO_PASS *const twopass = &cpi->twopass; |
const int max_bits = frame_max_bits(rc, &cpi->oxcf); |
int64_t total_group_bits; |
@@ -1495,15 +1428,76 @@ |
return MAX((int)(((int64_t)boost * total_group_bits) / allocation_chunks), 0); |
} |
+static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits, |
+ double group_error, int gf_arf_bits) { |
+ RATE_CONTROL *const rc = &cpi->rc; |
+ const VP9EncoderConfig *const oxcf = &cpi->oxcf; |
+ TWO_PASS *twopass = &cpi->twopass; |
+ FIRSTPASS_STATS frame_stats; |
+ int i; |
+ int group_frame_index = 1; |
+ int target_frame_size; |
+ int key_frame; |
+ const int max_bits = frame_max_bits(&cpi->rc, &cpi->oxcf); |
+ int64_t total_group_bits = gf_group_bits; |
+ double modified_err = 0.0; |
+ double err_fraction; |
+ key_frame = cpi->common.frame_type == KEY_FRAME || |
+ vp9_is_upper_layer_key_frame(cpi); |
+ |
+ // For key frames the frame target rate is already set and it |
+ // is also the golden frame. |
+ // NOTE: We dont bother to check for the special case of ARF overlay |
+ // frames here, as there is clamping code for this in the function |
+ // vp9_rc_clamp_pframe_target_size(), which applies to one and two pass |
+ // encodes. |
+ if (!key_frame) { |
+ twopass->gf_group_bit_allocation[0] = gf_arf_bits; |
+ |
+ // Step over the golden frame / overlay frame |
+ if (EOF == input_stats(twopass, &frame_stats)) |
+ return; |
+ } |
+ |
+ // Store the bits to spend on the ARF if there is one. |
+ if (rc->source_alt_ref_pending) { |
+ twopass->gf_group_bit_allocation[group_frame_index++] = gf_arf_bits; |
+ } |
+ |
+ // Deduct the boost bits for arf or gf if it is not a key frame. |
+ if (rc->source_alt_ref_pending || !key_frame) |
+ total_group_bits -= gf_arf_bits; |
+ |
+ // Allocate bits to the other frames in the group. |
+ for (i = 0; i < rc->baseline_gf_interval - 1; ++i) { |
+ if (EOF == input_stats(twopass, &frame_stats)) |
+ break; |
+ |
+ modified_err = calculate_modified_err(twopass, oxcf, &frame_stats); |
+ |
+ if (group_error > 0) |
+ err_fraction = modified_err / DOUBLE_DIVIDE_CHECK(group_error); |
+ else |
+ err_fraction = 0.0; |
+ |
+ target_frame_size = (int)((double)total_group_bits * err_fraction); |
+ target_frame_size = clamp(target_frame_size, 0, |
+ MIN(max_bits, (int)total_group_bits)); |
+ |
+ twopass->gf_group_bit_allocation[group_frame_index++] = target_frame_size; |
+ } |
+} |
+ |
// Analyse and define a gf/arf group. |
static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
RATE_CONTROL *const rc = &cpi->rc; |
const VP9EncoderConfig *const oxcf = &cpi->oxcf; |
- struct twopass_rc *const twopass = &cpi->twopass; |
+ TWO_PASS *const twopass = &cpi->twopass; |
FIRSTPASS_STATS next_frame; |
- const FIRSTPASS_STATS *start_pos; |
+ const FIRSTPASS_STATS *const start_pos = twopass->stats_in; |
int i; |
+ |
double boost_score = 0.0; |
double old_boost_score = 0.0; |
double gf_group_err = 0.0; |
@@ -1521,21 +1515,30 @@ |
double mv_in_out_accumulator = 0.0; |
double abs_mv_in_out_accumulator = 0.0; |
double mv_ratio_accumulator_thresh; |
- unsigned int allow_alt_ref = oxcf->play_alternate && oxcf->lag_in_frames; |
+ unsigned int allow_alt_ref = is_altref_enabled(oxcf); |
int f_boost = 0; |
int b_boost = 0; |
int flash_detected; |
int active_max_gf_interval; |
+ int64_t gf_group_bits; |
+ double gf_group_error_left; |
+ int gf_arf_bits; |
+ // Reset the GF group data structures unless this is a key |
+ // frame in which case it will already have been done. |
+ if (cpi->common.frame_type != KEY_FRAME) { |
+ twopass->gf_group_index = 0; |
+ vp9_zero(twopass->gf_group_bit_allocation); |
+ } |
+ |
vp9_clear_system_state(); |
vp9_zero(next_frame); |
- twopass->gf_group_bits = 0; |
- start_pos = twopass->stats_in; |
+ gf_group_bits = 0; |
// Load stats for the current frame. |
- mod_frame_err = calculate_modified_err(cpi, this_frame); |
+ mod_frame_err = calculate_modified_err(twopass, oxcf, 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. |
@@ -1567,7 +1570,7 @@ |
++i; |
// Accumulate error score of frames in this gf group. |
- mod_frame_err = calculate_modified_err(cpi, this_frame); |
+ mod_frame_err = calculate_modified_err(twopass, oxcf, this_frame); |
gf_group_err += mod_frame_err; |
if (EOF == input_stats(twopass, &next_frame)) |
@@ -1606,12 +1609,12 @@ |
} |
// Calculate a boost number for this frame. |
- boost_score += (decay_accumulator * |
- calc_frame_boost(cpi, &next_frame, this_frame_mv_in_out)); |
+ boost_score += decay_accumulator * calc_frame_boost(twopass, &next_frame, |
+ this_frame_mv_in_out); |
// Break out conditions. |
if ( |
- // Break at cpi->max_gf_interval unless almost totally static. |
+ // Break at active_max_gf_interval unless almost totally static. |
(i >= active_max_gf_interval && (zero_motion_accumulator < 0.995)) || |
( |
// Don't break out with a very short interval. |
@@ -1642,7 +1645,7 @@ |
break; |
if (i < rc->frames_to_key) { |
- mod_frame_err = calculate_modified_err(cpi, this_frame); |
+ mod_frame_err = calculate_modified_err(twopass, oxcf, this_frame); |
gf_group_err += mod_frame_err; |
} |
} |
@@ -1738,7 +1741,7 @@ |
reset_fpf_position(twopass, start_pos); |
// Calculate the bits to be allocated to the gf/arf group as a whole |
- twopass->gf_group_bits = calculate_total_gf_group_bits(cpi, gf_group_err); |
+ gf_group_bits = calculate_total_gf_group_bits(cpi, gf_group_err); |
// Calculate the extra bits to be used for boosted frame(s) |
{ |
@@ -1749,19 +1752,8 @@ |
boost = clamp(boost, 125, (rc->baseline_gf_interval + 1) * 200); |
// Calculate the extra bits to be used for boosted frame(s) |
- twopass->gf_bits = calculate_boost_bits(rc->baseline_gf_interval, |
- boost, twopass->gf_group_bits); |
- |
- |
- // For key frames the frame target rate is set already. |
- // NOTE: We dont bother to check for the special case of ARF overlay |
- // frames here, as there is clamping code for this in the function |
- // vp9_rc_clamp_pframe_target_size(), which applies to one and two pass |
- // encodes. |
- if (cpi->common.frame_type != KEY_FRAME && |
- !vp9_is_upper_layer_key_frame(cpi)) { |
- vp9_rc_set_frame_target(cpi, twopass->gf_bits); |
- } |
+ gf_arf_bits = calculate_boost_bits(rc->baseline_gf_interval, |
+ boost, gf_group_bits); |
} |
// Adjust KF group bits and error remaining. |
@@ -1774,52 +1766,28 @@ |
// For normal GFs remove the score for the GF itself unless this is |
// also a key frame in which case it has already been accounted for. |
if (rc->source_alt_ref_pending) { |
- twopass->gf_group_error_left = (int64_t)(gf_group_err - mod_frame_err); |
+ gf_group_error_left = gf_group_err - mod_frame_err; |
} else if (cpi->common.frame_type != KEY_FRAME) { |
- twopass->gf_group_error_left = (int64_t)(gf_group_err |
- - gf_first_frame_err); |
+ gf_group_error_left = gf_group_err - gf_first_frame_err; |
} else { |
- twopass->gf_group_error_left = (int64_t)gf_group_err; |
+ gf_group_error_left = gf_group_err; |
} |
+ // Allocate bits to each of the frames in the GF group. |
+ allocate_gf_group_bits(cpi, gf_group_bits, gf_group_error_left, gf_arf_bits); |
+ |
+ // Reset the file position. |
+ reset_fpf_position(twopass, start_pos); |
+ |
// Calculate a section intra ratio used in setting max loop filter. |
if (cpi->common.frame_type != KEY_FRAME) { |
- calculate_section_intra_ratio(twopass, start_pos, rc->baseline_gf_interval); |
+ twopass->section_intra_rating = |
+ calculate_section_intra_ratio(start_pos, twopass->stats_in_end, |
+ rc->baseline_gf_interval); |
} |
} |
-// Allocate bits to a normal frame that is neither a gf an arf or a key frame. |
-static void assign_std_frame_bits(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
- struct twopass_rc *twopass = &cpi->twopass; |
- // For a single frame. |
- const int max_bits = frame_max_bits(&cpi->rc, &cpi->oxcf); |
- // Calculate modified prediction error used in bit allocation. |
- const double modified_err = calculate_modified_err(cpi, this_frame); |
- int target_frame_size; |
- double err_fraction; |
- |
- if (twopass->gf_group_error_left > 0) |
- // What portion of the remaining GF group error is used by this frame. |
- err_fraction = modified_err / twopass->gf_group_error_left; |
- else |
- err_fraction = 0.0; |
- |
- // How many of those bits available for allocation should we give it? |
- target_frame_size = (int)((double)twopass->gf_group_bits * err_fraction); |
- |
- // Clip target size to 0 - max_bits (or cpi->twopass.gf_group_bits) at |
- // the top end. |
- target_frame_size = clamp(target_frame_size, 0, |
- MIN(max_bits, (int)twopass->gf_group_bits)); |
- |
- // Adjust error and bits remaining. |
- twopass->gf_group_error_left -= (int64_t)modified_err; |
- |
- // Per frame bit target for this frame. |
- vp9_rc_set_frame_target(cpi, target_frame_size); |
-} |
- |
-static int test_candidate_kf(struct twopass_rc *twopass, |
+static int test_candidate_kf(TWO_PASS *twopass, |
const FIRSTPASS_STATS *last_frame, |
const FIRSTPASS_STATS *this_frame, |
const FIRSTPASS_STATS *next_frame) { |
@@ -1899,11 +1867,13 @@ |
static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
int i, j; |
RATE_CONTROL *const rc = &cpi->rc; |
- struct twopass_rc *const twopass = &cpi->twopass; |
+ TWO_PASS *const twopass = &cpi->twopass; |
+ const VP9EncoderConfig *const oxcf = &cpi->oxcf; |
const FIRSTPASS_STATS first_frame = *this_frame; |
- const FIRSTPASS_STATS *start_position = twopass->stats_in; |
+ const FIRSTPASS_STATS *const start_position = twopass->stats_in; |
FIRSTPASS_STATS next_frame; |
FIRSTPASS_STATS last_frame; |
+ int kf_bits = 0; |
double decay_accumulator = 1.0; |
double zero_motion_accumulator = 1.0; |
double boost_score = 0.0; |
@@ -1915,6 +1885,10 @@ |
cpi->common.frame_type = KEY_FRAME; |
+ // Reset the GF group data structures. |
+ twopass->gf_group_index = 0; |
+ vp9_zero(twopass->gf_group_bit_allocation); |
+ |
// Is this a forced key frame by interval. |
rc->this_key_frame_forced = rc->next_key_frame_forced; |
@@ -1929,14 +1903,14 @@ |
twopass->kf_group_bits = 0; // Total bits available to kf group |
twopass->kf_group_error_left = 0; // Group modified error score. |
- kf_mod_err = calculate_modified_err(cpi, this_frame); |
+ kf_mod_err = calculate_modified_err(twopass, oxcf, this_frame); |
// Find the next keyframe. |
i = 0; |
while (twopass->stats_in < twopass->stats_in_end && |
rc->frames_to_key < cpi->oxcf.key_freq) { |
// Accumulate kf group error. |
- kf_group_err += calculate_modified_err(cpi, this_frame); |
+ kf_group_err += calculate_modified_err(twopass, oxcf, this_frame); |
// Load the next frame's stats. |
last_frame = *this_frame; |
@@ -1998,7 +1972,7 @@ |
// Rescan to get the correct error data for the forced kf group. |
for (i = 0; i < rc->frames_to_key; ++i) { |
- kf_group_err += calculate_modified_err(cpi, &tmp_frame); |
+ kf_group_err += calculate_modified_err(twopass, oxcf, &tmp_frame); |
input_stats(twopass, &tmp_frame); |
} |
rc->next_key_frame_forced = 1; |
@@ -2012,7 +1986,7 @@ |
// Special case for the last key frame of the file. |
if (twopass->stats_in >= twopass->stats_in_end) { |
// Accumulate kf group error. |
- kf_group_err += calculate_modified_err(cpi, this_frame); |
+ kf_group_err += calculate_modified_err(twopass, oxcf, this_frame); |
} |
// Calculate the number of bits that should be assigned to the kf group. |
@@ -2080,11 +2054,15 @@ |
} |
} |
+ reset_fpf_position(twopass, start_position); |
+ |
// Store the zero motion percentage |
twopass->kf_zeromotion_pct = (int)(zero_motion_accumulator * 100.0); |
// Calculate a section intra ratio used in setting max loop filter. |
- calculate_section_intra_ratio(twopass, start_position, rc->frames_to_key); |
+ twopass->section_intra_rating = |
+ calculate_section_intra_ratio(start_position, twopass->stats_in_end, |
+ rc->frames_to_key); |
// Work out how many bits to allocate for the key frame itself. |
rc->kf_boost = (int)boost_score; |
@@ -2094,13 +2072,13 @@ |
if (rc->kf_boost < MIN_KF_BOOST) |
rc->kf_boost = MIN_KF_BOOST; |
- twopass->kf_bits = calculate_boost_bits((rc->frames_to_key - 1), |
- rc->kf_boost, twopass->kf_group_bits); |
+ kf_bits = calculate_boost_bits((rc->frames_to_key - 1), |
+ rc->kf_boost, twopass->kf_group_bits); |
- twopass->kf_group_bits -= twopass->kf_bits; |
+ twopass->kf_group_bits -= kf_bits; |
- // Per frame bit target for this frame. |
- vp9_rc_set_frame_target(cpi, twopass->kf_bits); |
+ // Save the bits to spend on the key frame. |
+ twopass->gf_group_bit_allocation[0] = kf_bits; |
// Note the total error score of the kf group minus the key frame itself. |
twopass->kf_group_error_left = (int)(kf_group_err - kf_mod_err); |
@@ -2111,19 +2089,6 @@ |
twopass->modified_error_left -= kf_group_err; |
} |
-void vp9_rc_get_first_pass_params(VP9_COMP *cpi) { |
- VP9_COMMON *const cm = &cpi->common; |
- if (!cpi->refresh_alt_ref_frame && |
- (cm->current_video_frame == 0 || |
- (cpi->frame_flags & FRAMEFLAGS_KEY))) { |
- cm->frame_type = KEY_FRAME; |
- } else { |
- cm->frame_type = INTER_FRAME; |
- } |
- // Do not use periodic key frames. |
- cpi->rc.frames_to_key = INT_MAX; |
-} |
- |
// For VBR...adjustment to the frame target based on error from previous frames |
void vbr_rate_correction(int * this_frame_target, |
const int64_t vbr_bits_off_target) { |
@@ -2144,14 +2109,12 @@ |
void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { |
VP9_COMMON *const cm = &cpi->common; |
RATE_CONTROL *const rc = &cpi->rc; |
- struct twopass_rc *const twopass = &cpi->twopass; |
+ TWO_PASS *const twopass = &cpi->twopass; |
int frames_left; |
FIRSTPASS_STATS this_frame; |
FIRSTPASS_STATS this_frame_copy; |
- double this_frame_intra_error; |
- double this_frame_coded_error; |
- int target; |
+ int target_rate; |
LAYER_CONTEXT *lc = NULL; |
const int is_spatial_svc = (cpi->use_svc && |
cpi->svc.number_temporal_layers == 1); |
@@ -2167,16 +2130,23 @@ |
if (!twopass->stats_in) |
return; |
+ // Increment the gf group index. |
+ ++twopass->gf_group_index; |
+ |
+ // If this is an arf frame then we dont want to read the stats file or |
+ // advance the input pointer as we already have what we need. |
if (cpi->refresh_alt_ref_frame) { |
- int modified_target = twopass->gf_bits; |
- rc->base_frame_target = twopass->gf_bits; |
- cm->frame_type = INTER_FRAME; |
+ int target_rate; |
+ target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index]; |
+ target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate); |
+ rc->base_frame_target = target_rate; |
#ifdef LONG_TERM_VBR_CORRECTION |
// Correction to rate target based on prior over or under shoot. |
- if (cpi->oxcf.rc_mode == RC_MODE_VBR) |
- vbr_rate_correction(&modified_target, rc->vbr_bits_off_target); |
+ if (cpi->oxcf.rc_mode == VPX_VBR) |
+ vbr_rate_correction(&target_rate, rc->vbr_bits_off_target); |
#endif |
- vp9_rc_set_frame_target(cpi, modified_target); |
+ vp9_rc_set_frame_target(cpi, target_rate); |
+ cm->frame_type = INTER_FRAME; |
return; |
} |
@@ -2187,7 +2157,7 @@ |
twopass->gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs; |
} |
- if (cpi->oxcf.rc_mode == RC_MODE_CONSTANT_QUALITY) { |
+ if (cpi->oxcf.rc_mode == VPX_Q) { |
twopass->active_worst_quality = cpi->oxcf.cq_level; |
} else if (cm->current_video_frame == 0 || |
(is_spatial_svc && lc->current_video_frame_in_layer == 0)) { |
@@ -2204,34 +2174,33 @@ |
if (EOF == input_stats(twopass, &this_frame)) |
return; |
- this_frame_intra_error = this_frame.intra_error; |
- this_frame_coded_error = this_frame.coded_error; |
+ // Local copy of the current frame's first pass stats. |
+ this_frame_copy = this_frame; |
// Keyframe and section processing. |
if (rc->frames_to_key == 0 || |
(cpi->frame_flags & FRAMEFLAGS_KEY)) { |
// Define next KF group and assign bits to it. |
- this_frame_copy = this_frame; |
find_next_key_frame(cpi, &this_frame_copy); |
- // Don't place key frame in any enhancement layers in spatial svc |
- if (is_spatial_svc) { |
- lc->is_key_frame = 1; |
- if (cpi->svc.spatial_layer_id > 0) { |
- cm->frame_type = INTER_FRAME; |
- } |
- } |
} else { |
- if (is_spatial_svc) { |
- lc->is_key_frame = 0; |
- } |
cm->frame_type = INTER_FRAME; |
} |
- // Is this frame a GF / ARF? (Note: a key frame is always also a GF). |
- if (rc->frames_till_gf_update_due == 0) { |
- // Define next gf group and assign bits to it. |
- this_frame_copy = this_frame; |
+ if (is_spatial_svc) { |
+ if (cpi->svc.spatial_layer_id == 0) { |
+ lc->is_key_frame = (cm->frame_type == KEY_FRAME); |
+ } else { |
+ cm->frame_type = INTER_FRAME; |
+ lc->is_key_frame = cpi->svc.layer_context[0].is_key_frame; |
+ if (lc->is_key_frame) { |
+ cpi->ref_frame_flags &= (~VP9_LAST_FLAG); |
+ } |
+ } |
+ } |
+ |
+ // Define a new GF/ARF group. (Should always enter here for key frames). |
+ if (rc->frames_till_gf_update_due == 0) { |
#if CONFIG_MULTIPLE_ARF |
if (cpi->multi_arf_enabled) { |
define_fixed_arf_period(cpi); |
@@ -2254,16 +2223,8 @@ |
rc->frames_till_gf_update_due = rc->baseline_gf_interval; |
cpi->refresh_golden_frame = 1; |
- } else { |
- // Otherwise this is an ordinary frame. |
- // Assign bits from those allocated to the GF group. |
- this_frame_copy = this_frame; |
- assign_std_frame_bits(cpi, &this_frame_copy); |
} |
- // Keep a globally available copy of this and the next frame's iiratio. |
- twopass->this_iiratio = (int)(this_frame_intra_error / |
- DOUBLE_DIVIDE_CHECK(this_frame_coded_error)); |
{ |
FIRSTPASS_STATS next_frame; |
if (lookup_next_frame_stats(twopass, &next_frame) != EOF) { |
@@ -2272,24 +2233,26 @@ |
} |
} |
+ target_rate = twopass->gf_group_bit_allocation[twopass->gf_group_index]; |
if (cpi->common.frame_type == KEY_FRAME) |
- target = vp9_rc_clamp_iframe_target_size(cpi, rc->this_frame_target); |
+ target_rate = vp9_rc_clamp_iframe_target_size(cpi, target_rate); |
else |
- target = vp9_rc_clamp_pframe_target_size(cpi, rc->this_frame_target); |
+ target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate); |
- rc->base_frame_target = target; |
+ rc->base_frame_target = target_rate; |
#ifdef LONG_TERM_VBR_CORRECTION |
// Correction to rate target based on prior over or under shoot. |
- if (cpi->oxcf.rc_mode == RC_MODE_VBR) |
- vbr_rate_correction(&target, rc->vbr_bits_off_target); |
+ if (cpi->oxcf.rc_mode == VPX_VBR) |
+ vbr_rate_correction(&target_rate, rc->vbr_bits_off_target); |
#endif |
- vp9_rc_set_frame_target(cpi, target); |
+ vp9_rc_set_frame_target(cpi, target_rate); |
// Update the total stats remaining structure. |
subtract_stats(&twopass->total_left_stats, &this_frame); |
} |
void vp9_twopass_postencode_update(VP9_COMP *cpi) { |
+ TWO_PASS *const twopass = &cpi->twopass; |
RATE_CONTROL *const rc = &cpi->rc; |
#ifdef LONG_TERM_VBR_CORRECTION |
// In this experimental mode, the VBR correction is done exclusively through |
@@ -2311,14 +2274,13 @@ |
// vs. actual bitrate gradually as we progress towards the end of the |
// sequence in order to mitigate this effect. |
const double progress = |
- (double)(cpi->twopass.stats_in - cpi->twopass.stats_in_start) / |
- (cpi->twopass.stats_in_end - cpi->twopass.stats_in_start); |
+ (double)(twopass->stats_in - twopass->stats_in_start) / |
+ (twopass->stats_in_end - twopass->stats_in_start); |
const int bits_used = (int)(progress * rc->this_frame_target + |
(1.0 - progress) * rc->projected_frame_size); |
#endif |
- cpi->twopass.bits_left -= bits_used; |
- cpi->twopass.bits_left = MAX(cpi->twopass.bits_left, 0); |
+ twopass->bits_left = MAX(twopass->bits_left - bits_used, 0); |
#ifdef LONG_TERM_VBR_CORRECTION |
if (cpi->common.frame_type != KEY_FRAME && |
@@ -2328,12 +2290,10 @@ |
vp9_is_upper_layer_key_frame(cpi)) { |
// For key frames kf_group_bits already had the target bits subtracted out. |
// So now update to the correct value based on the actual bits used. |
- cpi->twopass.kf_group_bits += cpi->rc.this_frame_target - bits_used; |
+ twopass->kf_group_bits += rc->this_frame_target - bits_used; |
} else { |
#endif |
- cpi->twopass.kf_group_bits -= bits_used; |
- cpi->twopass.gf_group_bits -= bits_used; |
- cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0); |
+ twopass->kf_group_bits -= bits_used; |
} |
- cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0); |
+ twopass->kf_group_bits = MAX(twopass->kf_group_bits, 0); |
} |