Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(899)

Unified Diff: webrtc/call/bitrate_allocator.cc

Issue 2996643002: BWE allocation strategy
Patch Set: BWE allocation strategy Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/call/bitrate_allocator.cc
diff --git a/webrtc/call/bitrate_allocator.cc b/webrtc/call/bitrate_allocator.cc
index 2eb40b0670813c008b1b594541fc1e12147e47e9..5b18253a031f829a1ac8b073037402fcb1ae67af 100644
--- a/webrtc/call/bitrate_allocator.cc
+++ b/webrtc/call/bitrate_allocator.cc
@@ -16,6 +16,7 @@
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/rtc_base/checks.h"
+#include "webrtc/rtc_base/helpers.h"
#include "webrtc/rtc_base/logging.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/system_wrappers/include/metrics.h"
@@ -56,7 +57,8 @@ BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
clock_(Clock::GetRealTimeClock()),
last_bwe_log_time_(0),
total_requested_padding_bitrate_(0),
- total_requested_min_bitrate_(0) {
+ total_requested_min_bitrate_(0),
+ bitrate_allocation_strategy_(nullptr) {
sequenced_checker_.Detach();
}
@@ -86,36 +88,36 @@ void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
- for (auto& config : bitrate_observer_configs_) {
- uint32_t allocated_bitrate = allocation[config.observer];
- uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
- allocated_bitrate, last_fraction_loss_, last_rtt_,
- last_bwe_period_ms_);
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* config = static_cast<ObserverConfig*>(track_config.get());
+ uint32_t allocated_bitrate = allocation[config->observer];
+ uint32_t protection_bitrate = config->observer->OnBitrateUpdated(
+ allocated_bitrate, last_fraction_loss_, last_rtt_, last_bwe_period_ms_);
- if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
+ if (allocated_bitrate == 0 && config->allocated_bitrate_bps > 0) {
if (target_bitrate_bps > 0)
++num_pause_events_;
// The protection bitrate is an estimate based on the ratio between media
// and protection used before this observer was muted.
uint32_t predicted_protection_bps =
- (1.0 - config.media_ratio) * config.min_bitrate_bps;
- LOG(LS_INFO) << "Pausing observer " << config.observer
- << " with configured min bitrate " << config.min_bitrate_bps
+ (1.0 - config->media_ratio) * config->min_bitrate_bps;
+ LOG(LS_INFO) << "Pausing observer " << config->observer
+ << " with configured min bitrate " << config->min_bitrate_bps
<< " and current estimate of " << target_bitrate_bps
<< " and protection bitrate " << predicted_protection_bps;
- } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
+ } else if (allocated_bitrate > 0 && config->allocated_bitrate_bps == 0) {
if (target_bitrate_bps > 0)
++num_pause_events_;
- LOG(LS_INFO) << "Resuming observer " << config.observer
- << ", configured min bitrate " << config.min_bitrate_bps
+ LOG(LS_INFO) << "Resuming observer " << config->observer
+ << ", configured min bitrate " << config->min_bitrate_bps
<< ", current allocation " << allocated_bitrate
<< " and protection bitrate " << protection_bitrate;
}
// Only update the media ratio if the observer got an allocation.
if (allocated_bitrate > 0)
- config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
- config.allocated_bitrate_bps = allocated_bitrate;
+ config->media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
+ config->allocated_bitrate_bps = allocated_bitrate;
}
UpdateAllocationLimits();
}
@@ -129,30 +131,53 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
auto it = FindObserverConfig(observer);
+ // Track IDs are used by custom allocation strategies. Track IDs may be either
+ // empty or unique. Empty track IDs will be replaced with the random strings.
+ // The strategy will not be able to handle track without ID specifically
+ // but it will be able to handle it in some general way. For example a
+ // strategy giving priotiry to audio streams will consider a stream
+ // without an ID as a non-audio streams and will allocate bitrate for it
+ // after required minimum allocated for audio.
+ // Track IDs have ot be unique because strategy returns allocations mapped by
+ // track ID (it is not aware of observers).
+ std::string unique_track_id = track_id;
+ if (unique_track_id.size() == 0) {
+ unique_track_id = rtc::CreateRandomString(8);
+ while (track_ids.count(unique_track_id)) {
+ unique_track_id = rtc::CreateRandomString(8);
+ }
+ }
// Update settings if the observer already exists, create a new one otherwise.
if (it != bitrate_observer_configs_.end()) {
- it->min_bitrate_bps = min_bitrate_bps;
- it->max_bitrate_bps = max_bitrate_bps;
- it->pad_up_bitrate_bps = pad_up_bitrate_bps;
- it->enforce_min_bitrate = enforce_min_bitrate;
+ ObserverConfig* observer_config = static_cast<ObserverConfig*>(it->get());
+ observer_config->min_bitrate_bps = min_bitrate_bps;
+ observer_config->max_bitrate_bps = max_bitrate_bps;
+ observer_config->pad_up_bitrate_bps = pad_up_bitrate_bps;
+ observer_config->enforce_min_bitrate = enforce_min_bitrate;
+ RTC_DCHECK(track_ids.count(unique_track_id) == 0 ||
+ observer_config->track_id == unique_track_id);
+ observer_config->track_id = unique_track_id;
} else {
- bitrate_observer_configs_.push_back(
- ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
- pad_up_bitrate_bps, enforce_min_bitrate, track_id));
+ RTC_DCHECK(track_ids.count(unique_track_id) == 0);
+ bitrate_observer_configs_.emplace_back(new ObserverConfig(
+ observer, min_bitrate_bps, max_bitrate_bps, pad_up_bitrate_bps,
+ enforce_min_bitrate, unique_track_id));
}
+ track_ids.insert(unique_track_id);
ObserverAllocation allocation;
if (last_bitrate_bps_ > 0) {
// Calculate a new allocation and update all observers.
allocation = AllocateBitrates(last_bitrate_bps_);
- for (auto& config : bitrate_observer_configs_) {
- uint32_t allocated_bitrate = allocation[config.observer];
- uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
+ for (auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* config = static_cast<ObserverConfig*>(track_config.get());
+ uint32_t allocated_bitrate = allocation[config->observer];
+ uint32_t protection_bitrate = config->observer->OnBitrateUpdated(
allocated_bitrate, last_fraction_loss_, last_rtt_,
last_bwe_period_ms_);
- config.allocated_bitrate_bps = allocated_bitrate;
+ config->allocated_bitrate_bps = allocated_bitrate;
if (allocated_bitrate > 0)
- config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
+ config->media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
}
} else {
// Currently, an encoder is not allowed to produce frames.
@@ -170,13 +195,14 @@ void BitrateAllocator::UpdateAllocationLimits() {
uint32_t total_requested_padding_bitrate = 0;
uint32_t total_requested_min_bitrate = 0;
- for (const auto& config : bitrate_observer_configs_) {
- uint32_t stream_padding = config.pad_up_bitrate_bps;
- if (config.enforce_min_bitrate) {
- total_requested_min_bitrate += config.min_bitrate_bps;
- } else if (config.allocated_bitrate_bps == 0) {
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* config = static_cast<ObserverConfig*>(track_config.get());
+ uint32_t stream_padding = config->pad_up_bitrate_bps;
+ if (config->enforce_min_bitrate) {
+ total_requested_min_bitrate += config->min_bitrate_bps;
+ } else if (config->allocated_bitrate_bps == 0) {
stream_padding =
- std::max(MinBitrateWithHysteresis(config), stream_padding);
+ std::max(MinBitrateWithHysteresis(*config), stream_padding);
}
total_requested_padding_bitrate += stream_padding;
}
@@ -201,6 +227,7 @@ void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
auto it = FindObserverConfig(observer);
if (it != bitrate_observer_configs_.end()) {
+ track_ids.erase((*it)->track_id);
bitrate_observer_configs_.erase(it);
}
@@ -210,26 +237,35 @@ void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
const auto& it = FindObserverConfig(observer);
+ ObserverConfig* config = static_cast<ObserverConfig*>(it->get());
if (it == bitrate_observer_configs_.end()) {
// This observer hasn't been added yet, just give it its fair share.
return last_non_zero_bitrate_bps_ /
static_cast<int>((bitrate_observer_configs_.size() + 1));
- } else if (it->allocated_bitrate_bps == -1) {
+ } else if (config->allocated_bitrate_bps == -1) {
// This observer hasn't received an allocation yet, so do the same.
return last_non_zero_bitrate_bps_ /
static_cast<int>(bitrate_observer_configs_.size());
} else {
// This observer already has an allocation.
- return it->allocated_bitrate_bps;
+ return config->allocated_bitrate_bps;
}
}
-BitrateAllocator::ObserverConfigs::iterator
+void BitrateAllocator::SetBitrateAllocationStrategy(
+ rtc::scoped_refptr<rtc::BitrateAllocationStrategy>
+ bitrate_allocation_strategy) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
+ bitrate_allocation_strategy_ = bitrate_allocation_strategy;
+}
+
+rtc::BitrateAllocationStrategy::TrackConfigs::iterator
BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
for (auto it = bitrate_observer_configs_.begin();
it != bitrate_observer_configs_.end(); ++it) {
- if (it->observer == observer)
+ ObserverConfig* config = static_cast<ObserverConfig*>(it->get());
+ if (config->observer == observer)
return it;
}
return bitrate_observer_configs_.end();
@@ -241,14 +277,33 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
if (bitrate_observer_configs_.empty())
return ObserverAllocation();
+ if (bitrate_allocation_strategy_ != nullptr) {
+ rtc::BitrateAllocationStrategy::TrackAllocations track_allocations =
+ bitrate_allocation_strategy_->AllocateBitrates(
+ bitrate, bitrate_observer_configs_);
+ ObserverAllocation allocation;
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
+ // The strategy should return allocation for all tracks.
+ // In release builds still may be better to use zero allocation
+ // rathen than crash
+ RTC_DCHECK(track_allocations.find(observer_config->track_id) !=
+ track_allocations.end());
+ allocation[observer_config->observer] =
+ track_allocations[observer_config->track_id];
+ }
+ return allocation;
+ }
+
if (bitrate == 0)
return ZeroRateAllocation();
uint32_t sum_min_bitrates = 0;
uint32_t sum_max_bitrates = 0;
for (const auto& observer_config : bitrate_observer_configs_) {
- sum_min_bitrates += observer_config.min_bitrate_bps;
- sum_max_bitrates += observer_config.max_bitrate_bps;
+ sum_min_bitrates += observer_config->min_bitrate_bps;
+ sum_max_bitrates += observer_config->max_bitrate_bps;
}
// Not enough for all observers to get an allocation, allocate according to:
@@ -268,8 +323,11 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
ObserverAllocation allocation;
- for (const auto& observer_config : bitrate_observer_configs_)
- allocation[observer_config.observer] = 0;
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
+ allocation[observer_config->observer] = 0;
+ }
return allocation;
}
@@ -280,25 +338,29 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
// Start by allocating bitrate to observers enforcing a min bitrate, hence
// remaining_bitrate might turn negative.
int64_t remaining_bitrate = bitrate;
- for (const auto& observer_config : bitrate_observer_configs_) {
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
int32_t allocated_bitrate = 0;
- if (observer_config.enforce_min_bitrate)
- allocated_bitrate = observer_config.min_bitrate_bps;
+ if (observer_config->enforce_min_bitrate)
+ allocated_bitrate = observer_config->min_bitrate_bps;
- allocation[observer_config.observer] = allocated_bitrate;
+ allocation[observer_config->observer] = allocated_bitrate;
remaining_bitrate -= allocated_bitrate;
}
// Allocate bitrate to all previously active streams.
if (remaining_bitrate > 0) {
- for (const auto& observer_config : bitrate_observer_configs_) {
- if (observer_config.enforce_min_bitrate ||
- LastAllocatedBitrate(observer_config) == 0)
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
+ if (observer_config->enforce_min_bitrate ||
+ LastAllocatedBitrate(*observer_config) == 0)
continue;
- uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
+ uint32_t required_bitrate = MinBitrateWithHysteresis(*observer_config);
if (remaining_bitrate >= required_bitrate) {
- allocation[observer_config.observer] = required_bitrate;
+ allocation[observer_config->observer] = required_bitrate;
remaining_bitrate -= required_bitrate;
}
}
@@ -306,14 +368,16 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
// Allocate bitrate to previously paused streams.
if (remaining_bitrate > 0) {
- for (const auto& observer_config : bitrate_observer_configs_) {
- if (LastAllocatedBitrate(observer_config) != 0)
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
+ if (LastAllocatedBitrate(*observer_config) != 0)
continue;
// Add a hysteresis to avoid toggling.
- uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
+ uint32_t required_bitrate = MinBitrateWithHysteresis(*observer_config);
if (remaining_bitrate >= required_bitrate) {
- allocation[observer_config.observer] = required_bitrate;
+ allocation[observer_config->observer] = required_bitrate;
remaining_bitrate -= required_bitrate;
}
}
@@ -332,8 +396,11 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
uint32_t sum_min_bitrates) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
ObserverAllocation allocation;
- for (const auto& observer_config : bitrate_observer_configs_)
- allocation[observer_config.observer] = observer_config.min_bitrate_bps;
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
+ allocation[observer_config->observer] = observer_config->min_bitrate_bps;
+ }
bitrate -= sum_min_bitrates;
if (bitrate > 0)
@@ -348,9 +415,11 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
ObserverAllocation allocation;
- for (const auto& observer_config : bitrate_observer_configs_) {
- allocation[observer_config.observer] = observer_config.max_bitrate_bps;
- bitrate -= observer_config.max_bitrate_bps;
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
+ allocation[observer_config->observer] = observer_config->max_bitrate_bps;
+ bitrate -= observer_config->max_bitrate_bps;
}
DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
&allocation);
@@ -394,11 +463,13 @@ void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
ObserverSortingMap list_max_bitrates;
- for (const auto& observer_config : bitrate_observer_configs_) {
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
if (include_zero_allocations ||
- allocation->at(observer_config.observer) != 0) {
- list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
- observer_config.max_bitrate_bps, &observer_config));
+ allocation->at(observer_config->observer) != 0) {
+ list_max_bitrates.insert(std::pair<uint32_t, ObserverConfig*>(
+ observer_config->max_bitrate_bps, observer_config));
}
}
auto it = list_max_bitrates.begin();
@@ -430,9 +501,11 @@ bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
uint32_t extra_bitrate_per_observer =
(bitrate - sum_min_bitrates) /
static_cast<uint32_t>(bitrate_observer_configs_.size());
- for (const auto& observer_config : bitrate_observer_configs_) {
- if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
- MinBitrateWithHysteresis(observer_config)) {
+ for (const auto& track_config : bitrate_observer_configs_) {
+ ObserverConfig* observer_config =
+ static_cast<ObserverConfig*>(track_config.get());
+ if (observer_config->min_bitrate_bps + extra_bitrate_per_observer <
+ MinBitrateWithHysteresis(*observer_config)) {
return false;
}
}

Powered by Google App Engine
This is Rietveld 408576698