diff --git a/webrtc/media/engine/fakewebrtccall.cc b/webrtc/media/engine/fakewebrtccall.cc index 5b2f0a73c4..c345565b1b 100644 --- a/webrtc/media/engine/fakewebrtccall.cc +++ b/webrtc/media/engine/fakewebrtccall.cc @@ -166,9 +166,17 @@ void FakeVideoSendStream::ReconfigureVideoEncoder( if (config_.encoder_settings.payload_name == "VP8") { vpx_settings_.vp8 = *reinterpret_cast( config.encoder_specific_settings); + if (!config.streams.empty()) { + vpx_settings_.vp8.numberOfTemporalLayers = static_cast( + config.streams.back().temporal_layer_thresholds_bps.size() + 1); + } } else if (config_.encoder_settings.payload_name == "VP9") { vpx_settings_.vp9 = *reinterpret_cast( config.encoder_specific_settings); + if (!config.streams.empty()) { + vpx_settings_.vp9.numberOfTemporalLayers = static_cast( + config.streams.back().temporal_layer_thresholds_bps.size() + 1); + } } else { ADD_FAILURE() << "Unsupported encoder payload: " << config_.encoder_settings.payload_name; diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc index 395dcb5737..3cff1e6fbd 100644 --- a/webrtc/media/engine/webrtcvideoengine2.cc +++ b/webrtc/media/engine/webrtcvideoengine2.cc @@ -10,6 +10,7 @@ #include "webrtc/media/engine/webrtcvideoengine2.h" +#include #include #include #include @@ -315,6 +316,44 @@ static int GetMaxDefaultVideoBitrateKbps(int width, int height) { } } +bool GetVp9LayersFromFieldTrialGroup(int* num_spatial_layers, + int* num_temporal_layers) { + std::string group = webrtc::field_trial::FindFullName("WebRTC-SupportVP9SVC"); + if (group.empty()) + return false; + + if (sscanf(group.c_str(), "EnabledByFlag_%dSL%dTL", num_spatial_layers, + num_temporal_layers) != 2) { + return false; + } + const int kMaxSpatialLayers = 3; + if (*num_spatial_layers > kMaxSpatialLayers || *num_spatial_layers < 1) + return false; + + const int kMaxTemporalLayers = 3; + if (*num_temporal_layers > kMaxTemporalLayers || *num_temporal_layers < 1) + return false; + + return true; +} + +int GetDefaultVp9SpatialLayers() { + int num_sl; + int num_tl; + if (GetVp9LayersFromFieldTrialGroup(&num_sl, &num_tl)) { + return num_sl; + } + return 1; +} + +int GetDefaultVp9TemporalLayers() { + int num_sl; + int num_tl; + if (GetVp9LayersFromFieldTrialGroup(&num_sl, &num_tl)) { + return num_tl; + } + return 1; +} } // namespace // Constants defined in webrtc/media/engine/constants.h @@ -443,6 +482,14 @@ void* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings( } if (CodecNamesEq(codec.name, kVp9CodecName)) { encoder_settings_.vp9 = webrtc::VideoEncoder::GetDefaultVp9Settings(); + if (is_screencast) { + // TODO(asapersson): Set to 2 for now since there is a DCHECK in + // VideoSendStream::ReconfigureVideoEncoder. + encoder_settings_.vp9.numberOfSpatialLayers = 2; + } else { + encoder_settings_.vp9.numberOfSpatialLayers = + GetDefaultVp9SpatialLayers(); + } // VP9 denoising is disabled by default. encoder_settings_.vp9.denoisingOn = codec_default_denoising ? false : denoising; @@ -1908,6 +1955,11 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( config.tl0_bitrate_kbps * 1000); } + if (CodecNamesEq(codec.name, kVp9CodecName) && !is_screencast && + encoder_config.streams.size() == 1) { + encoder_config.streams[0].temporal_layer_thresholds_bps.resize( + GetDefaultVp9TemporalLayers() - 1); + } return encoder_config; } diff --git a/webrtc/media/engine/webrtcvideoengine2_unittest.cc b/webrtc/media/engine/webrtcvideoengine2_unittest.cc index 81f0e5b168..477b62323e 100644 --- a/webrtc/media/engine/webrtcvideoengine2_unittest.cc +++ b/webrtc/media/engine/webrtcvideoengine2_unittest.cc @@ -1824,7 +1824,9 @@ TEST_F(WebRtcVideoChannel2Test, VerifyVp8SpecificSettings) { class Vp9SettingsTest : public WebRtcVideoChannel2Test { public: - Vp9SettingsTest() : WebRtcVideoChannel2Test() { + Vp9SettingsTest() : Vp9SettingsTest("") {} + explicit Vp9SettingsTest(const char* field_trials) + : WebRtcVideoChannel2Test(field_trials) { encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP9, "VP9"); } virtual ~Vp9SettingsTest() {} @@ -1899,6 +1901,72 @@ TEST_F(Vp9SettingsTest, VerifyVp9SpecificSettings) { EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); } +class Vp9SettingsTestWithFieldTrial : public Vp9SettingsTest { + public: + Vp9SettingsTestWithFieldTrial(const char* field_trials) + : Vp9SettingsTest(field_trials) {} + + protected: + void VerifySettings(int num_spatial_layers, int num_temporal_layers) { + cricket::VideoSendParameters parameters; + parameters.codecs.push_back(kVp9Codec); + ASSERT_TRUE(channel_->SetSendParameters(parameters)); + + FakeVideoSendStream* stream = SetUpSimulcast(false, false); + + cricket::FakeVideoCapturer capturer; + EXPECT_EQ(cricket::CS_RUNNING, + capturer.Start(capturer.GetSupportedFormats()->front())); + EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); + channel_->SetSend(true); + + EXPECT_TRUE(capturer.CaptureFrame()); + + webrtc::VideoCodecVP9 vp9_settings; + ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set."; + EXPECT_EQ(num_spatial_layers, vp9_settings.numberOfSpatialLayers); + EXPECT_EQ(num_temporal_layers, vp9_settings.numberOfTemporalLayers); + + EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); + } +}; + +class Vp9SettingsTestWithNoFlag : public Vp9SettingsTestWithFieldTrial { + public: + Vp9SettingsTestWithNoFlag() : Vp9SettingsTestWithFieldTrial("") {} +}; + +TEST_F(Vp9SettingsTestWithNoFlag, VerifySettings) { + const int kNumSpatialLayers = 1; + const int kNumTemporalLayers = 1; + VerifySettings(kNumSpatialLayers, kNumTemporalLayers); +} + +class Vp9SettingsTestWithInvalidFlag : public Vp9SettingsTestWithFieldTrial { + public: + Vp9SettingsTestWithInvalidFlag() + : Vp9SettingsTestWithFieldTrial("WebRTC-SupportVP9SVC/Default/") {} +}; + +TEST_F(Vp9SettingsTestWithInvalidFlag, VerifySettings) { + const int kNumSpatialLayers = 1; + const int kNumTemporalLayers = 1; + VerifySettings(kNumSpatialLayers, kNumTemporalLayers); +} + +class Vp9SettingsTestWith2SL3TLFlag : public Vp9SettingsTestWithFieldTrial { + public: + Vp9SettingsTestWith2SL3TLFlag() + : Vp9SettingsTestWithFieldTrial( + "WebRTC-SupportVP9SVC/EnabledByFlag_2SL3TL/") {} +}; + +TEST_F(Vp9SettingsTestWith2SL3TLFlag, VerifySettings) { + const int kNumSpatialLayers = 2; + const int kNumTemporalLayers = 3; + VerifySettings(kNumSpatialLayers, kNumTemporalLayers); +} + TEST_F(WebRtcVideoChannel2Test, AdaptsOnOveruse) { TestCpuAdaptation(true, false); }