Adds audio priority bitrate field trial parameter.
This replaces the functionality provided by
AudioPriorityBitrateAllocationStrategy, removing the need provide that
component via injection in all clients using audio bitrate priority.
Bug: webrtc:10286
Change-Id: I3bafab56d24459d9d27dc07abffdc8538440a346
Reviewed-on: https://webrtc-review.googlesource.com/c/121402
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26651}
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index baf51b2..8ced40e 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -785,10 +785,11 @@
config_.bitrate_priority = bitrate_priority;
// This either updates the current observer or adds a new observer.
bitrate_allocator_->AddObserver(
- this,
- MediaStreamAllocationConfig{static_cast<uint32_t>(min_bitrate_bps),
- static_cast<uint32_t>(max_bitrate_bps), 0,
- true, config_.track_id, bitrate_priority});
+ this, MediaStreamAllocationConfig{
+ static_cast<uint32_t>(min_bitrate_bps),
+ static_cast<uint32_t>(max_bitrate_bps), 0,
+ allocation_settings_.DefaultPriorityBitrate().bps(), true,
+ config_.track_id, bitrate_priority});
thread_sync_event.Set();
});
thread_sync_event.Wait(rtc::Event::kForever);
diff --git a/call/bitrate_allocator.cc b/call/bitrate_allocator.cc
index 06b74ba..21939a7 100644
--- a/call/bitrate_allocator.cc
+++ b/call/bitrate_allocator.cc
@@ -174,10 +174,10 @@
it->enforce_min_bitrate = config.enforce_min_bitrate;
it->bitrate_priority = config.bitrate_priority;
} else {
- bitrate_observer_configs_.push_back(
- ObserverConfig(observer, config.min_bitrate_bps, config.max_bitrate_bps,
- config.pad_up_bitrate_bps, config.enforce_min_bitrate,
- config.track_id, config.bitrate_priority));
+ bitrate_observer_configs_.push_back(ObserverConfig(
+ observer, config.min_bitrate_bps, config.max_bitrate_bps,
+ config.pad_up_bitrate_bps, config.priority_bitrate_bps,
+ config.enforce_min_bitrate, config.track_id, config.bitrate_priority));
}
if (last_target_bps_ > 0) {
@@ -439,6 +439,21 @@
}
bitrate -= sum_min_bitrates;
+
+ // TODO(srte): Implement fair sharing between prioritized streams, currently
+ // they are treated on a first come first serve basis.
+ for (const auto& observer_config : bitrate_observer_configs_) {
+ int64_t priority_margin = observer_config.priority_bitrate_bps -
+ allocation[observer_config.observer];
+ if (priority_margin > 0 && bitrate > 0) {
+ int64_t extra_bitrate = std::min<int64_t>(priority_margin, bitrate);
+ allocation[observer_config.observer] +=
+ rtc::dchecked_cast<int>(extra_bitrate);
+ observers_capacities[observer_config.observer] -= extra_bitrate;
+ bitrate -= extra_bitrate;
+ }
+ }
+
// From the remaining bitrate, allocate a proportional amount to each observer
// above the min bitrate already allocated.
if (bitrate > 0)
diff --git a/call/bitrate_allocator.h b/call/bitrate_allocator.h
index 1323aa3..43e89b2 100644
--- a/call/bitrate_allocator.h
+++ b/call/bitrate_allocator.h
@@ -55,6 +55,7 @@
uint32_t min_bitrate_bps;
uint32_t max_bitrate_bps;
uint32_t pad_up_bitrate_bps;
+ int64_t priority_bitrate_bps;
bool enforce_min_bitrate;
std::string track_id;
double bitrate_priority;
@@ -128,6 +129,7 @@
uint32_t min_bitrate_bps,
uint32_t max_bitrate_bps,
uint32_t pad_up_bitrate_bps,
+ int64_t priority_bitrate_bps,
bool enforce_min_bitrate,
std::string track_id,
double bitrate_priority)
@@ -137,12 +139,14 @@
track_id),
observer(observer),
pad_up_bitrate_bps(pad_up_bitrate_bps),
+ priority_bitrate_bps(priority_bitrate_bps),
allocated_bitrate_bps(-1),
media_ratio(1.0),
bitrate_priority(bitrate_priority) {}
BitrateAllocatorObserver* observer;
uint32_t pad_up_bitrate_bps;
+ int64_t priority_bitrate_bps;
int64_t allocated_bitrate_bps;
double media_ratio; // Part of the total bitrate used for media [0.0, 1.0].
// The amount of bitrate allocated to this observer relative to all other
diff --git a/call/bitrate_allocator_unittest.cc b/call/bitrate_allocator_unittest.cc
index 9956a88..33747ef 100644
--- a/call/bitrate_allocator_unittest.cc
+++ b/call/bitrate_allocator_unittest.cc
@@ -100,13 +100,60 @@
double bitrate_priority) {
allocator_->AddObserver(
observer, {min_bitrate_bps, max_bitrate_bps, pad_up_bitrate_bps,
- enforce_min_bitrate, track_id, bitrate_priority});
+ /* priority_bitrate */ 0, enforce_min_bitrate, track_id,
+ bitrate_priority});
+ }
+ MediaStreamAllocationConfig DefaultConfig() const {
+ MediaStreamAllocationConfig default_config;
+ default_config.min_bitrate_bps = 0;
+ default_config.max_bitrate_bps = 1500000;
+ default_config.pad_up_bitrate_bps = 0;
+ default_config.priority_bitrate_bps = 0;
+ default_config.enforce_min_bitrate = true;
+ default_config.track_id = "";
+ default_config.bitrate_priority = kDefaultBitratePriority;
+ return default_config;
}
NiceMock<MockLimitObserver> limit_observer_;
std::unique_ptr<BitrateAllocatorForTest> allocator_;
};
+TEST_F(BitrateAllocatorTest, RespectsPriorityBitrate) {
+ TestBitrateObserver stream_a;
+ auto config_a = DefaultConfig();
+ config_a.min_bitrate_bps = 100000;
+ config_a.priority_bitrate_bps = 0;
+ allocator_->AddObserver(&stream_a, config_a);
+
+ TestBitrateObserver stream_b;
+ auto config_b = DefaultConfig();
+ config_b.min_bitrate_bps = 100000;
+ config_b.max_bitrate_bps = 300000;
+ config_b.priority_bitrate_bps = 300000;
+ allocator_->AddObserver(&stream_b, config_b);
+
+ allocator_->OnNetworkChanged(100000, 0, 0, 0);
+ EXPECT_EQ(stream_a.last_bitrate_bps_, 100000u);
+ EXPECT_EQ(stream_b.last_bitrate_bps_, 100000u);
+
+ allocator_->OnNetworkChanged(200000, 0, 0, 0);
+ EXPECT_EQ(stream_a.last_bitrate_bps_, 100000u);
+ EXPECT_EQ(stream_b.last_bitrate_bps_, 100000u);
+
+ allocator_->OnNetworkChanged(300000, 0, 0, 0);
+ EXPECT_EQ(stream_a.last_bitrate_bps_, 100000u);
+ EXPECT_EQ(stream_b.last_bitrate_bps_, 200000u);
+
+ allocator_->OnNetworkChanged(400000, 0, 0, 0);
+ EXPECT_EQ(stream_a.last_bitrate_bps_, 100000u);
+ EXPECT_EQ(stream_b.last_bitrate_bps_, 300000u);
+
+ allocator_->OnNetworkChanged(800000, 0, 0, 0);
+ EXPECT_EQ(stream_a.last_bitrate_bps_, 500000u);
+ EXPECT_EQ(stream_b.last_bitrate_bps_, 300000u);
+}
+
TEST_F(BitrateAllocatorTest, UpdatingBitrateObserver) {
TestBitrateObserver bitrate_observer;
const uint32_t kMinSendBitrateBps = 100000;
@@ -232,7 +279,7 @@
std::string track_id,
double bitrate_priority) {
allocator_->AddObserver(
- observer, {min_bitrate_bps, max_bitrate_bps, pad_up_bitrate_bps,
+ observer, {min_bitrate_bps, max_bitrate_bps, pad_up_bitrate_bps, 0,
enforce_min_bitrate, track_id, bitrate_priority});
}
NiceMock<MockLimitObserver> limit_observer_;
@@ -404,9 +451,10 @@
EXPECT_CALL(limit_observer_,
OnAllocationLimitsChanged(kMinBitrateBps, 0, kMaxBitrateBps))
.Times(1);
- allocator_->AddObserver(
- &bitrate_observer,
- {kMinBitrateBps, kMaxBitrateBps, 0, true, "", kDefaultBitratePriority});
+ MediaStreamAllocationConfig allocation_config = DefaultConfig();
+ allocation_config.min_bitrate_bps = kMinBitrateBps;
+ allocation_config.max_bitrate_bps = kMaxBitrateBps;
+ allocator_->AddObserver(&bitrate_observer, allocation_config);
// Observer uses 20% of it's allocated bitrate for protection.
bitrate_observer.SetBitrateProtectionRatio(/*protection_ratio=*/0.2);
diff --git a/rtc_base/experiments/audio_allocation_settings.cc b/rtc_base/experiments/audio_allocation_settings.cc
index 51c8591..79c5a0d 100644
--- a/rtc_base/experiments/audio_allocation_settings.cc
+++ b/rtc_base/experiments/audio_allocation_settings.cc
@@ -15,13 +15,18 @@
// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
const int kOpusMinBitrateBps = 6000;
const int kOpusBitrateFbBps = 32000;
+// OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
+constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
} // namespace
AudioAllocationSettings::AudioAllocationSettings()
: audio_send_side_bwe_("Enabled"),
allocate_audio_without_feedback_("Enabled"),
force_no_audio_feedback_("Enabled"),
audio_feedback_to_improve_video_bwe_("Enabled"),
- send_side_bwe_with_overhead_("Enabled") {
+ send_side_bwe_with_overhead_("Enabled"),
+ default_min_bitrate_("min", DataRate::bps(kOpusMinBitrateBps)),
+ default_max_bitrate_("max", DataRate::bps(kOpusBitrateFbBps)),
+ priority_bitrate_("prio", DataRate::Zero()) {
ParseFieldTrial({&audio_send_side_bwe_},
field_trial::FindFullName("WebRTC-Audio-SendSideBwe"));
ParseFieldTrial({&allocate_audio_without_feedback_},
@@ -31,16 +36,17 @@
ParseFieldTrial(
{&audio_feedback_to_improve_video_bwe_},
field_trial::FindFullName("WebRTC-Audio-SendSideBwe-For-Video"));
+
ParseFieldTrial({&send_side_bwe_with_overhead_},
field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead"));
+ ParseFieldTrial(
+ {&default_min_bitrate_, &default_max_bitrate_, &priority_bitrate_},
+ field_trial::FindFullName("WebRTC-Audio-Allocation"));
// TODO(mflodman): Keep testing this and set proper values.
// Note: This is an early experiment currently only supported by Opus.
if (send_side_bwe_with_overhead_) {
constexpr int kMaxPacketSizeMs = WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
-
- // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
- constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
min_overhead_bps_ = kOverheadPerPacket * 8 * 1000 / kMaxPacketSizeMs;
}
}
@@ -116,7 +122,7 @@
}
int AudioAllocationSettings::MinBitrateBps() const {
- return kOpusMinBitrateBps + min_overhead_bps_;
+ return default_min_bitrate_->bps() + min_overhead_bps_;
}
int AudioAllocationSettings::MaxBitrateBps(
@@ -133,6 +139,15 @@
// meanwhile change the cap to the output of BWE.
if (rtp_parameter_max_bitrate_bps)
return *rtp_parameter_max_bitrate_bps + min_overhead_bps_;
- return kOpusBitrateFbBps + min_overhead_bps_;
+ return default_max_bitrate_->bps() + min_overhead_bps_;
}
+DataRate AudioAllocationSettings::DefaultPriorityBitrate() const {
+ DataRate max_overhead = DataRate::Zero();
+ if (send_side_bwe_with_overhead_) {
+ const TimeDelta kMinPacketDuration = TimeDelta::ms(20);
+ max_overhead = DataSize::bytes(kOverheadPerPacket) / kMinPacketDuration;
+ }
+ return priority_bitrate_.Get() + max_overhead;
+}
+
} // namespace webrtc
diff --git a/rtc_base/experiments/audio_allocation_settings.h b/rtc_base/experiments/audio_allocation_settings.h
index a932c13..bcc0f3e 100644
--- a/rtc_base/experiments/audio_allocation_settings.h
+++ b/rtc_base/experiments/audio_allocation_settings.h
@@ -75,6 +75,10 @@
// overhead. |rtp_parameter_max_bitrate_bps| max bitrate as configured in rtp
// parameters, excluding overhead.
int MaxBitrateBps(absl::optional<int> rtp_parameter_max_bitrate_bps) const;
+ // Indicates the default priority bitrate for audio streams. The bitrate
+ // allocator will prioritize audio until it reaches this bitrate and will
+ // divide bitrate evently between audio and video above this bitrate.
+ DataRate DefaultPriorityBitrate() const;
private:
FieldTrialFlag audio_send_side_bwe_;
@@ -83,6 +87,11 @@
FieldTrialFlag audio_feedback_to_improve_video_bwe_;
FieldTrialFlag send_side_bwe_with_overhead_;
int min_overhead_bps_ = 0;
+ // Default bitrates to use as range if there's no user configured
+ // bitrate range but audio bitrate allocation is enabled.
+ FieldTrialParameter<DataRate> default_min_bitrate_;
+ FieldTrialParameter<DataRate> default_max_bitrate_;
+ FieldTrialParameter<DataRate> priority_bitrate_;
};
} // namespace webrtc
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc
index 5d60a41..b8088ea 100644
--- a/video/video_send_stream_impl.cc
+++ b/video/video_send_stream_impl.cc
@@ -385,13 +385,7 @@
void VideoSendStreamImpl::StartupVideoSendStream() {
RTC_DCHECK_RUN_ON(worker_queue_);
- bitrate_allocator_->AddObserver(
- this,
- MediaStreamAllocationConfig{
- static_cast<uint32_t>(encoder_min_bitrate_bps_),
- encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
- !config_->suspend_below_min_bitrate, config_->track_id,
- encoder_bitrate_priority_});
+ bitrate_allocator_->AddObserver(this, GetAllocationConfig());
// Start monitoring encoder activity.
{
RTC_DCHECK(!check_encoder_activity_task_.Running());
@@ -498,13 +492,18 @@
void VideoSendStreamImpl::SignalEncoderActive() {
RTC_DCHECK_RUN_ON(worker_queue_);
RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
- bitrate_allocator_->AddObserver(
- this,
- MediaStreamAllocationConfig{
- static_cast<uint32_t>(encoder_min_bitrate_bps_),
- encoder_max_bitrate_bps_, static_cast<uint32_t>(max_padding_bitrate_),
- !config_->suspend_below_min_bitrate, config_->track_id,
- encoder_bitrate_priority_});
+ bitrate_allocator_->AddObserver(this, GetAllocationConfig());
+}
+
+MediaStreamAllocationConfig VideoSendStreamImpl::GetAllocationConfig() const {
+ return MediaStreamAllocationConfig{
+ static_cast<uint32_t>(encoder_min_bitrate_bps_),
+ encoder_max_bitrate_bps_,
+ static_cast<uint32_t>(max_padding_bitrate_),
+ /* priority_bitrate */ 0,
+ !config_->suspend_below_min_bitrate,
+ config_->track_id,
+ encoder_bitrate_priority_};
}
void VideoSendStreamImpl::OnEncoderConfigurationChanged(
@@ -571,13 +570,7 @@
if (rtp_video_sender_->IsActive()) {
// The send stream is started already. Update the allocator with new bitrate
// limits.
- bitrate_allocator_->AddObserver(
- this, MediaStreamAllocationConfig{
- static_cast<uint32_t>(encoder_min_bitrate_bps_),
- encoder_max_bitrate_bps_,
- static_cast<uint32_t>(max_padding_bitrate_),
- !config_->suspend_below_min_bitrate, config_->track_id,
- encoder_bitrate_priority_});
+ bitrate_allocator_->AddObserver(this, GetAllocationConfig());
}
}
diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h
index 4c5e3e4..1cdad60 100644
--- a/video/video_send_stream_impl.h
+++ b/video/video_send_stream_impl.h
@@ -139,6 +139,8 @@
void ConfigureSsrcs();
void SignalEncoderTimedOut();
void SignalEncoderActive();
+ MediaStreamAllocationConfig GetAllocationConfig() const
+ RTC_RUN_ON(worker_queue_);
const bool has_alr_probing_;
const PacingConfig pacing_config_;