}
if (rv && search_subpel) {
- int subpel_force_stop = cpi->sf.mv.subpel_force_stop;
- if (use_base_mv && cpi->sf.base_mv_aggressive) subpel_force_stop = 2;
+ SUBPEL_FORCE_STOP subpel_force_stop = cpi->sf.mv.subpel_force_stop;
+ if (use_base_mv && cpi->sf.base_mv_aggressive) subpel_force_stop = HALF_PEL;
if (cpi->sf.mv.enable_adaptive_subpel_force_stop) {
- int mv_thresh = cpi->sf.mv.adapt_subpel_force_stop.mv_thresh;
+ const int mv_thresh = cpi->sf.mv.adapt_subpel_force_stop.mv_thresh;
if (abs(tmp_mv->as_mv.row) >= mv_thresh ||
abs(tmp_mv->as_mv.col) >= mv_thresh)
subpel_force_stop = cpi->sf.mv.adapt_subpel_force_stop.force_stop_above;
x, &tmp_mv->as_mv, &ref_mv, cpi->common.allow_high_precision_mv,
x->errorperbit, &cpi->fn_ptr[bsize], subpel_force_stop,
cpi->sf.mv.subpel_search_level, cond_cost_list(cpi, cost_list),
- x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref], NULL, 0, 0);
+ x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref], NULL, 0, 0,
+ cpi->sf.use_accurate_subpel_search);
*rate_mv = vp9_mv_bit_cost(&tmp_mv->as_mv, &ref_mv, x->nmvjointcost,
x->mvcost, MV_COST_WEIGHT);
}
const int bw = 4 * num_4x4_w;
const int bh = 4 * num_4x4_h;
-#if CONFIG_VP9_HIGHBITDEPTH
- // TODO(jingning): Implement the high bit-depth Hadamard transforms and
- // remove this check condition.
- // TODO(marpan): Use this path (model_rd) for 8bit under certain conditions
- // for now, as the vp9_quantize_fp below for highbitdepth build is slow.
- if (xd->bd != 8 ||
- (cpi->oxcf.speed > 5 && cpi->common.frame_type != KEY_FRAME &&
- bsize < BLOCK_32X32)) {
- unsigned int var_y, sse_y;
- (void)tx_size;
- if (!rd_computed)
- model_rd_for_sb_y(cpi, bsize, x, xd, &this_rdc->rate, &this_rdc->dist,
- &var_y, &sse_y);
- *sse = INT_MAX;
- *skippable = 0;
- return;
- }
-#endif
-
if (cpi->sf.use_simple_block_yrd && cpi->common.frame_type != KEY_FRAME &&
(bsize < BLOCK_32X32 ||
(cpi->use_svc &&
// Skipping threshold for dc.
unsigned int thresh_dc;
int motion_low = 1;
+
if (cpi->use_svc && ref_frame == GOLDEN_FRAME) return;
if (mi->mv[0].as_mv.row > 64 || mi->mv[0].as_mv.row < -64 ||
mi->mv[0].as_mv.col > 64 || mi->mv[0].as_mv.col < -64)
int mi_row, int mi_col, PRED_BUFFER *tmp,
BLOCK_SIZE bsize, int reuse_inter_pred,
PRED_BUFFER **this_mode_pred, unsigned int *var_y,
- unsigned int *sse_y) {
+ unsigned int *sse_y, int force_smooth_filter) {
MACROBLOCKD *const xd = &x->e_mbd;
MODE_INFO *const mi = xd->mi[0];
struct macroblockd_plane *const pd = &xd->plane[0];
INTERP_FILTER best_filter = SWITCHABLE, filter;
PRED_BUFFER *current_pred = *this_mode_pred;
uint8_t skip_txfm = SKIP_TXFM_NONE;
-
- for (filter = EIGHTTAP; filter <= EIGHTTAP_SMOOTH; ++filter) {
+ INTERP_FILTER filter_start = force_smooth_filter ? EIGHTTAP_SMOOTH : EIGHTTAP;
+ for (filter = filter_start; filter <= EIGHTTAP_SMOOTH; ++filter) {
int64_t cost;
mi->interp_filter = filter;
vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
cpi->common.allow_high_precision_mv, x->errorperbit,
&cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
cpi->sf.mv.subpel_search_level, cond_cost_list(cpi, cost_list),
- x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref_frame], NULL, 0, 0);
+ x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref_frame], NULL, 0, 0,
+ cpi->sf.use_accurate_subpel_search);
} else if (svc->use_base_mv && svc->spatial_layer_id) {
if (frame_mv[NEWMV][ref_frame].as_int != INVALID_MV) {
const int pre_stride = xd->plane[0].pre[0].stride;
unsigned int sse_zeromv_normalized = UINT_MAX;
unsigned int best_sse_sofar = UINT_MAX;
int gf_temporal_ref = 0;
+ int force_test_gf_zeromv = 0;
#if CONFIG_VP9_TEMPORAL_DENOISING
VP9_PICKMODE_CTX_DEN ctx_den;
int64_t zero_last_cost_orig = INT64_MAX;
int svc_mv_row = 0;
int no_scaling = 0;
unsigned int thresh_svc_skip_golden = 500;
+ unsigned int thresh_skip_golden = 500;
+ int force_smooth_filter =
+ (cpi->oxcf.speed >= 8 && cm->width * cm->height <= 320 * 240 &&
+ cm->base_qindex >= 200)
+ ? 1
+ : 0;
int scene_change_detected =
cpi->rc.high_source_sad ||
(cpi->use_svc && cpi->svc.high_source_sad_superframe);
init_best_pickmode(&best_pickmode);
+ x->encode_breakout = seg->enabled
+ ? cpi->segment_encode_breakout[mi->segment_id]
+ : cpi->encode_breakout;
+
x->source_variance = UINT_MAX;
if (cpi->sf.default_interp_filter == BILINEAR) {
best_pickmode.best_pred_filter = BILINEAR;
if (!cpi->use_svc ||
(svc->use_gf_temporal_ref_current_layer &&
!svc->layer_context[svc->temporal_layer_id].is_key_frame)) {
+ struct scale_factors *const sf_last = &cm->frame_refs[LAST_FRAME - 1].sf;
+ struct scale_factors *const sf_golden =
+ &cm->frame_refs[GOLDEN_FRAME - 1].sf;
gf_temporal_ref = 1;
- if (cpi->rc.avg_frame_low_motion > 70)
- thresh_svc_skip_golden = 500;
- else
- thresh_svc_skip_golden = 0;
+ // For temporal long term prediction, check that the golden reference
+ // is same scale as last reference, otherwise disable.
+ if ((sf_last->x_scale_fp != sf_golden->x_scale_fp) ||
+ (sf_last->y_scale_fp != sf_golden->y_scale_fp)) {
+ gf_temporal_ref = 0;
+ } else {
+ if (cpi->rc.avg_frame_low_motion > 70)
+ thresh_svc_skip_golden = 500;
+ else
+ thresh_svc_skip_golden = 0;
+ }
}
init_ref_frame_cost(cm, xd, ref_frame_cost);
x->source_variance =
vp9_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
- if (cpi->oxcf.content == VP9E_CONTENT_SCREEN && mi->segment_id > 0 &&
+ if (cpi->oxcf.content == VP9E_CONTENT_SCREEN &&
+ cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && mi->segment_id > 0 &&
x->zero_temp_sad_source && x->source_variance == 0) {
mi->segment_id = 0;
vp9_init_plane_quantizers(cpi, x);
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0) {
- if (cpi->use_svc) {
- int layer =
- LAYER_IDS_TO_IDX(svc->spatial_layer_id, svc->temporal_layer_id,
- svc->number_temporal_layers);
- LAYER_CONTEXT *lc = &svc->layer_context[layer];
- denoise_svc_pickmode = denoise_svc(cpi) && !lc->is_key_frame;
- }
+ if (cpi->use_svc) denoise_svc_pickmode = vp9_denoise_svc_non_key(cpi);
if (cpi->denoiser.denoising_level > kDenLowLow && denoise_svc_pickmode)
vp9_denoiser_reset_frame_stats(ctx);
}
flag_svc_subpel = 1;
}
+ // For SVC with quality layers, when QP of lower layer is lower
+ // than current layer: force check of GF-ZEROMV before early exit
+ // due to skip flag.
+ if (svc->spatial_layer_id > 0 && no_scaling &&
+ (cpi->ref_frame_flags & flag_list[GOLDEN_FRAME]) &&
+ cm->base_qindex > svc->lower_layer_qindex + 10)
+ force_test_gf_zeromv = 1;
+
for (idx = 0; idx < num_inter_modes + comp_modes; ++idx) {
int rate_mv = 0;
int mode_rd_thresh;
if (segfeature_active(seg, mi->segment_id, SEG_LVL_REF_FRAME)) continue;
}
- // For SVC, skip the golden (spatial) reference search if sse of zeromv_last
- // is below threshold.
- if (cpi->use_svc && ref_frame == GOLDEN_FRAME &&
- sse_zeromv_normalized < thresh_svc_skip_golden)
+ // For CBR mode: skip the golden reference search if sse of zeromv_last is
+ // below threshold.
+ if (ref_frame == GOLDEN_FRAME && cpi->oxcf.rc_mode == VPX_CBR &&
+ ((cpi->use_svc && sse_zeromv_normalized < thresh_svc_skip_golden) ||
+ (!cpi->use_svc && sse_zeromv_normalized < thresh_skip_golden)))
continue;
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) continue;
- if (sf->short_circuit_flat_blocks && x->source_variance == 0 &&
- (frame_mv[this_mode][ref_frame].as_int != 0 ||
- (cpi->oxcf.content == VP9E_CONTENT_SCREEN && !svc->spatial_layer_id &&
- !x->zero_temp_sad_source))) {
- continue;
+ // For screen content. If zero_temp_sad source is computed: skip
+ // non-zero motion check for stationary blocks. If the superblock is
+ // non-stationary then for flat blocks skip the zero last check (keep golden
+ // as it may be inter-layer reference). Otherwise (if zero_temp_sad_source
+ // is not computed) skip non-zero motion check for flat blocks.
+ // TODO(marpan): Compute zero_temp_sad_source per coding block.
+ if (cpi->oxcf.content == VP9E_CONTENT_SCREEN) {
+ if (cpi->compute_source_sad_onepass && cpi->sf.use_source_sad) {
+ if ((frame_mv[this_mode][ref_frame].as_int != 0 &&
+ x->zero_temp_sad_source) ||
+ (frame_mv[this_mode][ref_frame].as_int == 0 &&
+ x->source_variance == 0 && ref_frame == LAST_FRAME &&
+ !x->zero_temp_sad_source))
+ continue;
+ } else if (frame_mv[this_mode][ref_frame].as_int != 0 &&
+ x->source_variance == 0) {
+ continue;
+ }
}
if (!(cpi->sf.inter_mode_mask[bsize] & (1 << this_mode))) continue;
(((mi->mv[0].as_mv.row | mi->mv[0].as_mv.col) & 0x07) != 0)) {
rd_computed = 1;
search_filter_ref(cpi, x, &this_rdc, mi_row, mi_col, tmp, bsize,
- reuse_inter_pred, &this_mode_pred, &var_y, &sse_y);
+ reuse_inter_pred, &this_mode_pred, &var_y, &sse_y,
+ force_smooth_filter);
} else {
// For low motion content use x->sb_is_skin in addition to VeryHighSad
// for setting large_block.
&var_y, &sse_y);
}
// Save normalized sse (between current and last frame) for (0, 0) motion.
- if (cpi->use_svc && ref_frame == LAST_FRAME &&
+ if (ref_frame == LAST_FRAME &&
frame_mv[this_mode][ref_frame].as_int == 0) {
sse_zeromv_normalized =
sse_y >> (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
if (reuse_inter_pred) free_pred_buffer(this_mode_pred);
}
- if (x->skip) break;
+ if (x->skip &&
+ (!force_test_gf_zeromv || mode_checked[ZEROMV][GOLDEN_FRAME]))
+ break;
// If early termination flag is 1 and at least 2 modes are checked,
// the mode search is terminated.
- if (best_early_term && idx > 0 && !scene_change_detected) {
+ if (best_early_term && idx > 0 && !scene_change_detected &&
+ (!force_test_gf_zeromv || mode_checked[ZEROMV][GOLDEN_FRAME])) {
x->skip = 1;
break;
}
// Perform intra prediction search, if the best SAD is above a certain
// threshold.
if (best_rdc.rdcost == INT64_MAX ||
+ (cpi->oxcf.content == VP9E_CONTENT_SCREEN && x->source_variance == 0) ||
(scene_change_detected && perform_intra_pred) ||
((!force_skip_low_temp_var || bsize < BLOCK_32X32 ||
x->content_state_sb == kVeryHighSad) &&
const PREDICTION_MODE this_mode = intra_mode_list[i];
THR_MODES mode_index = mode_idx[INTRA_FRAME][mode_offset(this_mode)];
int mode_rd_thresh = rd_threshes[mode_index];
+ // For spatially flat blocks, under short_circuit_flat_blocks flag:
+ // only check DC mode for stationary blocks, otherwise also check
+ // H and V mode.
if (sf->short_circuit_flat_blocks && x->source_variance == 0 &&
- this_mode != DC_PRED) {
+ ((x->zero_temp_sad_source && this_mode != DC_PRED) || i > 2)) {
continue;
}
&cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
cpi->sf.mv.subpel_search_level, cond_cost_list(cpi, cost_list),
x->nmvjointcost, x->mvcost, &dummy_dist,
- &x->pred_sse[ref_frame], NULL, 0, 0);
+ &x->pred_sse[ref_frame], NULL, 0, 0,
+ cpi->sf.use_accurate_subpel_search);
xd->mi[0]->bmi[i].as_mv[0].as_mv = tmp_mv;
} else {