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