| 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);
|
| }
|
|
|