WebRTC Bandwidth Allocation
Table of Contents
Title Bandwidth allocation by REMB
ModuleRtpRtcpImpl->RTCPReceiver: IncomingPacket
RTCPReceiver->RTCPReceiver: TriggerCallbacksFromRtcpPacket
RTCPReceiver->RtpTransportControllerSend:OnReceivedEstimatedBitrate(bitrate)
RtpTransportControllerSend->GoogCcNetworkController: OnRemoteBitrateReport(receiveTime, bitrate)
GoogCcNetworkController->SendSideBandwidthEstimation: UpdateReceiverEstimate
SendSideBandwidthEstimation->SendSideBandwidthEstimation: ApplyTargetLimits
SendSideBandwidthEstimation->SendSideBandwidthEstimation: UpdateTargetBitrate
#SendSideBandwidthEstimation->LinkCapacityTracker:OnRateUpdate
GoogCcNetworkController->Call: OnTargetTransferRate
Call->BitrateAllocator: OnNetworkEstimateChanged
BitrateAllocator->BitrateAllocator: AllocateBitrates
Snippets
- AllocateBitrates 带宽分配方法
std::map<BitrateAllocatorObserver*, int> AllocateBitrates(
const std::vector<AllocatableTrack>& allocatable_tracks,
uint32_t bitrate) {
if (allocatable_tracks.empty())
return std::map<BitrateAllocatorObserver*, int>();
if (bitrate == 0)
return ZeroRateAllocation(allocatable_tracks);
uint32_t sum_min_bitrates = 0;
uint32_t sum_max_bitrates = 0;
for (const auto& observer_config : allocatable_tracks) {
sum_min_bitrates += observer_config.config.min_bitrate_bps;
sum_max_bitrates += observer_config.config.max_bitrate_bps;
}
// Not enough for all observers to get an allocation, allocate according to:
// enforced min bitrate -> allocated bitrate previous round -> restart paused
// streams.
if (!EnoughBitrateForAllObservers(allocatable_tracks, bitrate,
sum_min_bitrates))
return LowRateAllocation(allocatable_tracks, bitrate);
// All observers will get their min bitrate plus a share of the rest. This
// share is allocated to each observer based on its bitrate_priority.
if (bitrate <= sum_max_bitrates)
return NormalRateAllocation(allocatable_tracks, bitrate, sum_min_bitrates);
// All observers will get up to transmission_max_bitrate_multiplier_ x max.
return MaxRateAllocation(allocatable_tracks, bitrate, sum_max_bitrates);
}
-
UpdateControlState
void RtpTransportControllerSend::UpdateControlState() { absl::optional<TargetTransferRate> update = control_handler_->GetUpdate(); if (!update) return; retransmission_rate_limiter_.SetMaxRate(update->target_rate.bps()); // We won't create control_handler_ until we have an observers. RTC_DCHECK(observer_ != nullptr); observer_->OnTargetTransferRate(*update); }
EnoughBitrateForAllObservers 带宽足够和话
bool EnoughBitrateForAllObservers( const std::vector<AllocatableTrack>& allocatable_tracks, uint32_t bitrate, uint32_t sum_min_bitrates) { if (bitrate < sum_min_bitrates) return false; uint32_t extra_bitrate_per_observer = (bitrate - sum_min_bitrates) / static_cast<uint32_t>(allocatable_tracks.size()); for (const auto& observer_config : allocatable_tracks) { if (observer_config.config.min_bitrate_bps + extra_bitrate_per_observer < observer_config.MinBitrateWithHysteresis()) { return false; } } return true; }
LowRateAllocation 带宽不够的分析策略
// Allocates bitrate to observers when there isn't enough to allocate the
// minimum to all observers.
std::map<BitrateAllocatorObserver*, int> LowRateAllocation(
const std::vector<AllocatableTrack>& allocatable_tracks,
uint32_t bitrate) {
std::map<BitrateAllocatorObserver*, int> allocation;
// 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 : allocatable_tracks) {
int32_t allocated_bitrate = 0;
if (observer_config.config.enforce_min_bitrate)
allocated_bitrate = observer_config.config.min_bitrate_bps;
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 : allocatable_tracks) {
if (observer_config.config.enforce_min_bitrate ||
observer_config.LastAllocatedBitrate() == 0)
continue;
uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
if (remaining_bitrate >= required_bitrate) {
allocation[observer_config.observer] = required_bitrate;
remaining_bitrate -= required_bitrate;
}
}
}
// Allocate bitrate to previously paused streams.
if (remaining_bitrate > 0) {
for (const auto& observer_config : allocatable_tracks) {
if (observer_config.LastAllocatedBitrate() != 0)
continue;
// Add a hysteresis to avoid toggling.
uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
if (remaining_bitrate >= required_bitrate) {
allocation[observer_config.observer] = required_bitrate;
remaining_bitrate -= required_bitrate;
}
}
}
// Split a possible remainder evenly on all streams with an allocation.
if (remaining_bitrate > 0)
DistributeBitrateEvenly(allocatable_tracks, remaining_bitrate, false, 1,
&allocation);
RTC_DCHECK_EQ(allocation.size(), allocatable_tracks.size());
return allocation;
}
NormalRateAllocation 按优先级的带宽分配策略
// Allocates the bitrate based on the bitrate priority of each observer. This
// bitrate priority defines the priority for bitrate to be allocated to that
// observer in relation to other observers. For example with two observers, if
// observer 1 had a bitrate_priority = 1.0, and observer 2 has a
// bitrate_priority = 2.0, the expected behavior is that observer 2 will be
// allocated twice the bitrate as observer 1 above the each observer's
// min_bitrate_bps values, until one of the observers hits its max_bitrate_bps.
std::map<BitrateAllocatorObserver*, int> NormalRateAllocation(
const std::vector<AllocatableTrack>& allocatable_tracks,
uint32_t bitrate,
uint32_t sum_min_bitrates) {
std::map<BitrateAllocatorObserver*, int> allocation;
std::map<BitrateAllocatorObserver*, int> observers_capacities;
for (const auto& observer_config : allocatable_tracks) {
allocation[observer_config.observer] =
observer_config.config.min_bitrate_bps;
observers_capacities[observer_config.observer] =
observer_config.config.max_bitrate_bps -
observer_config.config.min_bitrate_bps;
}
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 : allocatable_tracks) {
int64_t priority_margin = observer_config.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)
DistributeBitrateRelatively(allocatable_tracks, bitrate,
observers_capacities, &allocation);
return allocation;
}
MaxRateAllocation 最大带宽分配策略
// Allocates bitrate to observers when there is enough available bandwidth
// for all observers to be allocated their max bitrate.
std::map<BitrateAllocatorObserver*, int> MaxRateAllocation(
const std::vector<AllocatableTrack>& allocatable_tracks,
uint32_t bitrate,
uint32_t sum_max_bitrates) {
std::map<BitrateAllocatorObserver*, int> allocation;
for (const auto& observer_config : allocatable_tracks) {
allocation[observer_config.observer] =
observer_config.config.max_bitrate_bps;
bitrate -= observer_config.config.max_bitrate_bps;
}
DistributeBitrateEvenly(allocatable_tracks, bitrate, true,
kTransmissionMaxBitrateMultiplier, &allocation);
return allocation;
}
ZeroRateAllocation 零带宽分配策略
// Allocates zero bitrate to all observers.
std::map<BitrateAllocatorObserver*, int> ZeroRateAllocation(
const std::vector<AllocatableTrack>& allocatable_tracks) {
std::map<BitrateAllocatorObserver*, int> allocation;
for (const auto& observer_config : allocatable_tracks)
allocation[observer_config.observer] = 0;
return allocation;
}
Log keyword
-
Current BWE
void BitrateAllocator::OnNetworkEstimateChanged(TargetTransferRate msg) { //... // Periodically log the incoming BWE. int64_t now = msg.at_time.ms(); if (now > last_bwe_log_time_ + kBweLogIntervalMs) { RTC_LOG(LS_INFO) << "Current BWE " << last_target_bps_; last_bwe_log_time_ = now; }
Comments |0|
Category: Uncategorized