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}
This commit is contained in:
Sergey Silkin 2019-04-09 11:40:09 +02:00 committed by Commit Bot
parent 2e06926c95
commit cf267052b3
3 changed files with 62 additions and 48 deletions

View File

@ -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.

View File

@ -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<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;

View File

@ -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<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 @@ 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<webrtc::VideoStream> streams = AddSendStream()->GetVideoStreams();