| Index: source/libvpx/vp9/encoder/vp9_firstpass.c
|
| ===================================================================
|
| --- source/libvpx/vp9/encoder/vp9_firstpass.c (revision 263011)
|
| +++ source/libvpx/vp9/encoder/vp9_firstpass.c (working copy)
|
| @@ -20,9 +20,10 @@
|
|
|
| #include "vp9/common/vp9_entropymv.h"
|
| #include "vp9/common/vp9_quant_common.h"
|
| -#include "vp9/common/vp9_reconinter.h" // setup_dst_planes()
|
| +#include "vp9/common/vp9_reconinter.h" // vp9_setup_dst_planes()
|
| #include "vp9/common/vp9_systemdependent.h"
|
|
|
| +#include "vp9/encoder/vp9_aq_variance.h"
|
| #include "vp9/encoder/vp9_block.h"
|
| #include "vp9/encoder/vp9_encodeframe.h"
|
| #include "vp9/encoder/vp9_encodemb.h"
|
| @@ -34,7 +35,6 @@
|
| #include "vp9/encoder/vp9_quantize.h"
|
| #include "vp9/encoder/vp9_ratectrl.h"
|
| #include "vp9/encoder/vp9_rdopt.h"
|
| -#include "vp9/encoder/vp9_vaq.h"
|
| #include "vp9/encoder/vp9_variance.h"
|
|
|
| #define OUTPUT_FPF 0
|
| @@ -54,30 +54,21 @@
|
|
|
| #define MIN_KF_BOOST 300
|
|
|
| -#define DISABLE_RC_LONG_TERM_MEM 0
|
| +#if CONFIG_MULTIPLE_ARF
|
| +// Set MIN_GF_INTERVAL to 1 for the full decomposition.
|
| +#define MIN_GF_INTERVAL 2
|
| +#else
|
| +#define MIN_GF_INTERVAL 4
|
| +#endif
|
|
|
| +#define DISABLE_RC_LONG_TERM_MEM
|
| +
|
| static void swap_yv12(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
|
| YV12_BUFFER_CONFIG temp = *a;
|
| *a = *b;
|
| *b = temp;
|
| }
|
|
|
| -static int select_cq_level(int qindex) {
|
| - int ret_val = QINDEX_RANGE - 1;
|
| - int i;
|
| -
|
| - double target_q = (vp9_convert_qindex_to_q(qindex) * 0.5847) + 1.0;
|
| -
|
| - for (i = 0; i < QINDEX_RANGE; ++i) {
|
| - if (target_q <= vp9_convert_qindex_to_q(i)) {
|
| - ret_val = i;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - return ret_val;
|
| -}
|
| -
|
| static int gfboost_qadjust(int qindex) {
|
| const double q = vp9_convert_qindex_to_q(qindex);
|
| return (int)((0.00000828 * q * q * q) +
|
| @@ -85,17 +76,10 @@
|
| (1.32 * q) + 79.3);
|
| }
|
|
|
| -static int kfboost_qadjust(int qindex) {
|
| - const double q = vp9_convert_qindex_to_q(qindex);
|
| - return (int)((0.00000973 * q * q * q) +
|
| - (-0.00613 * q * q) +
|
| - (1.316 * q) + 121.2);
|
| -}
|
| -
|
| // 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,
|
| - FIRSTPASS_STATS *position) {
|
| + const FIRSTPASS_STATS *position) {
|
| p->stats_in = position;
|
| }
|
|
|
| @@ -197,10 +181,13 @@
|
| section->new_mv_count = 0.0;
|
| section->count = 0.0;
|
| section->duration = 1.0;
|
| + section->spatial_layer_id = 0;
|
| }
|
|
|
| -static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) {
|
| +static void accumulate_stats(FIRSTPASS_STATS *section,
|
| + const FIRSTPASS_STATS *frame) {
|
| section->frame += frame->frame;
|
| + section->spatial_layer_id = frame->spatial_layer_id;
|
| section->intra_error += frame->intra_error;
|
| section->coded_error += frame->coded_error;
|
| section->sr_coded_error += frame->sr_coded_error;
|
| @@ -221,7 +208,8 @@
|
| section->duration += frame->duration;
|
| }
|
|
|
| -static void subtract_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) {
|
| +static void subtract_stats(FIRSTPASS_STATS *section,
|
| + const FIRSTPASS_STATS *frame) {
|
| section->frame -= frame->frame;
|
| section->intra_error -= frame->intra_error;
|
| section->coded_error -= frame->coded_error;
|
| @@ -269,13 +257,23 @@
|
| // harder frames.
|
| static double calculate_modified_err(const VP9_COMP *cpi,
|
| const FIRSTPASS_STATS *this_frame) {
|
| - const struct twopass_rc *const twopass = &cpi->twopass;
|
| - const FIRSTPASS_STATS *const stats = &twopass->total_stats;
|
| - const double av_err = stats->ssim_weighted_pred_err / stats->count;
|
| - double modified_error = av_err * pow(this_frame->ssim_weighted_pred_err /
|
| - DOUBLE_DIVIDE_CHECK(av_err),
|
| - cpi->oxcf.two_pass_vbrbias / 100.0);
|
| + 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);
|
| +
|
| return fclamp(modified_error,
|
| twopass->modified_error_min, twopass->modified_error_max);
|
| }
|
| @@ -338,15 +336,13 @@
|
| }
|
|
|
| // This function returns the maximum target rate per frame.
|
| -static int frame_max_bits(const VP9_COMP *cpi) {
|
| - int64_t max_bits =
|
| - ((int64_t)cpi->rc.av_per_frame_bandwidth *
|
| - (int64_t)cpi->oxcf.two_pass_vbrmax_section) / 100;
|
| -
|
| +static int frame_max_bits(const RATE_CONTROL *rc, const VP9_CONFIG *oxcf) {
|
| + int64_t max_bits = ((int64_t)rc->av_per_frame_bandwidth *
|
| + (int64_t)oxcf->two_pass_vbrmax_section) / 100;
|
| if (max_bits < 0)
|
| max_bits = 0;
|
| - else if (max_bits > cpi->rc.max_frame_bandwidth)
|
| - max_bits = cpi->rc.max_frame_bandwidth;
|
| + else if (max_bits > rc->max_frame_bandwidth)
|
| + max_bits = rc->max_frame_bandwidth;
|
|
|
| return (int)max_bits;
|
| }
|
| @@ -356,7 +352,15 @@
|
| }
|
|
|
| void vp9_end_first_pass(VP9_COMP *cpi) {
|
| - output_stats(&cpi->twopass.total_stats, cpi->output_pkt_list);
|
| + if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) {
|
| + int i;
|
| + for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
|
| + output_stats(&cpi->svc.layer_context[i].twopass.total_stats,
|
| + cpi->output_pkt_list);
|
| + }
|
| + } else {
|
| + output_stats(&cpi->twopass.total_stats, cpi->output_pkt_list);
|
| + }
|
| }
|
|
|
| static vp9_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
|
| @@ -379,7 +383,7 @@
|
| const uint8_t *const ref = xd->plane[0].pre[0].buf;
|
| const int ref_stride = xd->plane[0].pre[0].stride;
|
| unsigned int sse;
|
| - vp9_variance_fn_t fn = get_block_variance_fn(xd->mi_8x8[0]->mbmi.sb_type);
|
| + vp9_variance_fn_t fn = get_block_variance_fn(xd->mi[0]->mbmi.sb_type);
|
| fn(src, src_stride, ref, ref_stride, &sse);
|
| return sse;
|
| }
|
| @@ -393,7 +397,7 @@
|
| int num00, tmp_err, n, sr = 0;
|
| int step_param = 3;
|
| int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
|
| - const BLOCK_SIZE bsize = xd->mi_8x8[0]->mbmi.sb_type;
|
| + const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
|
| vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
|
| int new_mv_mode_penalty = 256;
|
| const int quart_frm = MIN(cpi->common.width, cpi->common.height);
|
| @@ -415,6 +419,8 @@
|
| x->sadperbit16, &num00, &v_fn_ptr,
|
| x->nmvjointcost,
|
| x->mvcost, ref_mv);
|
| + if (tmp_err < INT_MAX)
|
| + tmp_err = vp9_get_mvpred_var(x, &tmp_mv, ref_mv, &v_fn_ptr, 1);
|
| if (tmp_err < INT_MAX - new_mv_mode_penalty)
|
| tmp_err += new_mv_mode_penalty;
|
|
|
| @@ -439,6 +445,8 @@
|
| &num00, &v_fn_ptr,
|
| x->nmvjointcost,
|
| x->mvcost, ref_mv);
|
| + if (tmp_err < INT_MAX)
|
| + tmp_err = vp9_get_mvpred_var(x, &tmp_mv, ref_mv, &v_fn_ptr, 1);
|
| if (tmp_err < INT_MAX - new_mv_mode_penalty)
|
| tmp_err += new_mv_mode_penalty;
|
|
|
| @@ -474,11 +482,11 @@
|
|
|
| int recon_yoffset, recon_uvoffset;
|
| YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
|
| - YV12_BUFFER_CONFIG *const gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
| + YV12_BUFFER_CONFIG *gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
| YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
|
| - const int recon_y_stride = lst_yv12->y_stride;
|
| - const int recon_uv_stride = lst_yv12->uv_stride;
|
| - const int uv_mb_height = 16 >> (lst_yv12->y_height > lst_yv12->uv_height);
|
| + int recon_y_stride = lst_yv12->y_stride;
|
| + int recon_uv_stride = lst_yv12->uv_stride;
|
| + int uv_mb_height = 16 >> (lst_yv12->y_height > lst_yv12->uv_height);
|
| int64_t intra_error = 0;
|
| int64_t coded_error = 0;
|
| int64_t sr_coded_error = 0;
|
| @@ -494,17 +502,47 @@
|
| int new_mv_count = 0;
|
| int sum_in_vectors = 0;
|
| uint32_t lastmv_as_int = 0;
|
| - struct twopass_rc *const twopass = &cpi->twopass;
|
| + struct twopass_rc *twopass = &cpi->twopass;
|
| const MV zero_mv = {0, 0};
|
| + const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
|
|
|
| vp9_clear_system_state();
|
|
|
| + 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;
|
| + twopass = &cpi->svc.layer_context[cpi->svc.spatial_layer_id].twopass;
|
| +
|
| + vp9_scale_references(cpi);
|
| +
|
| + // Use either last frame or alt frame for motion search.
|
| + if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
|
| + scaled_ref_buf = vp9_get_scaled_ref_frame(cpi, LAST_FRAME);
|
| + ref_frame = LAST_FRAME;
|
| + } else if (cpi->ref_frame_flags & VP9_ALT_FLAG) {
|
| + scaled_ref_buf = vp9_get_scaled_ref_frame(cpi, ALTREF_FRAME);
|
| + ref_frame = ALTREF_FRAME;
|
| + }
|
| +
|
| + if (scaled_ref_buf != NULL) {
|
| + // Update the stride since we are using scaled reference buffer
|
| + first_ref_buf = scaled_ref_buf;
|
| + recon_y_stride = first_ref_buf->y_stride;
|
| + recon_uv_stride = first_ref_buf->uv_stride;
|
| + uv_mb_height = 16 >> (first_ref_buf->y_height > first_ref_buf->uv_height);
|
| + }
|
| +
|
| + // Disable golden frame for svc first pass for now.
|
| + gld_yv12 = NULL;
|
| + set_ref_ptrs(cm, xd, ref_frame, NONE);
|
| + }
|
| +
|
| vp9_setup_src_planes(x, cpi->Source, 0, 0);
|
| - setup_pre_planes(xd, 0, lst_yv12, 0, 0, NULL);
|
| - setup_dst_planes(xd, new_yv12, 0, 0);
|
| + vp9_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL);
|
| + vp9_setup_dst_planes(xd, new_yv12, 0, 0);
|
|
|
| - xd->mi_8x8 = cm->mi_grid_visible;
|
| - xd->mi_8x8[0] = cm->mi;
|
| + xd->mi = cm->mi_grid_visible;
|
| + xd->mi[0] = cm->mi;
|
|
|
| vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
|
|
|
| @@ -552,8 +590,8 @@
|
| xd->plane[1].dst.buf = new_yv12->u_buffer + recon_uvoffset;
|
| xd->plane[2].dst.buf = new_yv12->v_buffer + recon_uvoffset;
|
| xd->left_available = (mb_col != 0);
|
| - xd->mi_8x8[0]->mbmi.sb_type = bsize;
|
| - xd->mi_8x8[0]->mbmi.ref_frame[0] = INTRA_FRAME;
|
| + xd->mi[0]->mbmi.sb_type = bsize;
|
| + xd->mi[0]->mbmi.ref_frame[0] = INTRA_FRAME;
|
| set_mi_row_col(xd, &tile,
|
| mb_row << 1, num_8x8_blocks_high_lookup[bsize],
|
| mb_col << 1, num_8x8_blocks_wide_lookup[bsize],
|
| @@ -593,7 +631,7 @@
|
| int tmp_err, motion_error;
|
| int_mv mv, tmp_mv;
|
|
|
| - xd->plane[0].pre[0].buf = lst_yv12->y_buffer + recon_yoffset;
|
| + xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
|
| motion_error = zz_motion_search(x);
|
| // Assume 0,0 motion with no mv overhead.
|
| mv.as_int = tmp_mv.as_int = 0;
|
| @@ -625,7 +663,7 @@
|
| }
|
|
|
| // Search in an older reference frame.
|
| - if (cm->current_video_frame > 1) {
|
| + if (cm->current_video_frame > 1 && gld_yv12 != NULL) {
|
| // Assume 0,0 motion with no mv overhead.
|
| int gf_motion_error;
|
|
|
| @@ -643,9 +681,9 @@
|
| ++second_ref_count;
|
|
|
| // Reset to last frame as reference buffer.
|
| - xd->plane[0].pre[0].buf = lst_yv12->y_buffer + recon_yoffset;
|
| - xd->plane[1].pre[0].buf = lst_yv12->u_buffer + recon_uvoffset;
|
| - xd->plane[2].pre[0].buf = lst_yv12->v_buffer + recon_uvoffset;
|
| + 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
|
| @@ -672,10 +710,11 @@
|
| mv.as_mv.row *= 8;
|
| mv.as_mv.col *= 8;
|
| this_error = motion_error;
|
| - vp9_set_mbmode_and_mvs(xd, NEWMV, &mv.as_mv);
|
| - xd->mi_8x8[0]->mbmi.tx_size = TX_4X4;
|
| - xd->mi_8x8[0]->mbmi.ref_frame[0] = LAST_FRAME;
|
| - xd->mi_8x8[0]->mbmi.ref_frame[1] = NONE;
|
| + xd->mi[0]->mbmi.mode = NEWMV;
|
| + xd->mi[0]->mbmi.mv[0] = mv;
|
| + xd->mi[0]->mbmi.tx_size = TX_4X4;
|
| + xd->mi[0]->mbmi.ref_frame[0] = LAST_FRAME;
|
| + xd->mi[0]->mbmi.ref_frame[1] = NONE;
|
| vp9_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize);
|
| vp9_encode_sby_pass1(x, bsize);
|
| sum_mvr += mv.as_mv.row;
|
| @@ -752,6 +791,7 @@
|
| FIRSTPASS_STATS fps;
|
|
|
| fps.frame = cm->current_video_frame;
|
| + fps.spatial_layer_id = cpi->svc.spatial_layer_id;
|
| fps.intra_error = (double)(intra_error >> 8);
|
| fps.coded_error = (double)(coded_error >> 8);
|
| fps.sr_coded_error = (double)(sr_coded_error >> 8);
|
| @@ -801,20 +841,28 @@
|
| (twopass->this_frame_stats.pcnt_inter > 0.20) &&
|
| ((twopass->this_frame_stats.intra_error /
|
| DOUBLE_DIVIDE_CHECK(twopass->this_frame_stats.coded_error)) > 2.0))) {
|
| - vp8_yv12_copy_frame(lst_yv12, gld_yv12);
|
| + if (gld_yv12 != NULL) {
|
| + vp8_yv12_copy_frame(lst_yv12, gld_yv12);
|
| + }
|
| twopass->sr_update_lag = 1;
|
| } else {
|
| ++twopass->sr_update_lag;
|
| }
|
| - // Swap frame pointers so last frame refers to the frame we just compressed.
|
| - swap_yv12(lst_yv12, new_yv12);
|
|
|
| + if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) {
|
| + vp9_update_reference_frames(cpi);
|
| + } else {
|
| + // Swap frame pointers so last frame refers to the frame we just compressed.
|
| + swap_yv12(lst_yv12, new_yv12);
|
| + }
|
| +
|
| vp9_extend_frame_borders(lst_yv12);
|
|
|
| // Special case for the first frame. Copy into the GF buffer as a second
|
| // reference.
|
| - if (cm->current_video_frame == 0)
|
| + if (cm->current_video_frame == 0 && gld_yv12 != NULL) {
|
| vp8_yv12_copy_frame(lst_yv12, gld_yv12);
|
| + }
|
|
|
| // Use this to see what the first pass reconstruction looks like.
|
| if (0) {
|
| @@ -835,12 +883,6 @@
|
| ++cm->current_video_frame;
|
| }
|
|
|
| -// Estimate a cost per mb attributable to overheads such as the coding of modes
|
| -// and motion vectors. This currently makes simplistic assumptions for testing.
|
| -static double bitcost(double prob) {
|
| - return -(log(prob) / log(2.0));
|
| -}
|
| -
|
| static double calc_correction_factor(double err_per_mb,
|
| double err_divisor,
|
| double pt_low,
|
| @@ -868,21 +910,21 @@
|
|
|
| const double section_err = fpstats->coded_error / fpstats->count;
|
| const double err_per_mb = section_err / num_mbs;
|
| + const double speed_term = 1.0 + ((double)cpi->speed * 0.04);
|
|
|
| if (section_target_bandwitdh <= 0)
|
| return rc->worst_quality; // Highest value allowed
|
|
|
| - target_norm_bits_per_mb = section_target_bandwitdh < (1 << 20)
|
| - ? (512 * section_target_bandwitdh) / num_mbs
|
| - : 512 * (section_target_bandwitdh / num_mbs);
|
| + target_norm_bits_per_mb =
|
| + ((uint64_t)section_target_bandwitdh << BPER_MB_NORMBITS) / num_mbs;
|
|
|
| // Try and pick a max Q that will be high enough to encode the
|
| // content at the given rate.
|
| for (q = rc->best_quality; q < rc->worst_quality; ++q) {
|
| const double err_correction_factor = calc_correction_factor(err_per_mb,
|
| ERR_DIVISOR, 0.5, 0.90, q);
|
| - const int bits_per_mb_at_this_q = vp9_rc_bits_per_mb(INTER_FRAME, q,
|
| - err_correction_factor);
|
| + const int bits_per_mb_at_this_q =
|
| + vp9_rc_bits_per_mb(INTER_FRAME, q, (err_correction_factor * speed_term));
|
| if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
|
| break;
|
| }
|
| @@ -897,11 +939,19 @@
|
| extern void vp9_new_framerate(VP9_COMP *cpi, double framerate);
|
|
|
| void vp9_init_second_pass(VP9_COMP *cpi) {
|
| + SVC *const svc = &cpi->svc;
|
| FIRSTPASS_STATS this_frame;
|
| - FIRSTPASS_STATS *start_pos;
|
| - struct twopass_rc *const twopass = &cpi->twopass;
|
| + const FIRSTPASS_STATS *start_pos;
|
| + struct twopass_rc *twopass = &cpi->twopass;
|
| const VP9_CONFIG *const oxcf = &cpi->oxcf;
|
| + const int is_spatial_svc = (svc->number_spatial_layers > 1) &&
|
| + (svc->number_temporal_layers == 1);
|
| + double frame_rate;
|
|
|
| + if (is_spatial_svc) {
|
| + twopass = &svc->layer_context[svc->spatial_layer_id].twopass;
|
| + }
|
| +
|
| zero_stats(&twopass->total_stats);
|
| zero_stats(&twopass->total_left_stats);
|
|
|
| @@ -911,30 +961,44 @@
|
| twopass->total_stats = *twopass->stats_in_end;
|
| twopass->total_left_stats = twopass->total_stats;
|
|
|
| + frame_rate = 10000000.0 * twopass->total_stats.count /
|
| + twopass->total_stats.duration;
|
| // Each frame can have a different duration, as the frame rate in the source
|
| // isn't guaranteed to be constant. The frame rate prior to the first frame
|
| // encoded in the second pass is a guess. However, the sum duration is not.
|
| // It is calculated based on the actual durations of all frames from the
|
| // first pass.
|
| - vp9_new_framerate(cpi, 10000000.0 * twopass->total_stats.count /
|
| - twopass->total_stats.duration);
|
|
|
| + if (is_spatial_svc) {
|
| + vp9_update_spatial_layer_framerate(cpi, frame_rate);
|
| + twopass->bits_left =
|
| + (int64_t)(twopass->total_stats.duration *
|
| + svc->layer_context[svc->spatial_layer_id].target_bandwidth /
|
| + 10000000.0);
|
| + } else {
|
| + vp9_new_framerate(cpi, frame_rate);
|
| + twopass->bits_left = (int64_t)(twopass->total_stats.duration *
|
| + oxcf->target_bandwidth / 10000000.0);
|
| + }
|
| +
|
| cpi->output_framerate = oxcf->framerate;
|
| - twopass->bits_left = (int64_t)(twopass->total_stats.duration *
|
| - oxcf->target_bandwidth / 10000000.0);
|
|
|
| // Calculate a minimum intra value to be used in determining the IIratio
|
| // scores used in the second pass. We have this minimum to make sure
|
| // that clips that are static but "low complexity" in the intra domain
|
| // are still boosted appropriately for KF/GF/ARF.
|
| - twopass->kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
|
| - twopass->gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs;
|
| + if (!is_spatial_svc) {
|
| + // We don't know the number of MBs for each layer at this point.
|
| + // So we will do it later.
|
| + twopass->kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
|
| + twopass->gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs;
|
| + }
|
|
|
| // 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.
|
| + // Scan the first pass file and calculate an average Intra / Inter error
|
| + // score ratio for the sequence.
|
| {
|
| double sum_iiratio = 0.0;
|
| start_pos = twopass->stats_in;
|
| @@ -993,8 +1057,8 @@
|
| // 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(VP9_COMP *cpi, int frame_interval,
|
| - int still_interval,
|
| +static int detect_transition_to_still(struct twopass_rc *twopass,
|
| + int frame_interval, int still_interval,
|
| double loop_decay_rate,
|
| double last_decay_rate) {
|
| int trans_to_still = 0;
|
| @@ -1006,19 +1070,19 @@
|
| loop_decay_rate >= 0.999 &&
|
| last_decay_rate < 0.9) {
|
| int j;
|
| - FIRSTPASS_STATS *position = cpi->twopass.stats_in;
|
| + const FIRSTPASS_STATS *position = twopass->stats_in;
|
| FIRSTPASS_STATS tmp_next_frame;
|
|
|
| // Look ahead a few frames to see if static condition persists...
|
| for (j = 0; j < still_interval; ++j) {
|
| - if (EOF == input_stats(&cpi->twopass, &tmp_next_frame))
|
| + if (EOF == input_stats(twopass, &tmp_next_frame))
|
| break;
|
|
|
| if (tmp_next_frame.pcnt_inter - tmp_next_frame.pcnt_motion < 0.999)
|
| break;
|
| }
|
|
|
| - reset_fpf_position(&cpi->twopass, position);
|
| + reset_fpf_position(twopass, position);
|
|
|
| // Only if it does do we signal a transition to still.
|
| if (j == still_interval)
|
| @@ -1340,9 +1404,11 @@
|
|
|
| // 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;
|
| + VP9_CONFIG *const oxcf = &cpi->oxcf;
|
| + struct twopass_rc *const twopass = &cpi->twopass;
|
| FIRSTPASS_STATS next_frame = { 0 };
|
| - FIRSTPASS_STATS *start_pos;
|
| - struct twopass_rc *const twopass = &cpi->twopass;
|
| + const FIRSTPASS_STATS *start_pos;
|
| int i;
|
| double boost_score = 0.0;
|
| double old_boost_score = 0.0;
|
| @@ -1361,16 +1427,14 @@
|
| double mv_in_out_accumulator = 0.0;
|
| double abs_mv_in_out_accumulator = 0.0;
|
| double mv_ratio_accumulator_thresh;
|
| - const int max_bits = frame_max_bits(cpi); // Max bits for a single frame.
|
| + // Max bits for a single frame.
|
| + const int max_bits = frame_max_bits(rc, oxcf);
|
| + unsigned int allow_alt_ref = oxcf->play_alternate && oxcf->lag_in_frames;
|
|
|
| - unsigned int allow_alt_ref = cpi->oxcf.play_alternate &&
|
| - cpi->oxcf.lag_in_frames;
|
| -
|
| int f_boost = 0;
|
| int b_boost = 0;
|
| int flash_detected;
|
| int active_max_gf_interval;
|
| - RATE_CONTROL *const rc = &cpi->rc;
|
|
|
| twopass->gf_group_bits = 0;
|
|
|
| @@ -1407,7 +1471,7 @@
|
| active_max_gf_interval = rc->max_gf_interval;
|
|
|
| i = 0;
|
| - while (i < twopass->static_scene_max_gf_interval && i < rc->frames_to_key) {
|
| + while (i < rc->static_scene_max_gf_interval && i < rc->frames_to_key) {
|
| ++i;
|
|
|
| // Accumulate error score of frames in this gf group.
|
| @@ -1442,7 +1506,7 @@
|
|
|
| // Break clause to detect very still sections after motion. For example,
|
| // a static image after a fade or other transition.
|
| - if (detect_transition_to_still(cpi, i, 5, loop_decay_rate,
|
| + if (detect_transition_to_still(twopass, i, 5, loop_decay_rate,
|
| last_loop_decay_rate)) {
|
| allow_alt_ref = 0;
|
| break;
|
| @@ -1581,8 +1645,8 @@
|
|
|
| // Calculate the bits to be allocated to the group as a whole.
|
| if (twopass->kf_group_bits > 0 && twopass->kf_group_error_left > 0) {
|
| - twopass->gf_group_bits = (int64_t)(cpi->twopass.kf_group_bits *
|
| - (gf_group_err / cpi->twopass.kf_group_error_left));
|
| + twopass->gf_group_bits = (int64_t)(twopass->kf_group_bits *
|
| + (gf_group_err / twopass->kf_group_error_left));
|
| } else {
|
| twopass->gf_group_bits = 0;
|
| }
|
| @@ -1671,11 +1735,7 @@
|
| {
|
| // Adjust KF group bits and error remaining.
|
| twopass->kf_group_error_left -= (int64_t)gf_group_err;
|
| - twopass->kf_group_bits -= twopass->gf_group_bits;
|
|
|
| - if (twopass->kf_group_bits < 0)
|
| - twopass->kf_group_bits = 0;
|
| -
|
| // If this is an arf update we want to remove the score for the overlay
|
| // frame at the end which will usually be very cheap to code.
|
| // The overlay frame has already, in effect, been coded so we want to spread
|
| @@ -1691,11 +1751,6 @@
|
| twopass->gf_group_error_left = (int64_t)gf_group_err;
|
| }
|
|
|
| - twopass->gf_group_bits -= twopass->gf_bits;
|
| -
|
| - if (twopass->gf_group_bits < 0)
|
| - twopass->gf_group_bits = 0;
|
| -
|
| // This condition could fail if there are two kfs very close together
|
| // despite MIN_GF_INTERVAL and would cause a divide by 0 in the
|
| // calculation of alt_extra_bits.
|
| @@ -1704,8 +1759,9 @@
|
|
|
| if (boost >= 150) {
|
| const int pct_extra = MIN(20, (boost - 100) / 50);
|
| - const int alt_extra_bits = (int)((twopass->gf_group_bits * pct_extra) /
|
| - 100);
|
| + const int alt_extra_bits = (int)((
|
| + MAX(twopass->gf_group_bits - twopass->gf_bits, 0) *
|
| + pct_extra) / 100);
|
| twopass->gf_group_bits -= alt_extra_bits;
|
| }
|
| }
|
| @@ -1734,40 +1790,36 @@
|
|
|
| // 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 modified_err;
|
| double err_fraction;
|
| - const int max_bits = frame_max_bits(cpi); // Max for a single frame.
|
|
|
| - // Calculate modified prediction error used in bit allocation.
|
| - modified_err = calculate_modified_err(cpi, this_frame);
|
| -
|
| - if (cpi->twopass.gf_group_error_left > 0)
|
| + if (twopass->gf_group_error_left > 0)
|
| // What portion of the remaining GF group error is used by this frame.
|
| - err_fraction = modified_err / cpi->twopass.gf_group_error_left;
|
| + 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)cpi->twopass.gf_group_bits * err_fraction);
|
| + 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)cpi->twopass.gf_group_bits));
|
| + MIN(max_bits, (int)twopass->gf_group_bits));
|
|
|
| // Adjust error and bits remaining.
|
| - cpi->twopass.gf_group_error_left -= (int64_t)modified_err;
|
| - cpi->twopass.gf_group_bits -= target_frame_size;
|
| + twopass->gf_group_error_left -= (int64_t)modified_err;
|
|
|
| - if (cpi->twopass.gf_group_bits < 0)
|
| - cpi->twopass.gf_group_bits = 0;
|
| -
|
| // Per frame bit target for this frame.
|
| vp9_rc_set_frame_target(cpi, target_frame_size);
|
| }
|
|
|
| -static int test_candidate_kf(VP9_COMP *cpi,
|
| +static int test_candidate_kf(struct twopass_rc *twopass,
|
| const FIRSTPASS_STATS *last_frame,
|
| const FIRSTPASS_STATS *this_frame,
|
| const FIRSTPASS_STATS *next_frame) {
|
| @@ -1788,19 +1840,12 @@
|
| ((next_frame->intra_error /
|
| DOUBLE_DIVIDE_CHECK(next_frame->coded_error)) > 3.5))))) {
|
| int i;
|
| - FIRSTPASS_STATS *start_pos;
|
| -
|
| - FIRSTPASS_STATS local_next_frame;
|
| -
|
| + const FIRSTPASS_STATS *start_pos = twopass->stats_in;
|
| + FIRSTPASS_STATS local_next_frame = *next_frame;
|
| double boost_score = 0.0;
|
| double old_boost_score = 0.0;
|
| double decay_accumulator = 1.0;
|
|
|
| - local_next_frame = *next_frame;
|
| -
|
| - // Note the starting file position so we can reset to it.
|
| - start_pos = cpi->twopass.stats_in;
|
| -
|
| // Examine how well the key frame predicts subsequent frames.
|
| for (i = 0; i < 16; ++i) {
|
| double next_iiratio = (IIKFACTOR1 * local_next_frame.intra_error /
|
| @@ -1832,7 +1877,7 @@
|
| old_boost_score = boost_score;
|
|
|
| // Get the next frame details
|
| - if (EOF == input_stats(&cpi->twopass, &local_next_frame))
|
| + if (EOF == input_stats(twopass, &local_next_frame))
|
| break;
|
| }
|
|
|
| @@ -1842,7 +1887,7 @@
|
| is_viable_kf = 1;
|
| } else {
|
| // Reset the file position
|
| - reset_fpf_position(&cpi->twopass, start_pos);
|
| + reset_fpf_position(twopass, start_pos);
|
|
|
| is_viable_kf = 0;
|
| }
|
| @@ -1853,28 +1898,21 @@
|
|
|
| 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;
|
| + const FIRSTPASS_STATS first_frame = *this_frame;
|
| + const FIRSTPASS_STATS *start_position = twopass->stats_in;
|
| + FIRSTPASS_STATS next_frame;
|
| FIRSTPASS_STATS last_frame;
|
| - FIRSTPASS_STATS first_frame;
|
| - FIRSTPASS_STATS next_frame;
|
| - FIRSTPASS_STATS *start_position;
|
| -
|
| double decay_accumulator = 1.0;
|
| double zero_motion_accumulator = 1.0;
|
| - double boost_score = 0;
|
| - double loop_decay_rate;
|
| -
|
| + double boost_score = 0.0;
|
| double kf_mod_err = 0.0;
|
| double kf_group_err = 0.0;
|
| double recent_loop_decay[8] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
|
|
|
| - RATE_CONTROL *const rc = &cpi->rc;
|
| - struct twopass_rc *const twopass = &cpi->twopass;
|
| -
|
| vp9_zero(next_frame);
|
|
|
| - vp9_clear_system_state();
|
| -
|
| - start_position = twopass->stats_in;
|
| cpi->common.frame_type = KEY_FRAME;
|
|
|
| // Is this a forced key frame by interval.
|
| @@ -1888,9 +1926,6 @@
|
|
|
| rc->frames_to_key = 1;
|
|
|
| - // Take a copy of the initial frame details.
|
| - first_frame = *this_frame;
|
| -
|
| twopass->kf_group_bits = 0; // Total bits available to kf group
|
| twopass->kf_group_error_left = 0; // Group modified error score.
|
|
|
| @@ -1909,8 +1944,10 @@
|
| // Provided that we are not at the end of the file...
|
| if (cpi->oxcf.auto_key &&
|
| lookup_next_frame_stats(twopass, &next_frame) != EOF) {
|
| + double loop_decay_rate;
|
| +
|
| // Check for a scene cut.
|
| - if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
|
| + if (test_candidate_kf(twopass, &last_frame, this_frame, &next_frame))
|
| break;
|
|
|
| // How fast is the prediction quality decaying?
|
| @@ -1926,7 +1963,7 @@
|
|
|
| // Special check for transition or high motion followed by a
|
| // static scene.
|
| - if (detect_transition_to_still(cpi, i, cpi->key_frame_frequency - i,
|
| + if (detect_transition_to_still(twopass, i, cpi->key_frame_frequency - i,
|
| loop_decay_rate, decay_accumulator))
|
| break;
|
|
|
| @@ -1949,13 +1986,10 @@
|
| // is between 1x and 2x.
|
| if (cpi->oxcf.auto_key &&
|
| rc->frames_to_key > (int)cpi->key_frame_frequency) {
|
| - FIRSTPASS_STATS tmp_frame;
|
| + FIRSTPASS_STATS tmp_frame = first_frame;
|
|
|
| rc->frames_to_key /= 2;
|
|
|
| - // Copy first frame details.
|
| - tmp_frame = first_frame;
|
| -
|
| // Reset to the start of the group.
|
| reset_fpf_position(twopass, start_position);
|
|
|
| @@ -1963,10 +1997,7 @@
|
|
|
| // Rescan to get the correct error data for the forced kf group.
|
| for (i = 0; i < rc->frames_to_key; ++i) {
|
| - // Accumulate kf group errors.
|
| kf_group_err += calculate_modified_err(cpi, &tmp_frame);
|
| -
|
| - // Load the next frame's stats.
|
| input_stats(twopass, &tmp_frame);
|
| }
|
| rc->next_key_frame_forced = 1;
|
| @@ -1985,7 +2016,7 @@
|
| // Calculate the number of bits that should be assigned to the kf group.
|
| if (twopass->bits_left > 0 && twopass->modified_error_left > 0.0) {
|
| // Maximum number of bits for a single normal frame (not key frame).
|
| - int max_bits = frame_max_bits(cpi);
|
| + const int max_bits = frame_max_bits(rc, &cpi->oxcf);
|
|
|
| // Maximum number of bits allocated to the key frame group.
|
| int64_t max_grp_bits;
|
| @@ -2012,20 +2043,19 @@
|
|
|
| // Scan through the kf group collating various stats.
|
| for (i = 0; i < rc->frames_to_key; ++i) {
|
| - double r;
|
| -
|
| if (EOF == input_stats(twopass, &next_frame))
|
| break;
|
|
|
| // Monitor for static sections.
|
| if ((next_frame.pcnt_inter - next_frame.pcnt_motion) <
|
| - zero_motion_accumulator) {
|
| - zero_motion_accumulator =
|
| - (next_frame.pcnt_inter - next_frame.pcnt_motion);
|
| + zero_motion_accumulator) {
|
| + zero_motion_accumulator = (next_frame.pcnt_inter -
|
| + next_frame.pcnt_motion);
|
| }
|
|
|
| // For the first few frames collect data to decide kf boost.
|
| if (i <= (rc->max_gf_interval * 2)) {
|
| + double r;
|
| if (next_frame.intra_error > twopass->kf_intra_err_min)
|
| r = (IIKFACTOR2 * next_frame.intra_error /
|
| DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
|
| @@ -2038,10 +2068,10 @@
|
|
|
| // How fast is prediction quality decaying.
|
| if (!detect_flash(twopass, 0)) {
|
| - loop_decay_rate = get_prediction_decay_rate(&cpi->common, &next_frame);
|
| + const double loop_decay_rate = get_prediction_decay_rate(&cpi->common,
|
| + &next_frame);
|
| decay_accumulator *= loop_decay_rate;
|
| - decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
|
| - ? MIN_DECAY_FACTOR : decay_accumulator;
|
| + decay_accumulator = MAX(decay_accumulator, MIN_DECAY_FACTOR);
|
| }
|
|
|
| boost_score += (decay_accumulator * r);
|
| @@ -2072,7 +2102,6 @@
|
| if (1) {
|
| int kf_boost = (int)boost_score;
|
| int allocation_chunks;
|
| - int alt_kf_bits;
|
|
|
| if (kf_boost < (rc->frames_to_key * 3))
|
| kf_boost = (rc->frames_to_key * 3);
|
| @@ -2106,14 +2135,12 @@
|
|
|
| // Prevent overflow.
|
| if (kf_boost > 1028) {
|
| - int divisor = kf_boost >> 10;
|
| + const int divisor = kf_boost >> 10;
|
| kf_boost /= divisor;
|
| allocation_chunks /= divisor;
|
| }
|
|
|
| - twopass->kf_group_bits = (twopass->kf_group_bits < 0) ? 0
|
| - : twopass->kf_group_bits;
|
| -
|
| + twopass->kf_group_bits = MAX(0, twopass->kf_group_bits);
|
| // Calculate the number of bits to be spent on the key frame.
|
| twopass->kf_bits = (int)((double)kf_boost *
|
| ((double)twopass->kf_group_bits / allocation_chunks));
|
| @@ -2123,11 +2150,11 @@
|
| // then use an alternate calculation based on the kf error score
|
| // which should give a smaller key frame.
|
| if (kf_mod_err < kf_group_err / rc->frames_to_key) {
|
| - double alt_kf_grp_bits = ((double)twopass->bits_left *
|
| + double alt_kf_grp_bits = ((double)twopass->bits_left *
|
| (kf_mod_err * (double)rc->frames_to_key) /
|
| DOUBLE_DIVIDE_CHECK(twopass->modified_error_left));
|
|
|
| - alt_kf_bits = (int)((double)kf_boost *
|
| + const int alt_kf_bits = (int)((double)kf_boost *
|
| (alt_kf_grp_bits / (double)allocation_chunks));
|
|
|
| if (twopass->kf_bits > alt_kf_bits)
|
| @@ -2136,12 +2163,11 @@
|
| // Else if it is much harder than other frames in the group make sure
|
| // it at least receives an allocation in keeping with its relative
|
| // error score.
|
| - alt_kf_bits = (int)((double)twopass->bits_left * (kf_mod_err /
|
| + const int alt_kf_bits = (int)((double)twopass->bits_left * (kf_mod_err /
|
| DOUBLE_DIVIDE_CHECK(twopass->modified_error_left)));
|
|
|
| - if (alt_kf_bits > twopass->kf_bits) {
|
| + if (alt_kf_bits > twopass->kf_bits)
|
| twopass->kf_bits = alt_kf_bits;
|
| - }
|
| }
|
| twopass->kf_group_bits -= twopass->kf_bits;
|
| // Per frame bit target for this frame.
|
| @@ -2161,7 +2187,7 @@
|
| VP9_COMMON *const cm = &cpi->common;
|
| if (!cpi->refresh_alt_ref_frame &&
|
| (cm->current_video_frame == 0 ||
|
| - cm->frame_flags & FRAMEFLAGS_KEY)) {
|
| + (cm->frame_flags & FRAMEFLAGS_KEY))) {
|
| cm->frame_type = KEY_FRAME;
|
| } else {
|
| cm->frame_type = INTER_FRAME;
|
| @@ -2174,15 +2200,25 @@
|
| VP9_COMMON *const cm = &cpi->common;
|
| RATE_CONTROL *const rc = &cpi->rc;
|
| struct twopass_rc *const twopass = &cpi->twopass;
|
| - const int frames_left = (int)(twopass->total_stats.count -
|
| - cm->current_video_frame);
|
| + int frames_left;
|
| FIRSTPASS_STATS this_frame;
|
| FIRSTPASS_STATS this_frame_copy;
|
|
|
| double this_frame_intra_error;
|
| double this_frame_coded_error;
|
| int target;
|
| + LAYER_CONTEXT *lc = NULL;
|
| + int is_spatial_svc = (cpi->use_svc && cpi->svc.number_temporal_layers == 1);
|
|
|
| + if (is_spatial_svc) {
|
| + lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
|
| + frames_left = (int)(twopass->total_stats.count -
|
| + lc->current_video_frame_in_layer);
|
| + } else {
|
| + frames_left = (int)(twopass->total_stats.count -
|
| + cm->current_video_frame);
|
| + }
|
| +
|
| if (!twopass->stats_in)
|
| return;
|
|
|
| @@ -2194,9 +2230,15 @@
|
|
|
| vp9_clear_system_state();
|
|
|
| + if (is_spatial_svc && twopass->kf_intra_err_min == 0) {
|
| + twopass->kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
|
| + twopass->gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs;
|
| + }
|
| +
|
| if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
|
| twopass->active_worst_quality = cpi->oxcf.cq_level;
|
| - } else if (cm->current_video_frame == 0) {
|
| + } else if (cm->current_video_frame == 0 ||
|
| + (is_spatial_svc && lc->current_video_frame_in_layer == 0)) {
|
| // Special case code for first frame.
|
| const int section_target_bandwidth = (int)(twopass->bits_left /
|
| frames_left);
|
| @@ -2219,6 +2261,11 @@
|
| // 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 (cpi->use_svc && cpi->svc.number_temporal_layers == 1 &&
|
| + cpi->svc.spatial_layer_id > 0) {
|
| + cm->frame_type = INTER_FRAME;
|
| + }
|
| } else {
|
| cm->frame_type = INTER_FRAME;
|
| }
|
| @@ -2278,23 +2325,24 @@
|
| subtract_stats(&twopass->total_left_stats, &this_frame);
|
| }
|
|
|
| -void vp9_twopass_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
|
| +void vp9_twopass_postencode_update(VP9_COMP *cpi) {
|
| #ifdef DISABLE_RC_LONG_TERM_MEM
|
| - cpi->twopass.bits_left -= cpi->rc.this_frame_target;
|
| + const uint64_t bits_used = cpi->rc.this_frame_target;
|
| #else
|
| - cpi->twopass.bits_left -= 8 * bytes_used;
|
| + const uint64_t bits_used = cpi->rc.projected_frame_size;
|
| +#endif
|
| + cpi->twopass.bits_left -= bits_used;
|
| + cpi->twopass.bits_left = MAX(cpi->twopass.bits_left, 0);
|
| // Update bits left to the kf and gf groups to account for overshoot or
|
| // undershoot on these frames.
|
| - if (cm->frame_type == KEY_FRAME) {
|
| - cpi->twopass.kf_group_bits += cpi->rc.this_frame_target -
|
| - cpi->rc.projected_frame_size;
|
| -
|
| - cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0);
|
| - } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) {
|
| - cpi->twopass.gf_group_bits += cpi->rc.this_frame_target -
|
| - cpi->rc.projected_frame_size;
|
| -
|
| + if (cpi->common.frame_type == KEY_FRAME) {
|
| + // 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;
|
| + } else {
|
| + 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);
|
| }
|
| -#endif
|
| + cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0);
|
| }
|
|
|