Don't pad to min bitrate for streams with alr probing enabled

Especially for simulcast screensharing, we don't want to send constant
high bitrates of padding just to keep the bwe up since ALR probing
already handles that case.

Bug: webrtc:9734
Change-Id: I79a08fc073844628d8ad0561edd8bfcffed83fde
Reviewed-on: https://webrtc-review.googlesource.com/99120
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24734}
This commit is contained in:
Erik Språng
2018-09-13 10:52:38 +02:00
committed by Commit Bot
parent c5fe166dbc
commit b57ab38a8c
3 changed files with 170 additions and 20 deletions

View File

@ -76,19 +76,35 @@ int GetEncoderMinBitrateBps() {
kDefaultEncoderMinBitrateBps);
}
int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
int min_transmit_bitrate_bps,
bool pad_to_min_bitrate) {
int pad_up_to_bitrate_bps = 0;
// Calculate max padding bitrate for a multi layer codec.
if (streams.size() > 1) {
int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams,
int min_transmit_bitrate_bps,
bool pad_to_min_bitrate,
bool alr_probing) {
int pad_up_to_bitrate_bps = 0;
// Filter out only the active streams;
std::vector<VideoStream> active_streams;
for (const VideoStream& stream : streams) {
if (stream.active)
active_streams.emplace_back(stream);
}
if (active_streams.size() > 1) {
if (alr_probing) {
// With alr probing, just pad to the min bitrate of the lowest stream,
// probing will handle the rest of the rampup.
pad_up_to_bitrate_bps = active_streams[0].min_bitrate_bps;
} else {
// Pad to min bitrate of the highest layer.
pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
pad_up_to_bitrate_bps =
active_streams[active_streams.size() - 1].min_bitrate_bps;
// Add target_bitrate_bps of the lower layers.
for (size_t i = 0; i < streams.size() - 1; ++i)
pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
} else if (pad_to_min_bitrate) {
pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
for (size_t i = 0; i < active_streams.size() - 1; ++i)
pad_up_to_bitrate_bps += active_streams[i].target_bitrate_bps;
}
} else if (!active_streams.empty() && pad_to_min_bitrate) {
pad_up_to_bitrate_bps = active_streams[0].min_bitrate_bps;
}
pad_up_to_bitrate_bps =
@ -130,6 +146,16 @@ RtpSenderObservers CreateObservers(CallStats* call_stats,
observers.overhead_observer = overhead_observer;
return observers;
}
absl::optional<AlrExperimentSettings> GetAlrSettings(
VideoEncoderConfig::ContentType content_type) {
if (content_type == VideoEncoderConfig::ContentType::kScreen) {
return AlrExperimentSettings::CreateFromFieldTrial(
AlrExperimentSettings::kScreenshareProbingBweExperimentName);
}
return AlrExperimentSettings::CreateFromFieldTrial(
AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
}
} // namespace
// CheckEncoderActivityTask is used for tracking when the encoder last produced
@ -202,6 +228,8 @@ VideoSendStreamImpl::VideoSendStreamImpl(
std::unique_ptr<FecController> fec_controller)
: send_side_bwe_with_overhead_(
webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
has_alr_probing_(config->periodic_alr_bandwidth_probing ||
GetAlrSettings(content_type)),
stats_proxy_(stats_proxy),
config_(config),
fec_controller_(std::move(fec_controller)),
@ -268,14 +296,8 @@ VideoSendStreamImpl::VideoSendStreamImpl(
if (TransportSeqNumExtensionConfigured(*config_)) {
has_packet_feedback_ = true;
absl::optional<AlrExperimentSettings> alr_settings;
if (content_type == VideoEncoderConfig::ContentType::kScreen) {
alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
AlrExperimentSettings::kScreenshareProbingBweExperimentName);
} else {
alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
}
absl::optional<AlrExperimentSettings> alr_settings =
GetAlrSettings(content_type);
if (alr_settings) {
transport->EnablePeriodicAlrProbing(true);
transport->SetPacingFactor(alr_settings->pacing_factor);
@ -491,7 +513,8 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
max_padding_bitrate_ = streams[0].target_bitrate_bps;
} else {
max_padding_bitrate_ = CalculateMaxPadBitrateBps(
streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate,
has_alr_probing_);
}
// Clear stats for disabled layers.

View File

@ -136,6 +136,7 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
void SignalEncoderActive();
const bool send_side_bwe_with_overhead_;
const bool has_alr_probing_;
SendStatisticsProxy* const stats_proxy_;
const VideoSendStream::Config* const config_;

View File

@ -166,6 +166,132 @@ TEST_F(VideoSendStreamImplTest, RegistersAsBitrateObserverOnStart) {
});
}
TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChange) {
test_queue_.SendTask([this] {
config_.track_id = "test";
const bool kSuspend = false;
config_.suspend_below_min_bitrate = kSuspend;
config_.rtp.extensions.emplace_back(
RtpExtension::kTransportSequenceNumberUri, 1);
auto vss_impl = CreateVideoSendStreamImpl(
kDefaultInitialBitrateBps, kDefaultBitratePriority,
VideoEncoderConfig::ContentType::kRealtimeVideo);
vss_impl->Start();
// QVGA + VGA configuration matching defaults in media/engine/simulcast.cc.
VideoStream qvga_stream;
qvga_stream.width = 320;
qvga_stream.height = 180;
qvga_stream.max_framerate = 30;
qvga_stream.min_bitrate_bps = 30000;
qvga_stream.target_bitrate_bps = 150000;
qvga_stream.max_bitrate_bps = 200000;
qvga_stream.max_qp = 56;
qvga_stream.bitrate_priority = 1;
VideoStream vga_stream;
vga_stream.width = 640;
vga_stream.height = 360;
vga_stream.max_framerate = 30;
vga_stream.min_bitrate_bps = 150000;
vga_stream.target_bitrate_bps = 500000;
vga_stream.max_bitrate_bps = 700000;
vga_stream.max_qp = 56;
vga_stream.bitrate_priority = 1;
int min_transmit_bitrate_bps = 30000;
config_.rtp.ssrcs.emplace_back(1);
config_.rtp.ssrcs.emplace_back(2);
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
.WillOnce(Invoke(
[&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
EXPECT_EQ(config.min_bitrate_bps,
static_cast<uint32_t>(min_transmit_bitrate_bps));
EXPECT_EQ(config.max_bitrate_bps,
static_cast<uint32_t>(qvga_stream.max_bitrate_bps +
vga_stream.max_bitrate_bps));
EXPECT_EQ(config.pad_up_bitrate_bps,
static_cast<uint32_t>(qvga_stream.target_bitrate_bps +
vga_stream.min_bitrate_bps));
EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
EXPECT_EQ(config.has_packet_feedback, true);
}));
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
->OnEncoderConfigurationChanged(
std::vector<VideoStream>{qvga_stream, vga_stream},
min_transmit_bitrate_bps);
vss_impl->Stop();
});
}
TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChangeWithAlr) {
test_queue_.SendTask([this] {
config_.track_id = "test";
const bool kSuspend = false;
config_.suspend_below_min_bitrate = kSuspend;
config_.rtp.extensions.emplace_back(
RtpExtension::kTransportSequenceNumberUri, 1);
config_.periodic_alr_bandwidth_probing = true;
auto vss_impl = CreateVideoSendStreamImpl(
kDefaultInitialBitrateBps, kDefaultBitratePriority,
VideoEncoderConfig::ContentType::kScreen);
vss_impl->Start();
// Simulcast screenshare.
VideoStream low_stream;
low_stream.width = 1920;
low_stream.height = 1080;
low_stream.max_framerate = 5;
low_stream.min_bitrate_bps = 30000;
low_stream.target_bitrate_bps = 200000;
low_stream.max_bitrate_bps = 1000000;
low_stream.num_temporal_layers = 2;
low_stream.max_qp = 56;
low_stream.bitrate_priority = 1;
VideoStream high_stream;
high_stream.width = 1920;
high_stream.height = 1080;
high_stream.max_framerate = 30;
high_stream.min_bitrate_bps = 60000;
high_stream.target_bitrate_bps = 1250000;
high_stream.max_bitrate_bps = 1250000;
high_stream.num_temporal_layers = 2;
high_stream.max_qp = 56;
high_stream.bitrate_priority = 1;
// With ALR probing, this will be the padding target instead of
// low_stream.target_bitrate_bps + high_stream.min_bitrate_bps.
int min_transmit_bitrate_bps = 400000;
config_.rtp.ssrcs.emplace_back(1);
config_.rtp.ssrcs.emplace_back(2);
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
.WillOnce(Invoke(
[&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
EXPECT_EQ(config.min_bitrate_bps,
static_cast<uint32_t>(low_stream.min_bitrate_bps));
EXPECT_EQ(config.max_bitrate_bps,
static_cast<uint32_t>(low_stream.max_bitrate_bps +
high_stream.max_bitrate_bps));
EXPECT_EQ(config.pad_up_bitrate_bps,
static_cast<uint32_t>(min_transmit_bitrate_bps));
EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
EXPECT_EQ(config.has_packet_feedback, true);
}));
static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
->OnEncoderConfigurationChanged(
std::vector<VideoStream>{low_stream, high_stream},
min_transmit_bitrate_bps);
vss_impl->Stop();
});
}
TEST_F(VideoSendStreamImplTest, ReportFeedbackAvailability) {
test_queue_.SendTask([this] {
config_.rtp.extensions.emplace_back(