From cf267052b3d8228ce14d9692f7409e7afa37db9f Mon Sep 17 00:00:00 2001 From: Sergey Silkin Date: Tue, 9 Apr 2019 11:40:09 +0200 Subject: [PATCH] Field trial to control inter-layer prediction. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds WebRTC-Vp9InterLayerPred field trial that allows to control inter-layer prediction mode in VP9 encoder. Bug: chromium:949536 Change-Id: Iea03db07fd21f28ab58382c5fdaac68acacc701c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131322 Commit-Queue: Sergey Silkin Reviewed-by: Ilya Nikolaevskiy Reviewed-by: Erik Språng Cr-Commit-Position: refs/heads/master@{#27521} --- api/video_codecs/video_codec.h | 11 +-- media/engine/webrtc_video_engine.cc | 15 +++- media/engine/webrtc_video_engine_unittest.cc | 84 +++++++++++--------- 3 files changed, 62 insertions(+), 48 deletions(-) diff --git a/api/video_codecs/video_codec.h b/api/video_codecs/video_codec.h index 57bb8933de..622cce1326 100644 --- a/api/video_codecs/video_codec.h +++ b/api/video_codecs/video_codec.h @@ -47,13 +47,10 @@ struct VideoCodecVP8 { int keyFrameInterval; }; -enum class InterLayerPredMode { - kOn, // Allow inter-layer prediction for all frames. - // Frame of low spatial layer can be used for - // prediction of next spatial layer frame. - kOff, // Encoder produces independent spatial layers. - kOnKeyPic // Allow inter-layer prediction only for frames - // within key picture. +enum class InterLayerPredMode : int { + kOff = 0, // Inter-layer prediction is disabled. + kOn = 1, // Inter-layer prediction is enabled. + kOnKeyPic = 2 // Inter-layer prediction is enabled but limited to key frames. }; // VP9 specific. diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 2f0cfe47c7..762f0333e8 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc @@ -387,8 +387,19 @@ WebRtcVideoChannel::WebRtcVideoSendStream::ConfigureVideoEncoderSettings( // Ensure frame dropping is always enabled. RTC_DCHECK(vp9_settings.frameDroppingOn); if (!is_screencast) { - // Limit inter-layer prediction to key pictures. - vp9_settings.interLayerPred = webrtc::InterLayerPredMode::kOnKeyPic; + const std::string group = + webrtc::field_trial::FindFullName("WebRTC-Vp9InterLayerPred"); + int mode; + if (!group.empty() && sscanf(group.c_str(), "%d", &mode) == 1 && + (mode == static_cast(webrtc::InterLayerPredMode::kOn) || + mode == static_cast(webrtc::InterLayerPredMode::kOnKeyPic) || + mode == static_cast(webrtc::InterLayerPredMode::kOff))) { + vp9_settings.interLayerPred = + static_cast(mode); + } else { + // Limit inter-layer prediction to key pictures by default. + vp9_settings.interLayerPred = webrtc::InterLayerPredMode::kOnKeyPic; + } } else { // Multiple spatial layers vp9 screenshare needs flexible mode. vp9_settings.flexibleMode = vp9_settings.numberOfSpatialLayers > 1; diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc index d56b3b6892..e844403378 100644 --- a/media/engine/webrtc_video_engine_unittest.cc +++ b/media/engine/webrtc_video_engine_unittest.cc @@ -3196,13 +3196,20 @@ TEST_F(Vp9SettingsTest, AllEncodingParametersCopied) { EXPECT_TRUE(encoder_config.simulcast_layers[2].active); } -class Vp9SettingsTestWithFieldTrial : public Vp9SettingsTest { - public: - explicit Vp9SettingsTestWithFieldTrial(const char* field_trials) - : Vp9SettingsTest(field_trials) {} - +class Vp9SettingsTestWithFieldTrial + : public Vp9SettingsTest, + public ::testing::WithParamInterface< + ::testing::tuple> { protected: - void VerifySettings(int num_spatial_layers, int num_temporal_layers) { + Vp9SettingsTestWithFieldTrial() + : Vp9SettingsTest(::testing::get<0>(GetParam())), + num_spatial_layers_(::testing::get<1>(GetParam())), + num_temporal_layers_(::testing::get<2>(GetParam())), + inter_layer_pred_(::testing::get<3>(GetParam())) {} + + void VerifySettings(int num_spatial_layers, + int num_temporal_layers, + webrtc::InterLayerPredMode interLayerPred) { cricket::VideoSendParameters parameters; parameters.codecs.push_back(GetEngineCodec("VP9")); ASSERT_TRUE(channel_->SetSendParameters(parameters)); @@ -3219,46 +3226,45 @@ class Vp9SettingsTestWithFieldTrial : public Vp9SettingsTest { 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_EQ(inter_layer_pred_, vp9_settings.interLayerPred); EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr)); } + + const uint8_t num_spatial_layers_; + const uint8_t num_temporal_layers_; + const webrtc::InterLayerPredMode inter_layer_pred_; }; -class Vp9SettingsTestWithNoFlag : public Vp9SettingsTestWithFieldTrial { - public: - Vp9SettingsTestWithNoFlag() : Vp9SettingsTestWithFieldTrial("") {} -}; - -TEST_F(Vp9SettingsTestWithNoFlag, VerifySettings) { - const int kNumSpatialLayers = 1; - const int kNumTemporalLayers = 1; - VerifySettings(kNumSpatialLayers, kNumTemporalLayers); +TEST_P(Vp9SettingsTestWithFieldTrial, VerifyCodecSettings) { + VerifySettings(num_spatial_layers_, num_temporal_layers_, inter_layer_pred_); } -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); -} +INSTANTIATE_TEST_SUITE_P( + , + Vp9SettingsTestWithFieldTrial, + ::testing::Values( + std::make_tuple("", 1, 1, webrtc::InterLayerPredMode::kOnKeyPic), + std::make_tuple("WebRTC-SupportVP9SVC/Default/", + 1, + 1, + webrtc::InterLayerPredMode::kOnKeyPic), + std::make_tuple("WebRTC-SupportVP9SVC/EnabledByFlag_2SL3TL/", + 2, + 3, + webrtc::InterLayerPredMode::kOnKeyPic), + std::make_tuple("WebRTC-Vp9InterLayerPred/0/", + 1, + 1, + webrtc::InterLayerPredMode::kOff), + std::make_tuple("WebRTC-Vp9InterLayerPred/1/", + 1, + 1, + webrtc::InterLayerPredMode::kOn), + std::make_tuple("WebRTC-Vp9InterLayerPred/2/", + 1, + 1, + webrtc::InterLayerPredMode::kOnKeyPic))); TEST_F(WebRtcVideoChannelTest, VerifyMinBitrate) { std::vector streams = AddSendStream()->GetVideoStreams();