From 076d4bd91ad0ec042924d2772b2002c9e7d3d48b Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 7 Dec 2016 09:50:27 -0800 Subject: [PATCH] vp9: Fix to crash in svc code. use_base_mv assumes 2x2 scaling, so fix is to shutoff this feature unless spatial scale factors are 2. Added svc unittest for 2 spatial layers with 5x5 scaling, which generates the issue without this fix. Also fix some settings in svc unittest: let the speed setting vary (from 5 to 8), and enable static threshold. BUG=webm:1344 Change-Id: Idfd0a6c633c21b49a0479601506302cfe974e30e --- test/datarate_test.cc | 38 +++++++++++++++++++++++++++++++++++++- vp9/encoder/vp9_svc_layercontext.c | 15 +++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/test/datarate_test.cc b/test/datarate_test.cc index d5c0922..df6168d 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc @@ -1052,7 +1052,7 @@ class DatarateOnePassCbrSvc } svc_params_.speed_per_layer[0] = 5; for (i = 1; i < VPX_SS_MAX_LAYERS; ++i) { - svc_params_.speed_per_layer[i] = 7; + svc_params_.speed_per_layer[i] = speed_setting_; } encoder->Control(VP9E_SET_SVC, 1); encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_); @@ -1060,6 +1060,7 @@ class DatarateOnePassCbrSvc encoder->Control(VP9E_SET_TILE_COLUMNS, 0); encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300); encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1)); + encoder->Control(VP8E_SET_STATIC_THRESHOLD, 1); } const vpx_rational_t tb = video->timebase(); timebase_ = static_cast(tb.num) / tb.den; @@ -1390,6 +1391,41 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) { EXPECT_EQ(static_cast(0), GetMismatchFrames()); } +// Run SVC encoder for 1 temporal layer, 2 spatial layers, with spatial +// downscale 5x5. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers5x5MultipleRuns) { + 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 = 3; + cfg_.temporal_layering_mode = 0; + svc_params_.scaling_factor_num[0] = 256; + 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_.kf_max_dist = 999999; + cfg_.kf_min_dist = 0; + cfg_.ss_target_bitrate[0] = 300; + cfg_.ss_target_bitrate[1] = 1400; + cfg_.layer_target_bitrate[0] = 300; + cfg_.layer_target_bitrate[1] = 1400; + cfg_.rc_target_bitrate = 1700; + ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, 30, + 1, 0, 30); + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + EXPECT_EQ(static_cast(0), GetMismatchFrames()); +} + VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES, ::testing::Values(0)); VP8_INSTANTIATE_TEST_CASE(DatarateTestRealTime, diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index 2d29e26..1d892dc 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -650,6 +650,21 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) { lc->scaling_factor_num, lc->scaling_factor_den, &width, &height); + // The usage of use_base_mv assumes down-scale of 2x2. For now, turn off use + // of base motion vectors if spatial scale factors for any layers are not 2. + // TODO(marpan): Fix this to allow for use_base_mv for scale factors != 2. + if (cpi->svc.number_spatial_layers > 1) { + int sl; + for (sl = 0; sl < cpi->svc.number_spatial_layers - 1; ++sl) { + lc = &cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers + + cpi->svc.temporal_layer_id]; + if (lc->scaling_factor_num != lc->scaling_factor_den >> 1) { + cpi->svc.use_base_mv = 0; + break; + } + } + } + if (vp9_set_size_literal(cpi, width, height) != 0) return VPX_CODEC_INVALID_PARAM; -- 2.7.4