Reusing MediaStreamAllocationConfig struct in ObserverConfig.

This makes it easier to follow the code and reduces the risk of
accidents in the mapping of fields.

Also renaming the ObserverConfig struct to AllocatableTrack to better
reflect what it represents.

Bug: webrtc:9883
Change-Id: Ia320363813db2b4bf7b37852882a1ccb7644ae0b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/153342
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29213}
This commit is contained in:
Sebastian Jansson 2019-09-17 20:53:26 +02:00 committed by Commit Bot
parent 86314cfb5d
commit 4d461ba298
3 changed files with 99 additions and 138 deletions

View File

@ -206,6 +206,7 @@ rtc_source_set("bitrate_allocator") {
"../system_wrappers", "../system_wrappers",
"../system_wrappers:field_trial", "../system_wrappers:field_trial",
"../system_wrappers:metrics", "../system_wrappers:metrics",
"//third_party/abseil-cpp/absl/algorithm:container",
] ]
} }

View File

@ -16,6 +16,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "absl/algorithm/container.h"
#include "api/units/data_rate.h" #include "api/units/data_rate.h"
#include "api/units/time_delta.h" #include "api/units/time_delta.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
@ -122,7 +123,7 @@ void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
ObserverAllocation stable_bitrate_allocation = ObserverAllocation stable_bitrate_allocation =
AllocateBitrates(stable_target_bitrate_bps); AllocateBitrates(stable_target_bitrate_bps);
for (auto& config : bitrate_observer_configs_) { for (auto& config : allocatable_tracks_) {
uint32_t allocated_bitrate = allocation[config.observer]; uint32_t allocated_bitrate = allocation[config.observer];
uint32_t allocated_bandwidth = bandwidth_allocation[config.observer]; uint32_t allocated_bandwidth = bandwidth_allocation[config.observer];
uint32_t allocated_stable_target_rate = uint32_t allocated_stable_target_rate =
@ -142,17 +143,19 @@ void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
// The protection bitrate is an estimate based on the ratio between media // The protection bitrate is an estimate based on the ratio between media
// and protection used before this observer was muted. // and protection used before this observer was muted.
uint32_t predicted_protection_bps = uint32_t predicted_protection_bps =
(1.0 - config.media_ratio) * config.min_bitrate_bps; (1.0 - config.media_ratio) * config.config.min_bitrate_bps;
RTC_LOG(LS_INFO) << "Pausing observer " << config.observer RTC_LOG(LS_INFO) << "Pausing observer " << config.observer
<< " with configured min bitrate " << " with configured min bitrate "
<< config.min_bitrate_bps << " and current estimate of " << config.config.min_bitrate_bps
<< target_bitrate_bps << " and protection bitrate " << " and current estimate of " << target_bitrate_bps
<< " and protection bitrate "
<< predicted_protection_bps; << 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) if (target_bitrate_bps > 0)
++num_pause_events_; ++num_pause_events_;
RTC_LOG(LS_INFO) << "Resuming observer " << config.observer RTC_LOG(LS_INFO) << "Resuming observer " << config.observer
<< ", configured min bitrate " << config.min_bitrate_bps << ", configured min bitrate "
<< config.config.min_bitrate_bps
<< ", current allocation " << allocated_bitrate << ", current allocation " << allocated_bitrate
<< " and protection bitrate " << protection_bitrate; << " and protection bitrate " << protection_bitrate;
} }
@ -170,20 +173,14 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
RTC_DCHECK_RUN_ON(&sequenced_checker_); RTC_DCHECK_RUN_ON(&sequenced_checker_);
RTC_DCHECK_GT(config.bitrate_priority, 0); RTC_DCHECK_GT(config.bitrate_priority, 0);
RTC_DCHECK(std::isnormal(config.bitrate_priority)); RTC_DCHECK(std::isnormal(config.bitrate_priority));
auto it = FindObserverConfig(observer); auto it = absl::c_find_if(
allocatable_tracks_,
[observer](const auto& config) { return config.observer == observer; });
// Update settings if the observer already exists, create a new one otherwise. // Update settings if the observer already exists, create a new one otherwise.
if (it != bitrate_observer_configs_.end()) { if (it != allocatable_tracks_.end()) {
it->min_bitrate_bps = config.min_bitrate_bps; it->config = config;
it->max_bitrate_bps = config.max_bitrate_bps;
it->pad_up_bitrate_bps = config.pad_up_bitrate_bps;
it->enforce_min_bitrate = config.enforce_min_bitrate;
it->bitrate_priority = config.bitrate_priority;
} else { } else {
bitrate_observer_configs_.push_back( allocatable_tracks_.push_back(AllocatableTrack(observer, config));
ObserverConfig(observer, config.min_bitrate_bps, config.max_bitrate_bps,
config.pad_up_bitrate_bps, config.priority_bitrate_bps,
config.enforce_min_bitrate, config.bitrate_priority));
} }
if (last_target_bps_ > 0) { if (last_target_bps_ > 0) {
@ -194,7 +191,7 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
AllocateBitrates(last_bandwidth_bps_); AllocateBitrates(last_bandwidth_bps_);
ObserverAllocation stable_bitrate_allocation = ObserverAllocation stable_bitrate_allocation =
AllocateBitrates(last_stable_target_bps_); AllocateBitrates(last_stable_target_bps_);
for (auto& config : bitrate_observer_configs_) { for (auto& config : allocatable_tracks_) {
uint32_t allocated_bitrate = allocation[config.observer]; uint32_t allocated_bitrate = allocation[config.observer];
uint32_t allocated_stable_bitrate = uint32_t allocated_stable_bitrate =
stable_bitrate_allocation[config.observer]; stable_bitrate_allocation[config.observer];
@ -232,16 +229,16 @@ void BitrateAllocator::UpdateAllocationLimits() {
uint32_t total_requested_padding_bitrate = 0; uint32_t total_requested_padding_bitrate = 0;
uint32_t total_requested_min_bitrate = 0; uint32_t total_requested_min_bitrate = 0;
uint32_t total_requested_max_bitrate = 0; uint32_t total_requested_max_bitrate = 0;
for (const auto& config : bitrate_observer_configs_) { for (const auto& config : allocatable_tracks_) {
uint32_t stream_padding = config.pad_up_bitrate_bps; uint32_t stream_padding = config.config.pad_up_bitrate_bps;
if (config.enforce_min_bitrate) { if (config.config.enforce_min_bitrate) {
total_requested_min_bitrate += config.min_bitrate_bps; total_requested_min_bitrate += config.config.min_bitrate_bps;
} else if (config.allocated_bitrate_bps == 0) { } else if (config.allocated_bitrate_bps == 0) {
stream_padding = stream_padding =
std::max(config.MinBitrateWithHysteresis(), stream_padding); std::max(config.MinBitrateWithHysteresis(), stream_padding);
} }
total_requested_padding_bitrate += stream_padding; total_requested_padding_bitrate += stream_padding;
total_requested_max_bitrate += config.max_bitrate_bps; total_requested_max_bitrate += config.config.max_bitrate_bps;
} }
if (total_requested_padding_bitrate == total_requested_padding_bitrate_ && if (total_requested_padding_bitrate == total_requested_padding_bitrate_ &&
@ -267,10 +264,12 @@ void BitrateAllocator::UpdateAllocationLimits() {
void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) { void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
RTC_DCHECK_RUN_ON(&sequenced_checker_); RTC_DCHECK_RUN_ON(&sequenced_checker_);
for (auto it = allocatable_tracks_.begin(); it != allocatable_tracks_.end();
auto it = FindObserverConfig(observer); ++it) {
if (it != bitrate_observer_configs_.end()) { if (it->observer == observer) {
bitrate_observer_configs_.erase(it); allocatable_tracks_.erase(it);
break;
}
} }
UpdateAllocationLimits(); UpdateAllocationLimits();
@ -279,45 +278,26 @@ void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
int BitrateAllocator::GetStartBitrate( int BitrateAllocator::GetStartBitrate(
BitrateAllocatorObserver* observer) const { BitrateAllocatorObserver* observer) const {
RTC_DCHECK_RUN_ON(&sequenced_checker_); RTC_DCHECK_RUN_ON(&sequenced_checker_);
const auto& it = FindObserverConfig(observer); auto it = absl::c_find_if(
if (it == bitrate_observer_configs_.end()) { allocatable_tracks_,
[observer](const auto& config) { return config.observer == observer; });
if (it == allocatable_tracks_.end()) {
// This observer hasn't been added yet, just give it its fair share. // This observer hasn't been added yet, just give it its fair share.
return last_non_zero_bitrate_bps_ / return last_non_zero_bitrate_bps_ /
static_cast<int>((bitrate_observer_configs_.size() + 1)); static_cast<int>((allocatable_tracks_.size() + 1));
} else if (it->allocated_bitrate_bps == -1) { } else if (it->allocated_bitrate_bps == -1) {
// This observer hasn't received an allocation yet, so do the same. // This observer hasn't received an allocation yet, so do the same.
return last_non_zero_bitrate_bps_ / return last_non_zero_bitrate_bps_ /
static_cast<int>(bitrate_observer_configs_.size()); static_cast<int>(allocatable_tracks_.size());
} else { } else {
// This observer already has an allocation. // This observer already has an allocation.
return it->allocated_bitrate_bps; return it->allocated_bitrate_bps;
} }
} }
BitrateAllocator::ObserverConfigs::const_iterator
BitrateAllocator::FindObserverConfig(
const BitrateAllocatorObserver* observer) const {
for (auto it = bitrate_observer_configs_.begin();
it != bitrate_observer_configs_.end(); ++it) {
if (it->observer == observer)
return it;
}
return bitrate_observer_configs_.end();
}
BitrateAllocator::ObserverConfigs::iterator
BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) {
for (auto it = bitrate_observer_configs_.begin();
it != bitrate_observer_configs_.end(); ++it) {
if (it->observer == observer)
return it;
}
return bitrate_observer_configs_.end();
}
BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates( BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
uint32_t bitrate) const { uint32_t bitrate) const {
if (bitrate_observer_configs_.empty()) if (allocatable_tracks_.empty())
return ObserverAllocation(); return ObserverAllocation();
if (bitrate == 0) if (bitrate == 0)
@ -325,9 +305,9 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
uint32_t sum_min_bitrates = 0; uint32_t sum_min_bitrates = 0;
uint32_t sum_max_bitrates = 0; uint32_t sum_max_bitrates = 0;
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
sum_min_bitrates += observer_config.min_bitrate_bps; sum_min_bitrates += observer_config.config.min_bitrate_bps;
sum_max_bitrates += observer_config.max_bitrate_bps; sum_max_bitrates += observer_config.config.max_bitrate_bps;
} }
// Not enough for all observers to get an allocation, allocate according to: // Not enough for all observers to get an allocation, allocate according to:
@ -348,7 +328,7 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation()
const { const {
ObserverAllocation allocation; ObserverAllocation allocation;
for (const auto& observer_config : bitrate_observer_configs_) for (const auto& observer_config : allocatable_tracks_)
allocation[observer_config.observer] = 0; allocation[observer_config.observer] = 0;
return allocation; return allocation;
} }
@ -359,10 +339,10 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
// Start by allocating bitrate to observers enforcing a min bitrate, hence // Start by allocating bitrate to observers enforcing a min bitrate, hence
// remaining_bitrate might turn negative. // remaining_bitrate might turn negative.
int64_t remaining_bitrate = bitrate; int64_t remaining_bitrate = bitrate;
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
int32_t allocated_bitrate = 0; int32_t allocated_bitrate = 0;
if (observer_config.enforce_min_bitrate) if (observer_config.config.enforce_min_bitrate)
allocated_bitrate = observer_config.min_bitrate_bps; allocated_bitrate = observer_config.config.min_bitrate_bps;
allocation[observer_config.observer] = allocated_bitrate; allocation[observer_config.observer] = allocated_bitrate;
remaining_bitrate -= allocated_bitrate; remaining_bitrate -= allocated_bitrate;
@ -370,8 +350,8 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
// Allocate bitrate to all previously active streams. // Allocate bitrate to all previously active streams.
if (remaining_bitrate > 0) { if (remaining_bitrate > 0) {
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
if (observer_config.enforce_min_bitrate || if (observer_config.config.enforce_min_bitrate ||
observer_config.LastAllocatedBitrate() == 0) observer_config.LastAllocatedBitrate() == 0)
continue; continue;
@ -385,7 +365,7 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
// Allocate bitrate to previously paused streams. // Allocate bitrate to previously paused streams.
if (remaining_bitrate > 0) { if (remaining_bitrate > 0) {
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
if (observer_config.LastAllocatedBitrate() != 0) if (observer_config.LastAllocatedBitrate() != 0)
continue; continue;
@ -402,7 +382,7 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
if (remaining_bitrate > 0) if (remaining_bitrate > 0)
DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation); DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size()); RTC_DCHECK_EQ(allocation.size(), allocatable_tracks_.size());
return allocation; return allocation;
} }
@ -418,18 +398,20 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
uint32_t sum_min_bitrates) const { uint32_t sum_min_bitrates) const {
ObserverAllocation allocation; ObserverAllocation allocation;
ObserverAllocation observers_capacities; ObserverAllocation observers_capacities;
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
allocation[observer_config.observer] = observer_config.min_bitrate_bps; allocation[observer_config.observer] =
observer_config.config.min_bitrate_bps;
observers_capacities[observer_config.observer] = observers_capacities[observer_config.observer] =
observer_config.max_bitrate_bps - observer_config.min_bitrate_bps; observer_config.config.max_bitrate_bps -
observer_config.config.min_bitrate_bps;
} }
bitrate -= sum_min_bitrates; bitrate -= sum_min_bitrates;
// TODO(srte): Implement fair sharing between prioritized streams, currently // TODO(srte): Implement fair sharing between prioritized streams, currently
// they are treated on a first come first serve basis. // they are treated on a first come first serve basis.
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
int64_t priority_margin = observer_config.priority_bitrate_bps - int64_t priority_margin = observer_config.config.priority_bitrate_bps -
allocation[observer_config.observer]; allocation[observer_config.observer];
if (priority_margin > 0 && bitrate > 0) { if (priority_margin > 0 && bitrate > 0) {
int64_t extra_bitrate = std::min<int64_t>(priority_margin, bitrate); int64_t extra_bitrate = std::min<int64_t>(priority_margin, bitrate);
@ -453,24 +435,26 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
uint32_t sum_max_bitrates) const { uint32_t sum_max_bitrates) const {
ObserverAllocation allocation; ObserverAllocation allocation;
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
allocation[observer_config.observer] = observer_config.max_bitrate_bps; allocation[observer_config.observer] =
bitrate -= observer_config.max_bitrate_bps; observer_config.config.max_bitrate_bps;
bitrate -= observer_config.config.max_bitrate_bps;
} }
DistributeBitrateEvenly(bitrate, true, transmission_max_bitrate_multiplier_, DistributeBitrateEvenly(bitrate, true, transmission_max_bitrate_multiplier_,
&allocation); &allocation);
return allocation; return allocation;
} }
uint32_t BitrateAllocator::ObserverConfig::LastAllocatedBitrate() const { uint32_t BitrateAllocator::AllocatableTrack::LastAllocatedBitrate() const {
// Return the configured minimum bitrate for newly added observers, to avoid // Return the configured minimum bitrate for newly added observers, to avoid
// requiring an extra high bitrate for the observer to get an allocated // requiring an extra high bitrate for the observer to get an allocated
// bitrate. // bitrate.
return allocated_bitrate_bps == -1 ? min_bitrate_bps : allocated_bitrate_bps; return allocated_bitrate_bps == -1 ? config.min_bitrate_bps
: allocated_bitrate_bps;
} }
uint32_t BitrateAllocator::ObserverConfig::MinBitrateWithHysteresis() const { uint32_t BitrateAllocator::AllocatableTrack::MinBitrateWithHysteresis() const {
uint32_t min_bitrate = min_bitrate_bps; uint32_t min_bitrate = config.min_bitrate_bps;
if (LastAllocatedBitrate() == 0) { if (LastAllocatedBitrate() == 0) {
min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate), min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
kMinToggleBitrateBps); kMinToggleBitrateBps);
@ -492,14 +476,14 @@ void BitrateAllocator::DistributeBitrateEvenly(
bool include_zero_allocations, bool include_zero_allocations,
int max_multiplier, int max_multiplier,
ObserverAllocation* allocation) const { ObserverAllocation* allocation) const {
RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size()); RTC_DCHECK_EQ(allocation->size(), allocatable_tracks_.size());
ObserverSortingMap list_max_bitrates; ObserverSortingMap list_max_bitrates;
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
if (include_zero_allocations || if (include_zero_allocations ||
allocation->at(observer_config.observer) != 0) { allocation->at(observer_config.observer) != 0) {
list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>( list_max_bitrates.insert(std::pair<uint32_t, const AllocatableTrack*>(
observer_config.max_bitrate_bps, &observer_config)); observer_config.config.max_bitrate_bps, &observer_config));
} }
} }
auto it = list_max_bitrates.begin(); auto it = list_max_bitrates.begin();
@ -530,9 +514,9 @@ bool BitrateAllocator::EnoughBitrateForAllObservers(
uint32_t extra_bitrate_per_observer = uint32_t extra_bitrate_per_observer =
(bitrate - sum_min_bitrates) / (bitrate - sum_min_bitrates) /
static_cast<uint32_t>(bitrate_observer_configs_.size()); static_cast<uint32_t>(allocatable_tracks_.size());
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
if (observer_config.min_bitrate_bps + extra_bitrate_per_observer < if (observer_config.config.min_bitrate_bps + extra_bitrate_per_observer <
observer_config.MinBitrateWithHysteresis()) { observer_config.MinBitrateWithHysteresis()) {
return false; return false;
} }
@ -544,8 +528,8 @@ void BitrateAllocator::DistributeBitrateRelatively(
uint32_t remaining_bitrate, uint32_t remaining_bitrate,
const ObserverAllocation& observers_capacities, const ObserverAllocation& observers_capacities,
ObserverAllocation* allocation) const { ObserverAllocation* allocation) const {
RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size()); RTC_DCHECK_EQ(allocation->size(), allocatable_tracks_.size());
RTC_DCHECK_EQ(observers_capacities.size(), bitrate_observer_configs_.size()); RTC_DCHECK_EQ(observers_capacities.size(), allocatable_tracks_.size());
struct PriorityRateObserverConfig { struct PriorityRateObserverConfig {
PriorityRateObserverConfig(BitrateAllocatorObserver* allocation_key, PriorityRateObserverConfig(BitrateAllocatorObserver* allocation_key,
@ -574,11 +558,12 @@ void BitrateAllocator::DistributeBitrateRelatively(
double bitrate_priority_sum = 0; double bitrate_priority_sum = 0;
std::vector<PriorityRateObserverConfig> priority_rate_observers; std::vector<PriorityRateObserverConfig> priority_rate_observers;
for (const auto& observer_config : bitrate_observer_configs_) { for (const auto& observer_config : allocatable_tracks_) {
uint32_t capacity_bps = observers_capacities.at(observer_config.observer); uint32_t capacity_bps = observers_capacities.at(observer_config.observer);
priority_rate_observers.emplace_back(observer_config.observer, capacity_bps, priority_rate_observers.emplace_back(
observer_config.bitrate_priority); observer_config.observer, capacity_bps,
bitrate_priority_sum += observer_config.bitrate_priority; observer_config.config.bitrate_priority);
bitrate_priority_sum += observer_config.config.bitrate_priority;
} }
// Iterate in the order observers can be allocated their full capacity. // Iterate in the order observers can be allocated their full capacity.

View File

@ -41,21 +41,23 @@ class BitrateAllocatorObserver {
}; };
// Struct describing parameters for how a media stream should get bitrate // Struct describing parameters for how a media stream should get bitrate
// allocated to it. |min_bitrate_bps| = 0 equals no min bitrate. // allocated to it.
// |max_bitrate_bps| = 0 equals no max bitrate.
// |enforce_min_bitrate| = 'true' will allocate at least |min_bitrate_bps| for
// this observer, even if the BWE is too low, 'false' will allocate 0 to
// the observer if BWE doesn't allow |min_bitrate_bps|.
// Note that |observer|->OnBitrateUpdated() will be called
// within the scope of this method with the current rtt, fraction_loss and
// available bitrate and that the bitrate in OnBitrateUpdated will be zero if
// the |observer| is currently not allowed to send data.
struct MediaStreamAllocationConfig { struct MediaStreamAllocationConfig {
// Minimum bitrate supported by track. 0 equals no min bitrate.
uint32_t min_bitrate_bps; uint32_t min_bitrate_bps;
// Maximum bitrate supported by track. 0 equals no max bitrate.
uint32_t max_bitrate_bps; uint32_t max_bitrate_bps;
uint32_t pad_up_bitrate_bps; uint32_t pad_up_bitrate_bps;
int64_t priority_bitrate_bps; int64_t priority_bitrate_bps;
// True means track may not be paused by allocating 0 bitrate will allocate at
// least |min_bitrate_bps| for this observer, even if the BWE is too low,
// false will allocate 0 to the observer if BWE doesn't allow
// |min_bitrate_bps|.
bool enforce_min_bitrate; bool enforce_min_bitrate;
// The amount of bitrate allocated to this observer relative to all other
// observers. If an observer has twice the bitrate_priority of other
// observers, it should be allocated twice the bitrate above its min.
double bitrate_priority; double bitrate_priority;
}; };
@ -104,6 +106,10 @@ class BitrateAllocator : public BitrateAllocatorInterface {
// Set the configuration used by the bandwidth management. // Set the configuration used by the bandwidth management.
// |observer| updates bitrates if already in use. // |observer| updates bitrates if already in use.
// |config| is the configuration to use for allocation. // |config| is the configuration to use for allocation.
// Note that |observer|->OnBitrateUpdated() will be called
// within the scope of this method with the current rtt, fraction_loss and
// available bitrate and that the bitrate in OnBitrateUpdated will be zero if
// the |observer| is currently not allowed to send data.
void AddObserver(BitrateAllocatorObserver* observer, void AddObserver(BitrateAllocatorObserver* observer,
MediaStreamAllocationConfig config) override; MediaStreamAllocationConfig config) override;
@ -116,42 +122,17 @@ class BitrateAllocator : public BitrateAllocatorInterface {
int GetStartBitrate(BitrateAllocatorObserver* observer) const override; int GetStartBitrate(BitrateAllocatorObserver* observer) const override;
private: private:
struct ObserverConfig { struct AllocatableTrack {
ObserverConfig(BitrateAllocatorObserver* observer, AllocatableTrack(BitrateAllocatorObserver* observer,
uint32_t min_bitrate_bps, MediaStreamAllocationConfig allocation_config)
uint32_t max_bitrate_bps,
uint32_t pad_up_bitrate_bps,
int64_t priority_bitrate_bps,
bool enforce_min_bitrate,
double bitrate_priority)
: observer(observer), : observer(observer),
pad_up_bitrate_bps(pad_up_bitrate_bps), config(allocation_config),
priority_bitrate_bps(priority_bitrate_bps),
allocated_bitrate_bps(-1), allocated_bitrate_bps(-1),
media_ratio(1.0), media_ratio(1.0) {}
bitrate_priority(bitrate_priority),
min_bitrate_bps(min_bitrate_bps),
max_bitrate_bps(max_bitrate_bps),
enforce_min_bitrate(enforce_min_bitrate) {}
BitrateAllocatorObserver* observer; BitrateAllocatorObserver* observer;
uint32_t pad_up_bitrate_bps; MediaStreamAllocationConfig config;
int64_t priority_bitrate_bps;
int64_t allocated_bitrate_bps; int64_t allocated_bitrate_bps;
double media_ratio; // Part of the total bitrate used for media [0.0, 1.0]. 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
// observers. If an observer has twice the bitrate_priority of other
// observers, it should be allocated twice the bitrate above its min.
double bitrate_priority;
// Minimum bitrate supported by track.
uint32_t min_bitrate_bps;
// Maximum bitrate supported by track.
uint32_t max_bitrate_bps;
// True means track may not be paused by allocating 0 bitrate.
bool enforce_min_bitrate;
uint32_t LastAllocatedBitrate() const; uint32_t LastAllocatedBitrate() const;
// The minimum bitrate required by this observer, including // The minimum bitrate required by this observer, including
@ -163,14 +144,7 @@ class BitrateAllocator : public BitrateAllocatorInterface {
// calls LimitObserver::OnAllocationLimitsChanged. // calls LimitObserver::OnAllocationLimitsChanged.
void UpdateAllocationLimits() RTC_RUN_ON(&sequenced_checker_); void UpdateAllocationLimits() RTC_RUN_ON(&sequenced_checker_);
typedef std::vector<ObserverConfig> ObserverConfigs; typedef std::multimap<uint32_t, const AllocatableTrack*> ObserverSortingMap;
ObserverConfigs::const_iterator FindObserverConfig(
const BitrateAllocatorObserver* observer) const
RTC_RUN_ON(&sequenced_checker_);
ObserverConfigs::iterator FindObserverConfig(
const BitrateAllocatorObserver* observer) RTC_RUN_ON(&sequenced_checker_);
typedef std::multimap<uint32_t, const ObserverConfig*> ObserverSortingMap;
typedef std::map<BitrateAllocatorObserver*, int> ObserverAllocation; typedef std::map<BitrateAllocatorObserver*, int> ObserverAllocation;
ObserverAllocation AllocateBitrates(uint32_t bitrate) const ObserverAllocation AllocateBitrates(uint32_t bitrate) const
@ -227,7 +201,8 @@ class BitrateAllocator : public BitrateAllocatorInterface {
SequenceChecker sequenced_checker_; SequenceChecker sequenced_checker_;
LimitObserver* const limit_observer_ RTC_GUARDED_BY(&sequenced_checker_); LimitObserver* const limit_observer_ RTC_GUARDED_BY(&sequenced_checker_);
// Stored in a list to keep track of the insertion order. // Stored in a list to keep track of the insertion order.
ObserverConfigs bitrate_observer_configs_ RTC_GUARDED_BY(&sequenced_checker_); std::vector<AllocatableTrack> allocatable_tracks_
RTC_GUARDED_BY(&sequenced_checker_);
uint32_t last_target_bps_ RTC_GUARDED_BY(&sequenced_checker_); uint32_t last_target_bps_ RTC_GUARDED_BY(&sequenced_checker_);
uint32_t last_stable_target_bps_ RTC_GUARDED_BY(&sequenced_checker_); uint32_t last_stable_target_bps_ RTC_GUARDED_BY(&sequenced_checker_);
uint32_t last_bandwidth_bps_ RTC_GUARDED_BY(&sequenced_checker_); uint32_t last_bandwidth_bps_ RTC_GUARDED_BY(&sequenced_checker_);