Field trial to control inter-layer prediction.
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 <ssilkin@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27521}
diff --git a/api/video_codecs/video_codec.h b/api/video_codecs/video_codec.h
index 57bb893..622cce1 100644
--- a/api/video_codecs/video_codec.h
+++ b/api/video_codecs/video_codec.h
@@ -47,13 +47,10 @@
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 2f0cfe4..762f033 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -387,8 +387,19 @@
// 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<int>(webrtc::InterLayerPredMode::kOn) ||
+ mode == static_cast<int>(webrtc::InterLayerPredMode::kOnKeyPic) ||
+ mode == static_cast<int>(webrtc::InterLayerPredMode::kOff))) {
+ vp9_settings.interLayerPred =
+ static_cast<webrtc::InterLayerPredMode>(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 d56b3b6..e844403 100644
--- a/media/engine/webrtc_video_engine_unittest.cc
+++ b/media/engine/webrtc_video_engine_unittest.cc
@@ -3196,13 +3196,20 @@
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<const char*, int, int, webrtc::InterLayerPredMode>> {
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 @@
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<webrtc::VideoStream> streams = AddSendStream()->GetVideoStreams();