Skip to content

Commit

Permalink
Don't pad to min bitrate for streams with alr probing enabled
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Niels Moller <[email protected]>
Commit-Queue: Erik Språng <[email protected]>
Cr-Commit-Position: refs/heads/master@{#24734}
  • Loading branch information
Erik Språng authored and Commit Bot committed Sep 13, 2018
1 parent c5fe166 commit b57ab38
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 20 deletions.
63 changes: 43 additions & 20 deletions video/video_send_stream_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions video/video_send_stream_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down
126 changes: 126 additions & 0 deletions video/video_send_stream_impl_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit b57ab38

Please sign in to comment.