diff options
-rw-r--r-- | test/datarate_test.cc | 79 | ||||
-rw-r--r-- | vp9/encoder/vp9_encodeframe.c | 9 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 6 | ||||
-rw-r--r-- | vp9/encoder/vp9_mcomp.c | 6 | ||||
-rw-r--r-- | vp9/encoder/vp9_ratectrl.c | 5 | ||||
-rw-r--r-- | vp9/encoder/vp9_speed_features.c | 5 |
6 files changed, 68 insertions, 42 deletions
diff --git a/test/datarate_test.cc b/test/datarate_test.cc index d7f9148e1..ff88e9985 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc @@ -1221,9 +1221,10 @@ 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) { +// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1 +// temporal layer, with screen content mode on and same speed setting for all +// layers. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TLScreenContent1) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1241,7 +1242,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2patialLayersScreenContent1) { 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_.rc_dropframe_thresh = 10; cfg_.kf_max_dist = 9999; ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300); cfg_.rc_target_bitrate = 500; @@ -1256,7 +1257,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2patialLayersScreenContent1) { // 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) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1276,7 +1277,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) { 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 = 10; + cfg_.rc_dropframe_thresh = 0; cfg_.kf_max_dist = 9999; ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 30, 1, 0, 200); @@ -1288,17 +1289,21 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) { assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, cfg_.ts_number_layers, cfg_.temporal_layering_mode); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82) << " The datarate for the file exceeds the target by too much!"; ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15) << " The datarate for the file is lower than the target by too much!"; - EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + // Number of temporal layers > 1, so half of the frames in this SVC pattern + // will be non-reference frame and hence encoder will avoid loopfilter. + // Since frame dropper is off, we can expcet 100 (half of the sequence) + // mismatched frames. + EXPECT_EQ(static_cast<unsigned int>(100), GetMismatchFrames()); } } // Check basic rate targeting for 1 pass CBR SVC with denoising. // 2 spatial layers and 3 temporal layer. Run HD clip with 2 threads. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersDenoiserOn) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLDenoiserOn) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1318,7 +1323,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersDenoiserOn) { 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 = 10; + cfg_.rc_dropframe_thresh = 0; cfg_.kf_max_dist = 9999; ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300); // TODO(marpan): Check that effective_datarate for each layer hits the @@ -1330,17 +1335,21 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersDenoiserOn) { assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, cfg_.ts_number_layers, cfg_.temporal_layering_mode); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82) << " The datarate for the file exceeds the target by too much!"; ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15) << " The datarate for the file is lower than the target by too much!"; - EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + // Number of temporal layers > 1, so half of the frames in this SVC pattern + // will be non-reference frame and hence encoder will avoid loopfilter. + // Since frame dropper is off, we can expcet 150 (half of the sequence) + // mismatched frames. + EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames()); } } // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3 // temporal layers. Run CIF clip with 1 thread, and few short key frame periods. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLSmallKf) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1376,13 +1385,12 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) { << " The datarate for the file exceeds the target by too much!"; ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15) << " The datarate for the file is lower than the target by too much!"; - EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); } } // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and // 3 temporal layers. Run HD clip with 4 threads. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL4threads) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1402,7 +1410,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) { 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 = 10; + 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 = 800; @@ -1410,16 +1418,20 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) { assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, cfg_.ts_number_layers, cfg_.temporal_layering_mode); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82) << " The datarate for the file exceeds the target by too much!"; ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15) << " The datarate for the file is lower than the target by too much!"; - EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + // Number of temporal layers > 1, so half of the frames in this SVC pattern + // will be non-reference frame and hence encoder will avoid loopfilter. + // Since frame dropper is off, we can expcet 150 (half of the sequence) + // mismatched frames. + EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames()); } // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and // 3 temporal layers. Run CIF clip with 1 thread. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1441,7 +1453,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) { svc_params_.scaling_factor_den[1] = 288; svc_params_.scaling_factor_num[2] = 288; svc_params_.scaling_factor_den[2] = 288; - cfg_.rc_dropframe_thresh = 10; + 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 = 800; @@ -1449,16 +1461,20 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) { assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, cfg_.ts_number_layers, cfg_.temporal_layering_mode); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82) << " The datarate for the file exceeds the target by too much!"; ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22) << " The datarate for the file is lower than the target by too much!"; - EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + // Number of temporal layers > 1, so half of the frames in this SVC pattern + // will be non-reference frame and hence encoder will avoid loopfilter. + // Since frame dropper is off, we can expcet 150 (half of the sequence) + // mismatched frames. + EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames()); } // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3 // temporal layers. Run CIF clip with 1 thread, and few short key frame periods. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayersSmallKf) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TLSmallKf) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1495,13 +1511,12 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayersSmallKf) { << " The datarate for the file exceeds the target by too much!"; ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.30) << " The datarate for the file is lower than the target by too much!"; - EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); } } // Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and // 3 temporal layers. Run HD clip with 4 threads. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL4threads) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1523,7 +1538,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) { svc_params_.scaling_factor_den[1] = 288; svc_params_.scaling_factor_num[2] = 288; svc_params_.scaling_factor_den[2] = 288; - cfg_.rc_dropframe_thresh = 10; + 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 = 800; @@ -1531,16 +1546,20 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) { assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, cfg_.ts_number_layers, cfg_.temporal_layering_mode); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82) << " The datarate for the file exceeds the target by too much!"; ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22) << " The datarate for the file is lower than the target by too much!"; - EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + // Number of temporal layers > 1, so half of the frames in this SVC pattern + // will be non-reference frame and hence encoder will avoid loopfilter. + // Since frame dropper is off, we can expcet 150 (half of the sequence) + // mismatched frames. + EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames()); } // Run SVC encoder for 1 temporal layer, 2 spatial layers, with spatial // downscale 5x5. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers5x5MultipleRuns) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TL5x5MultipleRuns) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1558,7 +1577,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers5x5MultipleRuns) { svc_params_.scaling_factor_den[0] = 1280; svc_params_.scaling_factor_num[1] = 1280; svc_params_.scaling_factor_den[1] = 1280; - cfg_.rc_dropframe_thresh = 0; + cfg_.rc_dropframe_thresh = 10; cfg_.kf_max_dist = 999999; cfg_.kf_min_dist = 0; cfg_.ss_target_bitrate[0] = 300; diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 9b09e3891..481f5a0fd 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -1142,7 +1142,7 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile, mi->mv[0].as_int = 0; mi->interp_filter = BILINEAR; - if (cpi->oxcf.speed >= 8) + if (cpi->oxcf.speed >= 8 && !low_res) y_sad = 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); @@ -4152,14 +4152,11 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, ThreadData *td, break; case REFERENCE_PARTITION: set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64); - // Use nonrd_pick_partition on scene-cut for VBR, or on qp-segment - // if cyclic_refresh is enabled. + // Use nonrd_pick_partition on scene-cut for VBR mode. // nonrd_pick_partition does not support 4x4 partition, so avoid it // on key frame for now. if ((cpi->oxcf.rc_mode == VPX_VBR && cpi->rc.high_source_sad && - cm->frame_type != KEY_FRAME) || - (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled && - xd->mi[0]->segment_id)) { + cm->frame_type != KEY_FRAME)) { // Use lower max_partition_size for low resoultions. if (cm->width <= 352 && cm->height <= 288) x->max_partition_size = BLOCK_32X32; diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 1dc70d2d3..7d56232e1 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2618,6 +2618,10 @@ static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) { MACROBLOCKD *xd = &cpi->td.mb.e_mbd; struct loopfilter *lf = &cm->lf; + const int is_reference_frame = + (cpi->refresh_last_frame || cpi->refresh_golden_frame || + cpi->refresh_alt_ref_frame); + if (xd->lossless) { lf->filter_level = 0; lf->last_filt_level = 0; @@ -2643,7 +2647,7 @@ static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) { cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer); } - if (lf->filter_level > 0) { + if (lf->filter_level > 0 && is_reference_frame) { vp9_build_mask_frame(cm, lf->filter_level, 0); if (cpi->num_workers > 1) diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c index 4e8bbcbd1..a3939a5f8 100644 --- a/vp9/encoder/vp9_mcomp.c +++ b/vp9/encoder/vp9_mcomp.c @@ -101,10 +101,8 @@ static int mv_err_cost(const MV *mv, const MV *ref, const int *mvjcost, int *mvcost[2], int error_per_bit) { if (mvcost) { const MV diff = { mv->row - ref->row, mv->col - ref->col }; - // This product sits at a 32-bit ceiling right now and any additional - // accuracy in either bit cost or error cost will cause it to overflow. - return ROUND_POWER_OF_TWO( - (unsigned)mv_cost(&diff, mvjcost, mvcost) * error_per_bit, + return (int)ROUND64_POWER_OF_TWO( + (int64_t)mv_cost(&diff, mvjcost, mvcost) * error_per_bit, RDDIV_BITS + VP9_PROB_COST_SHIFT - RD_EPB_SHIFT + PIXEL_TRANSFORM_ERROR_SCALE); } diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index f79b7c6fc..b1866cd8a 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -2172,6 +2172,11 @@ void adjust_gf_boost_lag_one_pass_vbr(VP9_COMP *cpi, uint64_t avg_sad_current) { if (rate_err < 2.0 && !high_content) { rc->fac_active_worst_inter = 120; rc->fac_active_worst_gf = 90; + } else if (rate_err > 8.0 && rc->avg_frame_qindex[INTER_FRAME] < 16) { + // Increase active_worst faster at low Q if rate fluctuation is high. + rc->fac_active_worst_inter = 200; + if (rc->avg_frame_qindex[INTER_FRAME] < 8) + rc->fac_active_worst_inter = 400; } if (low_content && rc->avg_frame_low_motion > 80) { rc->af_ratio_onepass_vbr = 15; diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c index 2e0ca5b66..f74b6b0e9 100644 --- a/vp9/encoder/vp9_speed_features.c +++ b/vp9/encoder/vp9_speed_features.c @@ -555,7 +555,10 @@ static void set_rt_speed_feature_framesize_independent( } // Since the short_circuit_low_temp_var is used, reduce the // adaptive_rd_thresh level. - sf->adaptive_rd_thresh = 1; + if (cm->width > 320 && cm->height > 240) + sf->adaptive_rd_thresh = 1; + else + sf->adaptive_rd_thresh = 2; } sf->limit_newmv_early_exit = 0; if (cm->width > 320 && cm->height > 240) sf->use_simple_block_yrd = 1; |