diff --git a/test/datarate_test.cc b/test/datarate_test.cc index 014175981..d7f9148e1 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc @@ -1105,6 +1105,8 @@ class DatarateOnePassCbrSvc mismatch_psnr_ = 0.0; mismatch_nframes_ = 0; denoiser_on_ = 0; + tune_content_ = 0; + base_speed_setting_ = 5; } virtual void BeginPassHook(unsigned int /*pass*/) {} virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, @@ -1115,7 +1117,7 @@ class DatarateOnePassCbrSvc svc_params_.max_quantizers[i] = 63; svc_params_.min_quantizers[i] = 0; } - svc_params_.speed_per_layer[0] = 5; + svc_params_.speed_per_layer[0] = base_speed_setting_; for (i = 1; i < VPX_SS_MAX_LAYERS; ++i) { svc_params_.speed_per_layer[i] = speed_setting_; } @@ -1129,6 +1131,7 @@ class DatarateOnePassCbrSvc encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1)); encoder->Control(VP9E_SET_ROW_MT, 1); encoder->Control(VP8E_SET_STATIC_THRESHOLD, 1); + encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_); } const vpx_rational_t tb = video->timebase(); timebase_ = static_cast(tb.num) / tb.den; @@ -1185,6 +1188,8 @@ class DatarateOnePassCbrSvc double mismatch_psnr_; int mismatch_nframes_; int denoiser_on_; + int tune_content_; + int base_speed_setting_; }; static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg, const vpx_svc_extra_cfg_t *svc_params, @@ -1216,6 +1221,39 @@ static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg, } } +// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1temporal +// layer, with screen content mode on and same speed setting for all layers. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2patialLayersScreenContent1) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 2; + cfg_.ts_number_layers = 1; + cfg_.ts_rate_decimator[0] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 1; + cfg_.temporal_layering_mode = 0; + svc_params_.scaling_factor_num[0] = 144; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 288; + svc_params_.scaling_factor_den[1] = 288; + cfg_.rc_dropframe_thresh = 0; + cfg_.kf_max_dist = 9999; + ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300); + cfg_.rc_target_bitrate = 500; + ResetModel(); + tune_content_ = 1; + base_speed_setting_ = speed_setting_; + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + EXPECT_EQ(static_cast(0), GetMismatchFrames()); +} + // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and // 3 temporal layers. Run CIF clip with 1 thread. TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) { diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index a4dad85d4..cbc53047c 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -1011,7 +1011,8 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile, set_offsets(cpi, tile, x, mi_row, mi_col, BLOCK_64X64); segment_id = xd->mi[0]->segment_id; - if (cpi->sf.use_source_sad && !is_key_frame) { + if (cpi->sf.use_source_sad && cpi->content_state_sb != NULL && + !is_key_frame) { // The sb_offset2 is to make it consistent with the index in the function // vp9_avg_source_sad() in vp9_ratectrl.c. int sb_offset2 = ((cm->mi_cols + 7) >> 3) * (mi_row >> 3) + (mi_col >> 3); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index aba2c115a..dde6f62fc 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -3094,7 +3094,9 @@ static void encode_without_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest) { VP9_COMMON *const cm = &cpi->common; int q = 0, bottom_index = 0, top_index = 0; // Dummy variables. - int compute_source_sad = cpi->sf.use_source_sad; + int compute_source_sad = cpi->sf.use_source_sad || + cpi->oxcf.content == VP9E_CONTENT_SCREEN || + cpi->oxcf.rc_mode == VPX_VBR; vpx_clear_system_state(); @@ -3176,10 +3178,13 @@ static void encode_without_recode_loop(VP9_COMP *cpi, size_t *size, vp9_update_noise_estimate(cpi); + // Compute source_sad if the flag compute_source_sad is set, and + // only for 1 pass realtime speed >= 5 with show_frame = 1. + // TODO(jianj): Look into removing the condition on resize_state, + // and improving these conditions (i.e., better handle SVC case and combine + // them with condition above in compute_source_sad). if (cpi->oxcf.pass == 0 && cpi->oxcf.mode == REALTIME && - cpi->oxcf.speed >= 5 && cpi->resize_state == ORIG && - (cpi->oxcf.content == VP9E_CONTENT_SCREEN || - cpi->oxcf.rc_mode == VPX_VBR || compute_source_sad) && + cpi->oxcf.speed >= 5 && cpi->resize_state == ORIG && compute_source_sad && cm->show_frame) vp9_avg_source_sad(cpi); diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index fb41427ea..d7a0e1aa8 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -2303,7 +2303,7 @@ void vp9_avg_source_sad(VP9_COMP *cpi) { (sbi_row % 2 != 0 && sbi_col % 2 != 0)))) { tmp_sad = cpi->fn_ptr[bsize].sdf(src_y, src_ystride, last_src_y, last_src_ystride); - if (cpi->sf.use_source_sad) { + if (cpi->sf.use_source_sad && cpi->content_state_sb != NULL) { unsigned int tmp_sse; unsigned int tmp_variance = vpx_variance64x64( src_y, src_ystride, last_src_y, last_src_ystride, &tmp_sse);