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:
@ -76,19 +76,35 @@ int GetEncoderMinBitrateBps() {
|
||||
kDefaultEncoderMinBitrateBps);
|
||||
}
|
||||
|
||||
int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
|
||||
// Calculate max padding bitrate for a multi layer codec.
|
||||
int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams,
|
||||
int min_transmit_bitrate_bps,
|
||||
bool pad_to_min_bitrate) {
|
||||
bool pad_to_min_bitrate,
|
||||
bool alr_probing) {
|
||||
int pad_up_to_bitrate_bps = 0;
|
||||
// Calculate max padding bitrate for a multi layer codec.
|
||||
if (streams.size() > 1) {
|
||||
// Pad to min bitrate of the highest layer.
|
||||
pad_up_to_bitrate_bps = streams[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;
|
||||
|
||||
// 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 =
|
||||
active_streams[active_streams.size() - 1].min_bitrate_bps;
|
||||
// Add target_bitrate_bps of the lower layers.
|
||||
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.
|
||||
|
@ -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_;
|
||||
|
@ -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(
|
||||
|
Reference in New Issue
Block a user