| Index: webrtc/call/bitrate_allocator.cc
|
| diff --git a/webrtc/call/bitrate_allocator.cc b/webrtc/call/bitrate_allocator.cc
|
| index 2eb40b0670813c008b1b594541fc1e12147e47e9..439562b56901af1d1bbb7354bcf86795d11685a0 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();
|
| }
|
| @@ -131,28 +133,31 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
|
|
|
| // 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;
|
| + observer_config->track_id = 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));
|
| + bitrate_observer_configs_.emplace_back(
|
| + new ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
|
| + pad_up_bitrate_bps, enforce_min_bitrate, 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 +175,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;
|
| }
|
| @@ -214,22 +220,33 @@ int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
|
| // 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) {
|
| - // 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;
|
| + ObserverConfig* config = static_cast<ObserverConfig*>(it->get());
|
| + 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 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 +258,30 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
|
| if (bitrate_observer_configs_.empty())
|
| return ObserverAllocation();
|
|
|
| + if (bitrate_allocation_strategy_ != nullptr) {
|
| + std::vector<uint32_t> track_allocations =
|
| + bitrate_allocation_strategy_->AllocateBitrates(
|
| + bitrate, bitrate_observer_configs_);
|
| + // The strategy should return allocation for all tracks.
|
| + RTC_CHECK(track_allocations.size() == bitrate_observer_configs_.size());
|
| + ObserverAllocation allocation;
|
| + auto track_allocations_it = track_allocations.begin();
|
| + for (const auto& track_config : bitrate_observer_configs_) {
|
| + ObserverConfig* observer_config =
|
| + static_cast<ObserverConfig*>(track_config.get());
|
| + allocation[observer_config->observer] = *track_allocations_it++;
|
| + }
|
| + 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 +301,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 +316,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 +346,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 +374,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 +393,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 +441,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 +479,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;
|
| }
|
| }
|
|
|