Control inter-layer prediction mode in test apps.

Vp9 encoder supports several inter-layer prediction modes. This adds
possibility to control and test them in video/ss/sv loopback.

Filtering of sent packets has been modified. In addition to high
spatial and temporal layers it now filters out packets of low spatial
layers where non_ref_for_inter_layer_pred bit is set to true.

Bug: none
Change-Id: I17b1ee8f1ac1d70a6914eb86d153790ef2da9679
Reviewed-on: https://webrtc-review.googlesource.com/76540
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23233}
This commit is contained in:
Sergey Silkin 2018-05-15 09:12:05 +02:00 committed by Commit Bot
parent d675e63684
commit 5702736f7e
7 changed files with 144 additions and 37 deletions

View File

@ -141,20 +141,38 @@ bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
const int spatial_idx = static_cast<int>(
is_vp8 ? kNoSpatialIdx
: parsed_payload.type.Video.codecHeader.VP9.spatial_idx);
const bool non_ref_for_inter_layer_pred =
is_vp8 ? false
: parsed_payload.type.Video.codecHeader.VP9
.non_ref_for_inter_layer_pred;
if (selected_sl_ >= 0 && spatial_idx == selected_sl_ &&
parsed_payload.type.Video.codecHeader.VP9.end_of_frame) {
// This layer is now the last in the superframe.
set_marker_bit = true;
} else if ((selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx &&
temporal_idx > selected_tl_) ||
(selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
spatial_idx > selected_sl_)) {
// Truncate packet to a padding packet.
length = header.headerLength + 1;
temp_buffer[0] |= (1 << 5); // P = 1.
temp_buffer[1] &= 0x7F; // M = 0.
discarded_last_packet_ = true;
temp_buffer[header.headerLength] = 1; // One byte of padding.
} else {
const bool higher_temporal_layer =
(selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx &&
temporal_idx > selected_tl_);
const bool higher_spatial_layer =
(selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
spatial_idx > selected_sl_);
// Filter out non-reference lower spatial layers since they are not
// needed for decoding of target spatial layer.
const bool lower_non_ref_spatial_layer =
(selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
spatial_idx < selected_sl_ && non_ref_for_inter_layer_pred);
if (higher_temporal_layer || higher_spatial_layer ||
lower_non_ref_spatial_layer) {
// Truncate packet to a padding packet.
length = header.headerLength + 1;
temp_buffer[0] |= (1 << 5); // P = 1.
temp_buffer[1] &= 0x7F; // M = 0.
discarded_last_packet_ = true;
temp_buffer[header.headerLength] = 1; // One byte of padding.
}
}
} else {
RTC_NOTREACHED() << "Parse error";

View File

@ -521,7 +521,9 @@ TEST_F(FullStackTest, ScreenshareSlidesVP8_3TL_Simulcast) {
std::vector<VideoStream> streams = {
DefaultVideoStream(screenshare_params_low, 0),
DefaultVideoStream(screenshare_params_high, 0)};
screenshare.ss[0] = {streams, 1, 1, 0, std::vector<SpatialLayer>(), false};
screenshare.ss[0] = {
streams, 1, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(screenshare);
}
@ -670,7 +672,9 @@ TEST_F(FullStackTest, ScreenshareSlidesVP8_3TL_Simulcast_ALR) {
std::vector<VideoStream> streams = {
DefaultVideoStream(screenshare_params_low, 0),
DefaultVideoStream(screenshare_params_high, 0)};
screenshare.ss[0] = {streams, 1, 1, 0, std::vector<SpatialLayer>(), false};
screenshare.ss[0] = {
streams, 1, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(screenshare);
}
@ -704,8 +708,9 @@ TEST_F(FullStackTest, ScreenshareSlidesVP9_2SL) {
screenshare.screenshare[0] = {true, false, 10};
screenshare.analyzer = {"screenshare_slides_vp9_2sl", 0.0, 0.0,
kFullStackTestDurationSecs};
screenshare.ss[0] = {std::vector<VideoStream>(), 0, 2, 1,
std::vector<SpatialLayer>(), false};
screenshare.ss[0] = {
std::vector<VideoStream>(), 0, 2, 1, InterLayerPredMode::kOn,
std::vector<SpatialLayer>(), false};
RunTest(screenshare);
}
@ -715,8 +720,9 @@ TEST_F(FullStackTest, VP9SVC_3SL_High) {
simulcast.video[0] = kSvcVp9Video;
simulcast.analyzer = {"vp9svc_3sl_high", 0.0, 0.0,
kFullStackTestDurationSecs};
simulcast.ss[0] = {std::vector<VideoStream>(), 0, 3, 2,
std::vector<SpatialLayer>(), false};
simulcast.ss[0] = {
std::vector<VideoStream>(), 0, 3, 2, InterLayerPredMode::kOn,
std::vector<SpatialLayer>(), false};
RunTest(simulcast);
}
@ -726,8 +732,9 @@ TEST_F(FullStackTest, VP9SVC_3SL_Medium) {
simulcast.video[0] = kSvcVp9Video;
simulcast.analyzer = {"vp9svc_3sl_medium", 0.0, 0.0,
kFullStackTestDurationSecs};
simulcast.ss[0] = {std::vector<VideoStream>(), 0, 3, 1,
std::vector<SpatialLayer>(), false};
simulcast.ss[0] = {
std::vector<VideoStream>(), 0, 3, 1, InterLayerPredMode::kOn,
std::vector<SpatialLayer>(), false};
RunTest(simulcast);
}
@ -736,8 +743,9 @@ TEST_F(FullStackTest, VP9SVC_3SL_Low) {
simulcast.call.send_side_bwe = true;
simulcast.video[0] = kSvcVp9Video;
simulcast.analyzer = {"vp9svc_3sl_low", 0.0, 0.0, kFullStackTestDurationSecs};
simulcast.ss[0] = {std::vector<VideoStream>(), 0, 3, 0,
std::vector<SpatialLayer>(), false};
simulcast.ss[0] = {
std::vector<VideoStream>(), 0, 3, 0, InterLayerPredMode::kOn,
std::vector<SpatialLayer>(), false};
RunTest(simulcast);
}
#endif // !defined(RTC_DISABLE_VP9)
@ -763,7 +771,9 @@ TEST_F(FullStackTest, MAYBE_SimulcastFullHdOveruse) {
std::vector<VideoStream> streams = {DefaultVideoStream(simulcast, 0),
DefaultVideoStream(simulcast, 0),
DefaultVideoStream(simulcast, 0)};
simulcast.ss[0] = {streams, 2, 1, 0, std::vector<SpatialLayer>(), true};
simulcast.ss[0] = {
streams, 2, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
true};
webrtc::test::ScopedFieldTrials override_trials(
"WebRTC-ForceSimulatedOveruseIntervalMs/1000-50000-300/");
RunTest(simulcast);
@ -788,7 +798,9 @@ TEST_F(FullStackTest, SimulcastVP8_3SL_High) {
DefaultVideoStream(video_params_low, 0),
DefaultVideoStream(video_params_medium, 0),
DefaultVideoStream(video_params_high, 0)};
simulcast.ss[0] = {streams, 2, 1, 0, std::vector<SpatialLayer>(), false};
simulcast.ss[0] = {
streams, 2, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(simulcast);
}
@ -811,7 +823,9 @@ TEST_F(FullStackTest, SimulcastVP8_3SL_Medium) {
DefaultVideoStream(video_params_low, 0),
DefaultVideoStream(video_params_medium, 0),
DefaultVideoStream(video_params_high, 0)};
simulcast.ss[0] = {streams, 1, 1, 0, std::vector<SpatialLayer>(), false};
simulcast.ss[0] = {
streams, 1, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(simulcast);
}
@ -834,7 +848,9 @@ TEST_F(FullStackTest, SimulcastVP8_3SL_Low) {
DefaultVideoStream(video_params_low, 0),
DefaultVideoStream(video_params_medium, 0),
DefaultVideoStream(video_params_high, 0)};
simulcast.ss[0] = {streams, 0, 1, 0, std::vector<SpatialLayer>(), false};
simulcast.ss[0] = {
streams, 0, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(simulcast);
}
@ -858,7 +874,9 @@ TEST_F(FullStackTest, LargeRoomVP8_5thumb) {
DefaultVideoStream(video_params_medium, 0),
DefaultVideoStream(video_params_high, 0)};
large_room.call.num_thumbnails = 5;
large_room.ss[0] = {streams, 2, 1, 0, std::vector<SpatialLayer>(), false};
large_room.ss[0] = {
streams, 2, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(large_room);
}
@ -892,7 +910,9 @@ TEST_F(FullStackTest, MAYBE_LargeRoomVP8_15thumb) {
DefaultVideoStream(video_params_medium, 0),
DefaultVideoStream(video_params_high, 0)};
large_room.call.num_thumbnails = 15;
large_room.ss[0] = {streams, 2, 1, 0, std::vector<SpatialLayer>(), false};
large_room.ss[0] = {
streams, 2, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(large_room);
}
@ -916,7 +936,9 @@ TEST_F(FullStackTest, MAYBE_LargeRoomVP8_50thumb) {
DefaultVideoStream(video_params_medium, 0),
DefaultVideoStream(video_params_high, 0)};
large_room.call.num_thumbnails = 50;
large_room.ss[0] = {streams, 2, 1, 0, std::vector<SpatialLayer>(), false};
large_room.ss[0] = {
streams, 2, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
RunTest(large_room);
}
@ -951,8 +973,9 @@ TEST_P(DualStreamsTest,
DefaultVideoStream(screenshare_params_low, 0),
DefaultVideoStream(screenshare_params_high, 0)};
dual_streams.ss[first_stream] = {screenhsare_streams, 1, 1, 0,
std::vector<SpatialLayer>(), false};
dual_streams.ss[first_stream] = {
screenhsare_streams, 1, 1, 0, InterLayerPredMode::kOn,
std::vector<SpatialLayer>(), false};
// Video settings.
dual_streams.video[1 - first_stream] = kSimulcastVp8VideoHigh;
@ -969,7 +992,8 @@ TEST_P(DualStreamsTest,
DefaultVideoStream(video_params_high, 0)};
dual_streams.ss[1 - first_stream] = {
streams, 2, 1, 0, std::vector<SpatialLayer>(), false};
streams, 2, 1, 0, InterLayerPredMode::kOn, std::vector<SpatialLayer>(),
false};
// Call settings.
dual_streams.call.send_side_bwe = true;

View File

@ -157,6 +157,21 @@ int NumSpatialLayers() {
return static_cast<int>(FLAG_num_spatial_layers);
}
DEFINE_int(inter_layer_pred,
1,
"Inter-layer prediction mode. "
"0 - enabled, 1 - disabled, 2 - enabled only for key pictures.");
InterLayerPredMode InterLayerPred() {
if (FLAG_inter_layer_pred == 0) {
return InterLayerPredMode::kOn;
} else if (FLAG_inter_layer_pred == 1) {
return InterLayerPredMode::kOff;
} else {
RTC_DCHECK_EQ(FLAG_inter_layer_pred, 2);
return InterLayerPredMode::kOnKeyPic;
}
}
DEFINE_int(selected_sl,
-1,
"Spatial layer to show or analyze. -1 to disable filtering.");
@ -310,7 +325,7 @@ void Loopback() {
VideoQualityTest::FillScalabilitySettings(
&params, 0, stream_descriptors, flags::NumStreams(),
flags::SelectedStream(), flags::NumSpatialLayers(), flags::SelectedSL(),
SL_descriptors);
flags::InterLayerPred(), SL_descriptors);
VideoQualityTest test;
if (flags::DurationSecs()) {

View File

@ -21,6 +21,17 @@
namespace webrtc {
namespace flags {
InterLayerPredMode IntToInterLayerPredMode(int inter_layer_pred) {
if (inter_layer_pred == 0) {
return InterLayerPredMode::kOn;
} else if (inter_layer_pred == 1) {
return InterLayerPredMode::kOff;
} else {
RTC_DCHECK_EQ(inter_layer_pred, 2);
return InterLayerPredMode::kOnKeyPic;
}
}
// Flags for video.
DEFINE_int(vwidth, 640, "Video width.");
size_t VideoWidth() {
@ -80,6 +91,14 @@ int VideoNumSpatialLayers() {
return static_cast<int>(FLAG_vnum_spatial_layers);
}
DEFINE_int(vinter_layer_pred,
1,
"Video inter-layer prediction mode. "
"0 - enabled, 1 - disabled, 2 - enabled only for key pictures.");
InterLayerPredMode VideoInterLayerPred() {
return IntToInterLayerPredMode(FLAG_vinter_layer_pred);
}
DEFINE_string(
vstream0,
"",
@ -190,11 +209,19 @@ int ScreenshareNumStreams() {
DEFINE_int(snum_spatial_layers,
1,
"Number of screemshare spatial layers to use.");
"Number of screenshare spatial layers to use.");
int ScreenshareNumSpatialLayers() {
return static_cast<int>(FLAG_snum_spatial_layers);
}
DEFINE_int(sinter_layer_pred,
1,
"Screenshare inter-layer prediction mode. "
"0 - enabled, 1 - disabled, 2 - enabled only for key pictures.");
InterLayerPredMode ScreenshareInterLayerPred() {
return IntToInterLayerPredMode(FLAG_sinter_layer_pred);
}
DEFINE_string(
sstream0,
"",
@ -536,7 +563,7 @@ void Loopback() {
&params, screenshare_idx, stream_descriptors,
flags::ScreenshareNumStreams(), flags::ScreenshareSelectedStream(),
flags::ScreenshareNumSpatialLayers(), flags::ScreenshareSelectedSL(),
SL_descriptors);
flags::ScreenshareInterLayerPred(), SL_descriptors);
stream_descriptors.clear();
stream_descriptors.push_back(flags::VideoStream0());
@ -547,7 +574,7 @@ void Loopback() {
VideoQualityTest::FillScalabilitySettings(
&params, camera_idx, stream_descriptors, flags::VideoNumStreams(),
flags::VideoSelectedStream(), flags::VideoNumSpatialLayers(),
flags::VideoSelectedSL(), SL_descriptors);
flags::VideoSelectedSL(), flags::VideoInterLayerPred(), SL_descriptors);
VideoQualityTest test;
if (flags::DurationSecs()) {

View File

@ -72,6 +72,21 @@ int NumTemporalLayers() {
return static_cast<int>(FLAG_num_temporal_layers);
}
DEFINE_int(inter_layer_pred,
1,
"Inter-layer prediction mode. "
"0 - enabled, 1 - disabled, 2 - enabled only for key pictures.");
InterLayerPredMode InterLayerPred() {
if (FLAG_inter_layer_pred == 0) {
return InterLayerPredMode::kOn;
} else if (FLAG_inter_layer_pred == 1) {
return InterLayerPredMode::kOff;
} else {
RTC_DCHECK_EQ(FLAG_inter_layer_pred, 2);
return InterLayerPredMode::kOnKeyPic;
}
}
// Flags common with screenshare loopback, with equal default values.
DEFINE_string(codec, "VP8", "Video codec to use.");
std::string Codec() {
@ -310,7 +325,7 @@ void Loopback() {
VideoQualityTest::FillScalabilitySettings(
&params, 0, stream_descriptors, flags::NumStreams(),
flags::SelectedStream(), flags::NumSpatialLayers(), flags::SelectedSL(),
SL_descriptors);
flags::InterLayerPred(), SL_descriptors);
VideoQualityTest test;
if (flags::DurationSecs()) {

View File

@ -1135,8 +1135,10 @@ VideoQualityTest::Params::Params()
screenshare{{false, false, 10, 0}, {false, false, 10, 0}},
analyzer({"", 0.0, 0.0, 0, "", ""}),
pipe(),
ss{{std::vector<VideoStream>(), 0, 0, -1, std::vector<SpatialLayer>()},
{std::vector<VideoStream>(), 0, 0, -1, std::vector<SpatialLayer>()}},
ss{{std::vector<VideoStream>(), 0, 0, -1, InterLayerPredMode::kOn,
std::vector<SpatialLayer>()},
{std::vector<VideoStream>(), 0, 0, -1, InterLayerPredMode::kOn,
std::vector<SpatialLayer>()}},
logging({false, "", "", ""}) {}
VideoQualityTest::Params::~Params() = default;
@ -1292,6 +1294,7 @@ void VideoQualityTest::FillScalabilitySettings(
size_t selected_stream,
int num_spatial_layers,
int selected_sl,
InterLayerPredMode inter_layer_pred,
const std::vector<std::string>& sl_descriptors) {
if (params->ss[video_idx].streams.empty() &&
params->ss[video_idx].infer_streams) {
@ -1356,6 +1359,7 @@ void VideoQualityTest::FillScalabilitySettings(
params->ss[video_idx].selected_stream = selected_stream;
params->ss[video_idx].selected_sl = selected_sl;
params->ss[video_idx].inter_layer_pred = inter_layer_pred;
RTC_CHECK(params->ss[video_idx].spatial_layers.empty());
for (auto descriptor : sl_descriptors) {
if (descriptor.empty())
@ -1533,6 +1537,7 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
params_.video[video_idx].num_temporal_layers);
vp9_settings.numberOfSpatialLayers = static_cast<unsigned char>(
params_.ss[video_idx].num_spatial_layers);
vp9_settings.interLayerPred = params_.ss[video_idx].inter_layer_pred;
video_encoder_configs_[video_idx].encoder_specific_settings =
new rtc::RefCountedObject<
VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
@ -1545,6 +1550,7 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
params_.video[video_idx].num_temporal_layers);
vp9_settings.numberOfSpatialLayers =
static_cast<unsigned char>(params_.ss[video_idx].num_spatial_layers);
vp9_settings.interLayerPred = params_.ss[video_idx].inter_layer_pred;
video_encoder_configs_[video_idx].encoder_specific_settings =
new rtc::RefCountedObject<
VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);

View File

@ -82,6 +82,7 @@ class VideoQualityTest : public test::CallTest {
size_t selected_stream;
int num_spatial_layers;
int selected_sl;
InterLayerPredMode inter_layer_pred;
// If empty, bitrates are generated in VP9Impl automatically.
std::vector<SpatialLayer> spatial_layers;
// If set, default parameters will be used instead of |streams|.
@ -109,6 +110,7 @@ class VideoQualityTest : public test::CallTest {
size_t selected_stream,
int num_spatial_layers,
int selected_sl,
InterLayerPredMode inter_layer_pred,
const std::vector<std::string>& sl_descriptors);
protected: