diff --git a/media/engine/simulcast.cc b/media/engine/simulcast.cc index c53a49d483..dc05081ace 100644 --- a/media/engine/simulcast.cc +++ b/media/engine/simulcast.cc @@ -24,9 +24,15 @@ namespace cricket { namespace { +// Limits for legacy conference screensharing mode. Currently used for the +// lower of the two simulcast streams. constexpr int kScreenshareDefaultTl0BitrateKbps = 200; constexpr int kScreenshareDefaultTl1BitrateKbps = 1000; +// Max bitrate for the higher one of the two simulcast stream used for screen +// content. +constexpr int kScreenshareHighStreamMaxBitrateBps = 1600000; + } // namespace struct SimulcastFormat { @@ -311,21 +317,38 @@ std::vector GetScreenshareLayers( // restrictions. The base simulcast layer will still use legacy setup. if (num_simulcast_layers == kMaxScreenshareSimulcastLayers) { // Add optional upper simulcast layer. - // Lowest temporal layers of a 3 layer setup will have 40% of the total - // bitrate allocation for that simulcast layer. Make sure the gap between - // the target of the lower simulcast layer and first temporal layer of the - // higher one is at most 2x the bitrate, so that upswitching is not hampered - // by stalled bitrate estimates. - int max_bitrate_bps = 2 * ((layers[0].target_bitrate_bps * 10) / 4); + const int num_temporal_layers = DefaultNumberOfTemporalLayers(1); + int max_bitrate_bps; + if (!temporal_layers_supported) { + // Set the max bitrate to where the base layer would have been if temporal + // layer were enabled. + max_bitrate_bps = static_cast( + kScreenshareHighStreamMaxBitrateBps * + webrtc::SimulcastRateAllocator::GetTemporalRateAllocation( + num_temporal_layers, 0)); + } else if (DefaultNumberOfTemporalLayers(1) != 3 || + webrtc::field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) { + // Experimental temporal layer mode used, use increased max bitrate. + max_bitrate_bps = kScreenshareHighStreamMaxBitrateBps; + } else { + // Keep current bitrates with default 3tl/8 frame settings. + // Lowest temporal layers of a 3 layer setup will have 40% of the total + // bitrate allocation for that simulcast layer. Make sure the gap between + // the target of the lower simulcast layer and first temporal layer of the + // higher one is at most 2x the bitrate, so that upswitching is not + // hampered by stalled bitrate estimates. + max_bitrate_bps = 2 * ((layers[0].target_bitrate_bps * 10) / 4); + } + // Cap max bitrate so it isn't overly high for the given resolution. max_bitrate_bps = std::min(max_bitrate_bps, FindSimulcastMaxBitrateBps(width, height)); - layers[1].width = width; layers[1].height = height; layers[1].max_qp = max_qp; layers[1].max_framerate = max_framerate; - layers[1].num_temporal_layers = 3; + layers[1].num_temporal_layers = + temporal_layers_supported ? DefaultNumberOfTemporalLayers(1) : 0; layers[1].min_bitrate_bps = layers[0].target_bitrate_bps * 2; layers[1].target_bitrate_bps = max_bitrate_bps; layers[1].max_bitrate_bps = max_bitrate_bps; diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers.cc b/modules/video_coding/codecs/vp8/default_temporal_layers.cc index 03c582a84f..d1280a1c08 100644 --- a/modules/video_coding/codecs/vp8/default_temporal_layers.cc +++ b/modules/video_coding/codecs/vp8/default_temporal_layers.cc @@ -93,7 +93,7 @@ std::vector GetTemporalLayerSync(size_t num_layers) { case 1: return {false}; case 2: - if (field_trial::IsEnabled("WebRTC-UseShortVP8TL2Pattern")) { + if (!field_trial::IsDisabled("WebRTC-UseShortVP8TL2Pattern")) { return {false, true, false, false}; } else { return {false, true, false, false, false, false, false, false}; @@ -139,7 +139,7 @@ std::vector GetTemporalPattern(size_t num_layers) { // that the 'alt' buffer reference is effectively the last keyframe. // TL0 also references and updates the 'last' buffer. // TL1 also references 'last' and references and updates 'golden'. - if (field_trial::IsEnabled("WebRTC-UseShortVP8TL2Pattern")) { + if (!field_trial::IsDisabled("WebRTC-UseShortVP8TL2Pattern")) { // Shortened 4-frame pattern: // 1---1 1---1 ... // / / / / diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc b/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc index 8811bbd4d5..193bb38778 100644 --- a/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc +++ b/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc @@ -81,26 +81,26 @@ TEST(TemporalLayersTest, 2Layers) { kTemporalUpdateLastRefAltRef, kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateLastRefAltRef, - kTemporalUpdateGoldenRefAltRef, + kTemporalUpdateNone, kTemporalUpdateLastRefAltRef, - kTemporalUpdateGoldenRefAltRef, + kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateNone, kTemporalUpdateLastRefAltRef, kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateLastRefAltRef, - kTemporalUpdateGoldenRefAltRef, + kTemporalUpdateNone, kTemporalUpdateLastRefAltRef, - kTemporalUpdateGoldenRefAltRef, + kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateNone, }; int expected_temporal_idx[16] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; - bool expected_layer_sync[16] = {false, true, false, false, false, false, + bool expected_layer_sync[16] = {false, true, false, false, false, true, false, false, false, true, false, false, - false, false, false, false}; + false, true, false, false}; uint32_t timestamp = 0; for (int i = 0; i < 16; ++i) { diff --git a/modules/video_coding/codecs/vp8/temporal_layers.cc b/modules/video_coding/codecs/vp8/temporal_layers.cc index 1372f7a496..24129d7421 100644 --- a/modules/video_coding/codecs/vp8/temporal_layers.cc +++ b/modules/video_coding/codecs/vp8/temporal_layers.cc @@ -39,10 +39,15 @@ uint8_t NumTemporalLayers(const VideoCodec& codec, int spatial_id) { } bool IsConferenceModeScreenshare(const VideoCodec& codec) { - if (codec.mode != VideoCodecMode::kScreensharing) { + if (codec.mode != VideoCodecMode::kScreensharing || + NumTemporalLayers(codec, 0) != 2) { return false; } - return NumTemporalLayers(codec, 0) == 2; + // Fixed default bitrates for legacy screenshare layers mode. + return (codec.numberOfSimulcastStreams == 0 && codec.maxBitrate == 1000) || + (codec.numberOfSimulcastStreams >= 1 && + codec.simulcastStream[0].maxBitrate == 1000 && + codec.simulcastStream[0].targetBitrate == 200); } } // namespace diff --git a/modules/video_coding/utility/simulcast_test_fixture_impl.cc b/modules/video_coding/utility/simulcast_test_fixture_impl.cc index 2656a584fb..e81c2f4679 100644 --- a/modules/video_coding/utility/simulcast_test_fixture_impl.cc +++ b/modules/video_coding/utility/simulcast_test_fixture_impl.cc @@ -778,7 +778,7 @@ void SimulcastTestFixtureImpl::TestSpatioTemporalLayers321PatternEncoder() { input_frame_->set_timestamp(input_frame_->timestamp() + 3000); EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(2, 1, 255, expected_temporal_idx); - SetExpectedValues3(false, false, false, expected_layer_sync); + SetExpectedValues3(false, true, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); } diff --git a/video/BUILD.gn b/video/BUILD.gn index 96941f409d..5f9455c500 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -249,6 +249,7 @@ if (rtc_include_tests) { "../modules/video_coding:webrtc_vp9", "../rtc_base:rtc_base_approved", "../rtc_base/experiments:alr_experiment", + "../system_wrappers:field_trial_default", "../test:field_trial", "../test:test_common", "../test:test_support", diff --git a/video/full_stack_tests.cc b/video/full_stack_tests.cc index 0b7bfb37d6..dc8527ebde 100644 --- a/video/full_stack_tests.cc +++ b/video/full_stack_tests.cc @@ -13,6 +13,7 @@ #include "modules/video_coding/codecs/vp9/include/vp9.h" #include "rtc_base/experiments/alr_experiment.h" #include "rtc_base/flags.h" +#include "system_wrappers/include/field_trial_default.h" #include "test/field_trial.h" #include "test/gtest.h" #include "video/video_quality_test.h" @@ -66,6 +67,10 @@ CreateVideoQualityTestFixture() { return absl::make_unique(nullptr); } +// Takes the current active field trials set, and appends some new trials. +std::string AppendFieldTrials(std::string new_trial_string) { + return std::string(field_trial::GetFieldTrialString()) + new_trial_string; +} } // namespace // VideoQualityTest::Params params = { @@ -333,7 +338,7 @@ TEST(FullStackTest, ForemanCifPlr5H264) { TEST(FullStackTest, ForemanCifPlr5H264SpsPpsIdrIsKeyframe) { auto fixture = CreateVideoQualityTestFixture(); test::ScopedFieldTrials override_field_trials( - "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"); + AppendFieldTrials("WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/")); ParamsWithLogging foreman_cif; foreman_cif.call.send_side_bwe = true; @@ -556,7 +561,8 @@ TEST(FullStackTest, ConferenceMotionHd4TLModerateLimits) { TEST(FullStackTest, ConferenceMotionHd3TLModerateLimitsAltTLPattern) { auto fixture = CreateVideoQualityTestFixture(); - test::ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); + test::ScopedFieldTrials field_trial( + AppendFieldTrials("WebRTC-UseShortVP8TL3Pattern/Enabled/")); ParamsWithLogging conf_motion_hd; conf_motion_hd.call.send_side_bwe = true; conf_motion_hd.video[0] = { @@ -873,8 +879,8 @@ TEST(FullStackTest, MAYBE_SimulcastFullHdOveruse) { simulcast.ss[0] = { streams, 2, 1, 0, InterLayerPredMode::kOn, std::vector(), true}; - webrtc::test::ScopedFieldTrials override_trials( - "WebRTC-ForceSimulatedOveruseIntervalMs/1000-50000-300/"); + webrtc::test::ScopedFieldTrials override_trials(AppendFieldTrials( + "WebRTC-ForceSimulatedOveruseIntervalMs/1000-50000-300/")); fixture->RunWithAnalyzer(simulcast); } @@ -1054,8 +1060,8 @@ class DualStreamsTest : public ::testing::TestWithParam {}; TEST_P(DualStreamsTest, ModeratelyRestricted_SlidesVp8_3TL_Simulcast_Video_Simulcast_High) { test::ScopedFieldTrials field_trial( - std::string(kRoundRobinPacingQueueExperiment) + - std::string(kPacerPushBackExperiment)); + AppendFieldTrials(std::string(kRoundRobinPacingQueueExperiment) + + std::string(kPacerPushBackExperiment))); const int first_stream = GetParam(); ParamsWithLogging dual_streams; @@ -1118,8 +1124,8 @@ TEST_P(DualStreamsTest, TEST_P(DualStreamsTest, Conference_Restricted) { test::ScopedFieldTrials field_trial( - std::string(kRoundRobinPacingQueueExperiment) + - std::string(kPacerPushBackExperiment)); + AppendFieldTrials(std::string(kRoundRobinPacingQueueExperiment) + + std::string(kPacerPushBackExperiment))); const int first_stream = GetParam(); ParamsWithLogging dual_streams;