vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, 0);
- vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
+ vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0)) {
die_codec(&codec, "Failed to set SVC");
layer_id.temporal_layer_id);
}
flags = layer_flags[frame_cnt % flag_periodicity];
+ if (layering_mode == 0)
+ flags = 0;
frame_avail = vpx_img_read(&raw, infile);
if (frame_avail)
++rc.layer_input_frames[layer_id.temporal_layer_id];
cm->counts.tx.p8x8[i][j] += counts->tx.p8x8[i][j];
}
+ for (i = 0; i < TX_SIZES; i++)
+ cm->counts.tx.tx_totals[i] += counts->tx.tx_totals[i];
+
for (i = 0; i < SKIP_CONTEXTS; i++)
for (j = 0; j < 2; j++)
cm->counts.skip[i][j] += counts->skip[i][j];
int16_t motion_thresh;
// Rate target ratio to set q delta.
double rate_ratio_qdelta;
+ double low_content_avg;
};
CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) {
}
// Update the actual number of blocks that were applied the segment delta q.
-void vp9_cyclic_refresh_update_actual_count(struct VP9_COMP *const cpi) {
+void vp9_cyclic_refresh_postencode(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
unsigned char *const seg_map = cpi->segmentation_map;
}
}
+// Set golden frame update interval, for non-svc 1 pass CBR mode.
+void vp9_cyclic_refresh_set_golden_update(VP9_COMP *const cpi) {
+ RATE_CONTROL *const rc = &cpi->rc;
+ CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
+ // Set minimum gf_interval for GF update to a multiple (== 2) of refresh
+ // period. Depending on past encoding stats, GF flag may be reset and update
+ // may not occur until next baseline_gf_interval.
+ if (cr->percent_refresh > 0)
+ rc->baseline_gf_interval = 2 * (100 / cr->percent_refresh);
+ else
+ rc->baseline_gf_interval = 20;
+}
+
+// Update some encoding stats (from the just encoded frame), and if the golden
+// reference is to be updated check if we should NOT update the golden ref.
+void vp9_cyclic_refresh_check_golden_update(VP9_COMP *const cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
+ int mi_row, mi_col;
+ double fraction_low = 0.0;
+ int low_content_frame = 0;
+ for (mi_row = 0; mi_row < cm->mi_rows; mi_row++)
+ for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) {
+ if (cr->map[mi_row * cm->mi_cols + mi_col] < 1)
+ low_content_frame++;
+ }
+ fraction_low =
+ (double)low_content_frame / (cm->mi_rows * cm->mi_cols);
+ // Update average.
+ cr->low_content_avg = (fraction_low + 3 * cr->low_content_avg) / 4;
+ if (cpi->refresh_golden_frame == 1) {
+ // Don't update golden reference if the amount of low_content for the
+ // current encoded frame is small, or if the recursive average of the
+ // low_content over the update interval window falls below threshold.
+ if (fraction_low < 0.8 || cr->low_content_avg < 0.7)
+ cpi->refresh_golden_frame = 0;
+ // Reset for next internal.
+ cr->low_content_avg = fraction_low;
+ }
+}
+
// Update the segmentation map, and related quantities: cyclic refresh map,
// refresh sb_index, and target number of blocks to be refreshed.
// The map is set to either 0/CR_SEGMENT_ID_BASE (no refresh) or to
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
struct segmentation *const seg = &cm->seg;
const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc);
+ if (cm->current_video_frame == 0)
+ cr->low_content_avg = 0.0;
// Don't apply refresh on key frame or enhancement layer frames.
if (!apply_cyclic_refresh ||
(cm->frame_type == KEY_FRAME) ||
void vp9_cyclic_refresh_update__map(struct VP9_COMP *const cpi);
// Update the actual number of blocks that were applied the segment delta q.
-void vp9_cyclic_refresh_update_actual_count(struct VP9_COMP *const cpi);
+void vp9_cyclic_refresh_postencode(struct VP9_COMP *const cpi);
+
+// Set golden frame update interval, for non-svc 1 pass CBR mode.
+void vp9_cyclic_refresh_set_golden_update(struct VP9_COMP *cpi);
+
+// Check if we should not update golden reference, based on past refresh stats.
+void vp9_cyclic_refresh_check_golden_update(struct VP9_COMP *const cpi);
// Set/update global/frame level refresh parameters.
void vp9_cyclic_refresh_update_parameters(struct VP9_COMP *const cpi);
if (!is_key_frame) {
MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi;
unsigned int uv_sad;
+ const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
#if GLOBAL_MOTION
- unsigned int y_sad;
+ const YV12_BUFFER_CONFIG *yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
+ unsigned int y_sad, y_sad_g;
BLOCK_SIZE bsize;
+ if (mi_row + 4 < cm->mi_rows && mi_col + 4 < cm->mi_cols)
+ bsize = BLOCK_64X64;
+ else if (mi_row + 4 < cm->mi_rows && mi_col + 4 >= cm->mi_cols)
+ bsize = BLOCK_32X64;
+ else if (mi_row + 4 >= cm->mi_rows && mi_col + 4 < cm->mi_cols)
+ bsize = BLOCK_64X32;
+ else
+ bsize = BLOCK_32X32;
#endif
- const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
assert(yv12 != NULL);
+#if GLOBAL_MOTION
+ if (yv12_g && yv12_g != yv12) {
+ vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
+ &cm->frame_refs[GOLDEN_FRAME - 1].sf);
+ y_sad_g = cpi->fn_ptr[bsize].sdf(x->plane[0].src.buf,
+ x->plane[0].src.stride,
+ xd->plane[0].pre[0].buf,
+ xd->plane[0].pre[0].stride);
+ } else {
+ y_sad_g = UINT_MAX;
+ }
+#endif
vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col,
- &cm->frame_refs[LAST_FRAME - 1].sf);
+ &cm->frame_refs[LAST_FRAME - 1].sf);
mbmi->ref_frame[0] = LAST_FRAME;
mbmi->ref_frame[1] = NONE;
mbmi->sb_type = BLOCK_64X64;
mbmi->mv[0].as_int = 0;
mbmi->interp_filter = BILINEAR;
-
#if GLOBAL_MOTION
- if (mi_row + 4 < cm->mi_rows && mi_col + 4 < cm->mi_cols)
- bsize = BLOCK_64X64;
- else if (mi_row + 4 < cm->mi_rows && mi_col + 4 >= cm->mi_cols)
- bsize = BLOCK_32X64;
- else if (mi_row + 4 >= cm->mi_rows && mi_col + 4 < cm->mi_cols)
- bsize = BLOCK_64X32;
- else
- bsize = BLOCK_32X32;
-
y_sad = vp9_int_pro_motion_estimation(cpi, x, bsize);
- x->pred_mv[LAST_FRAME] = mbmi->mv[0].as_mv;
+ if (y_sad_g < y_sad) {
+ vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
+ &cm->frame_refs[GOLDEN_FRAME - 1].sf);
+ mbmi->ref_frame[0] = GOLDEN_FRAME;
+ mbmi->mv[0].as_int = 0;
+ y_sad = y_sad_g;
+ } else {
+ x->pred_mv[LAST_FRAME] = mbmi->mv[0].as_mv;
+ }
#endif
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_64X64);
// transform / motion compensation build reconstruction frame
vp9_encode_frame(cpi);
+ // Update some stats from cyclic refresh, and check if we should not update
+ // golden reference, for non-SVC 1 pass CBR.
+ if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ cm->frame_type != KEY_FRAME &&
+ !cpi->use_svc &&
+ (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR))
+ vp9_cyclic_refresh_check_golden_update(cpi);
+
// Update the skip mb flag probabilities based on the distribution
// seen in the last encoder iteration.
// update_base_skip_probs(cpi);
TX_SIZE t;
set_ext_overrides(cpi);
-
vp9_clear_system_state();
// Set the arf sign bias for this frame.
++twopass->gf_group.index;
// If the rate control is drifting consider adjustment to min or maxq.
- if ((cpi->oxcf.rc_mode == VPX_VBR) &&
+ if ((cpi->oxcf.rc_mode != VPX_Q) &&
(cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD) &&
!cpi->rc.is_src_frame_alt_ref) {
const int maxq_adj_limit =
rc->worst_quality - twopass->active_worst_quality;
+ const int minq_adj_limit =
+ (cpi->oxcf.rc_mode == VPX_CQ) ? 0 : MINQ_ADJ_LIMIT;
// Undershoot.
if (rc->rate_error_estimate > cpi->oxcf.under_shoot_pct) {
--twopass->extend_maxq;
}
- twopass->extend_minq = clamp(twopass->extend_minq, 0, MINQ_ADJ_LIMIT);
+ twopass->extend_minq = clamp(twopass->extend_minq, 0, minq_adj_limit);
twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit);
}
}
mode_idx[INTRA_FRAME][mbmi->mode];
PREDICTION_MODE this_mode;
for (ref_frame = LAST_FRAME; ref_frame <= GOLDEN_FRAME; ++ref_frame) {
+ if (best_ref_frame != ref_frame) continue;
for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
THR_MODES thr_mode_idx = mode_idx[ref_frame][INTER_OFFSET(this_mode)];
int *freq_fact = &tile_data->thresh_freq_fact[bsize][thr_mode_idx];
// Extension to max or min Q if undershoot or overshoot is outside
// the permitted range.
- if ((cpi->oxcf.rc_mode == VPX_VBR) &&
+ if ((cpi->oxcf.rc_mode != VPX_Q) &&
(cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) {
if (frame_is_intra_only(cm) ||
(!rc->is_src_frame_alt_ref &&
const int qindex = cm->base_qindex;
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled) {
- vp9_cyclic_refresh_update_actual_count(cpi);
+ vp9_cyclic_refresh_postencode(cpi);
}
// Update rate control heuristics
cm->frame_type = INTER_FRAME;
}
if (rc->frames_till_gf_update_due == 0) {
- rc->baseline_gf_interval = DEFAULT_GF_INTERVAL;
+ if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
+ vp9_cyclic_refresh_set_golden_update(cpi);
+ else
+ rc->baseline_gf_interval = DEFAULT_GF_INTERVAL;
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
// NOTE: frames_till_gf_update_due must be <= frames_to_key.
if (rc->frames_till_gf_update_due > rc->frames_to_key)