• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  *
10  */
11 
12 #include "call/bitrate_allocator.h"
13 
14 #include <algorithm>
15 #include <cmath>
16 #include <memory>
17 #include <utility>
18 
19 #include "absl/algorithm/container.h"
20 #include "api/units/data_rate.h"
21 #include "api/units/time_delta.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/logging.h"
24 #include "rtc_base/numerics/safe_minmax.h"
25 #include "system_wrappers/include/clock.h"
26 #include "system_wrappers/include/metrics.h"
27 
28 namespace webrtc {
29 
30 namespace {
31 using bitrate_allocator_impl::AllocatableTrack;
32 
33 // Allow packets to be transmitted in up to 2 times max video bitrate if the
34 // bandwidth estimate allows it.
35 const uint8_t kTransmissionMaxBitrateMultiplier = 2;
36 const int kDefaultBitrateBps = 300000;
37 
38 // Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
39 const double kToggleFactor = 0.1;
40 const uint32_t kMinToggleBitrateBps = 20000;
41 
42 const int64_t kBweLogIntervalMs = 5000;
43 
MediaRatio(uint32_t allocated_bitrate,uint32_t protection_bitrate)44 double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) {
45   RTC_DCHECK_GT(allocated_bitrate, 0);
46   if (protection_bitrate == 0)
47     return 1.0;
48 
49   uint32_t media_bitrate = allocated_bitrate - protection_bitrate;
50   return media_bitrate / static_cast<double>(allocated_bitrate);
51 }
52 
EnoughBitrateForAllObservers(const std::vector<AllocatableTrack> & allocatable_tracks,uint32_t bitrate,uint32_t sum_min_bitrates)53 bool EnoughBitrateForAllObservers(
54     const std::vector<AllocatableTrack>& allocatable_tracks,
55     uint32_t bitrate,
56     uint32_t sum_min_bitrates) {
57   if (bitrate < sum_min_bitrates)
58     return false;
59 
60   uint32_t extra_bitrate_per_observer =
61       (bitrate - sum_min_bitrates) /
62       static_cast<uint32_t>(allocatable_tracks.size());
63   for (const auto& observer_config : allocatable_tracks) {
64     if (observer_config.config.min_bitrate_bps + extra_bitrate_per_observer <
65         observer_config.MinBitrateWithHysteresis()) {
66       return false;
67     }
68   }
69   return true;
70 }
71 
72 // Splits `bitrate` evenly to observers already in `allocation`.
73 // `include_zero_allocations` decides if zero allocations should be part of
74 // the distribution or not. The allowed max bitrate is `max_multiplier` x
75 // observer max bitrate.
DistributeBitrateEvenly(const std::vector<AllocatableTrack> & allocatable_tracks,uint32_t bitrate,bool include_zero_allocations,int max_multiplier,std::map<BitrateAllocatorObserver *,int> * allocation)76 void DistributeBitrateEvenly(
77     const std::vector<AllocatableTrack>& allocatable_tracks,
78     uint32_t bitrate,
79     bool include_zero_allocations,
80     int max_multiplier,
81     std::map<BitrateAllocatorObserver*, int>* allocation) {
82   RTC_DCHECK_EQ(allocation->size(), allocatable_tracks.size());
83 
84   std::multimap<uint32_t, const AllocatableTrack*> list_max_bitrates;
85   for (const auto& observer_config : allocatable_tracks) {
86     if (include_zero_allocations ||
87         allocation->at(observer_config.observer) != 0) {
88       list_max_bitrates.insert(
89           {observer_config.config.max_bitrate_bps, &observer_config});
90     }
91   }
92   auto it = list_max_bitrates.begin();
93   while (it != list_max_bitrates.end()) {
94     RTC_DCHECK_GT(bitrate, 0);
95     uint32_t extra_allocation =
96         bitrate / static_cast<uint32_t>(list_max_bitrates.size());
97     uint32_t total_allocation =
98         extra_allocation + allocation->at(it->second->observer);
99     bitrate -= extra_allocation;
100     if (total_allocation > max_multiplier * it->first) {
101       // There is more than we can fit for this observer, carry over to the
102       // remaining observers.
103       bitrate += total_allocation - max_multiplier * it->first;
104       total_allocation = max_multiplier * it->first;
105     }
106     // Finally, update the allocation for this observer.
107     allocation->at(it->second->observer) = total_allocation;
108     it = list_max_bitrates.erase(it);
109   }
110 }
111 
112 // From the available `bitrate`, each observer will be allocated a
113 // proportional amount based upon its bitrate priority. If that amount is
114 // more than the observer's capacity, it will be allocated its capacity, and
115 // the excess bitrate is still allocated proportionally to other observers.
116 // Allocating the proportional amount means an observer with twice the
117 // bitrate_priority of another will be allocated twice the bitrate.
DistributeBitrateRelatively(const std::vector<AllocatableTrack> & allocatable_tracks,uint32_t remaining_bitrate,const std::map<BitrateAllocatorObserver *,int> & observers_capacities,std::map<BitrateAllocatorObserver *,int> * allocation)118 void DistributeBitrateRelatively(
119     const std::vector<AllocatableTrack>& allocatable_tracks,
120     uint32_t remaining_bitrate,
121     const std::map<BitrateAllocatorObserver*, int>& observers_capacities,
122     std::map<BitrateAllocatorObserver*, int>* allocation) {
123   RTC_DCHECK_EQ(allocation->size(), allocatable_tracks.size());
124   RTC_DCHECK_EQ(observers_capacities.size(), allocatable_tracks.size());
125 
126   struct PriorityRateObserverConfig {
127     BitrateAllocatorObserver* allocation_key;
128     // The amount of bitrate bps that can be allocated to this observer.
129     int capacity_bps;
130     double bitrate_priority;
131   };
132 
133   double bitrate_priority_sum = 0;
134   std::vector<PriorityRateObserverConfig> priority_rate_observers;
135   for (const auto& observer_config : allocatable_tracks) {
136     priority_rate_observers.push_back(PriorityRateObserverConfig{
137         observer_config.observer,
138         observers_capacities.at(observer_config.observer),
139         observer_config.config.bitrate_priority});
140     bitrate_priority_sum += observer_config.config.bitrate_priority;
141   }
142 
143   // Iterate in the order observers can be allocated their full capacity.
144 
145   // We want to sort by which observers will be allocated their full capacity
146   // first. By dividing each observer's capacity by its bitrate priority we
147   // are "normalizing" the capacity of an observer by the rate it will be
148   // filled. This is because the amount allocated is based upon bitrate
149   // priority. We allocate twice as much bitrate to an observer with twice the
150   // bitrate priority of another.
151   absl::c_sort(priority_rate_observers, [](const auto& a, const auto& b) {
152     return a.capacity_bps / a.bitrate_priority <
153            b.capacity_bps / b.bitrate_priority;
154   });
155   size_t i;
156   for (i = 0; i < priority_rate_observers.size(); ++i) {
157     const auto& priority_rate_observer = priority_rate_observers[i];
158     // We allocate the full capacity to an observer only if its relative
159     // portion from the remaining bitrate is sufficient to allocate its full
160     // capacity. This means we aren't greedily allocating the full capacity, but
161     // that it is only done when there is also enough bitrate to allocate the
162     // proportional amounts to all other observers.
163     double observer_share =
164         priority_rate_observer.bitrate_priority / bitrate_priority_sum;
165     double allocation_bps = observer_share * remaining_bitrate;
166     bool enough_bitrate = allocation_bps >= priority_rate_observer.capacity_bps;
167     if (!enough_bitrate)
168       break;
169     allocation->at(priority_rate_observer.allocation_key) +=
170         priority_rate_observer.capacity_bps;
171     remaining_bitrate -= priority_rate_observer.capacity_bps;
172     bitrate_priority_sum -= priority_rate_observer.bitrate_priority;
173   }
174 
175   // From the remaining bitrate, allocate the proportional amounts to the
176   // observers that aren't allocated their max capacity.
177   for (; i < priority_rate_observers.size(); ++i) {
178     const auto& priority_rate_observer = priority_rate_observers[i];
179     double fraction_allocated =
180         priority_rate_observer.bitrate_priority / bitrate_priority_sum;
181     allocation->at(priority_rate_observer.allocation_key) +=
182         fraction_allocated * remaining_bitrate;
183   }
184 }
185 
186 // Allocates bitrate to observers when there isn't enough to allocate the
187 // minimum to all observers.
LowRateAllocation(const std::vector<AllocatableTrack> & allocatable_tracks,uint32_t bitrate)188 std::map<BitrateAllocatorObserver*, int> LowRateAllocation(
189     const std::vector<AllocatableTrack>& allocatable_tracks,
190     uint32_t bitrate) {
191   std::map<BitrateAllocatorObserver*, int> allocation;
192   // Start by allocating bitrate to observers enforcing a min bitrate, hence
193   // remaining_bitrate might turn negative.
194   int64_t remaining_bitrate = bitrate;
195   for (const auto& observer_config : allocatable_tracks) {
196     int32_t allocated_bitrate = 0;
197     if (observer_config.config.enforce_min_bitrate)
198       allocated_bitrate = observer_config.config.min_bitrate_bps;
199 
200     allocation[observer_config.observer] = allocated_bitrate;
201     remaining_bitrate -= allocated_bitrate;
202   }
203 
204   // Allocate bitrate to all previously active streams.
205   if (remaining_bitrate > 0) {
206     for (const auto& observer_config : allocatable_tracks) {
207       if (observer_config.config.enforce_min_bitrate ||
208           observer_config.LastAllocatedBitrate() == 0)
209         continue;
210 
211       uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
212       if (remaining_bitrate >= required_bitrate) {
213         allocation[observer_config.observer] = required_bitrate;
214         remaining_bitrate -= required_bitrate;
215       }
216     }
217   }
218 
219   // Allocate bitrate to previously paused streams.
220   if (remaining_bitrate > 0) {
221     for (const auto& observer_config : allocatable_tracks) {
222       if (observer_config.LastAllocatedBitrate() != 0)
223         continue;
224 
225       // Add a hysteresis to avoid toggling.
226       uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
227       if (remaining_bitrate >= required_bitrate) {
228         allocation[observer_config.observer] = required_bitrate;
229         remaining_bitrate -= required_bitrate;
230       }
231     }
232   }
233 
234   // Split a possible remainder evenly on all streams with an allocation.
235   if (remaining_bitrate > 0)
236     DistributeBitrateEvenly(allocatable_tracks, remaining_bitrate, false, 1,
237                             &allocation);
238 
239   RTC_DCHECK_EQ(allocation.size(), allocatable_tracks.size());
240   return allocation;
241 }
242 
243 // Allocates bitrate to all observers when the available bandwidth is enough
244 // to allocate the minimum to all observers but not enough to allocate the
245 // max bitrate of each observer.
246 
247 // Allocates the bitrate based on the bitrate priority of each observer. This
248 // bitrate priority defines the priority for bitrate to be allocated to that
249 // observer in relation to other observers. For example with two observers, if
250 // observer 1 had a bitrate_priority = 1.0, and observer 2 has a
251 // bitrate_priority = 2.0, the expected behavior is that observer 2 will be
252 // allocated twice the bitrate as observer 1 above the each observer's
253 // min_bitrate_bps values, until one of the observers hits its max_bitrate_bps.
NormalRateAllocation(const std::vector<AllocatableTrack> & allocatable_tracks,uint32_t bitrate,uint32_t sum_min_bitrates)254 std::map<BitrateAllocatorObserver*, int> NormalRateAllocation(
255     const std::vector<AllocatableTrack>& allocatable_tracks,
256     uint32_t bitrate,
257     uint32_t sum_min_bitrates) {
258   std::map<BitrateAllocatorObserver*, int> allocation;
259   std::map<BitrateAllocatorObserver*, int> observers_capacities;
260   for (const auto& observer_config : allocatable_tracks) {
261     allocation[observer_config.observer] =
262         observer_config.config.min_bitrate_bps;
263     observers_capacities[observer_config.observer] =
264         observer_config.config.max_bitrate_bps -
265         observer_config.config.min_bitrate_bps;
266   }
267 
268   bitrate -= sum_min_bitrates;
269 
270   // TODO(srte): Implement fair sharing between prioritized streams, currently
271   // they are treated on a first come first serve basis.
272   for (const auto& observer_config : allocatable_tracks) {
273     int64_t priority_margin = observer_config.config.priority_bitrate_bps -
274                               allocation[observer_config.observer];
275     if (priority_margin > 0 && bitrate > 0) {
276       int64_t extra_bitrate = std::min<int64_t>(priority_margin, bitrate);
277       allocation[observer_config.observer] +=
278           rtc::dchecked_cast<int>(extra_bitrate);
279       observers_capacities[observer_config.observer] -= extra_bitrate;
280       bitrate -= extra_bitrate;
281     }
282   }
283 
284   // From the remaining bitrate, allocate a proportional amount to each observer
285   // above the min bitrate already allocated.
286   if (bitrate > 0)
287     DistributeBitrateRelatively(allocatable_tracks, bitrate,
288                                 observers_capacities, &allocation);
289 
290   return allocation;
291 }
292 
293 // Allocates bitrate to observers when there is enough available bandwidth
294 // for all observers to be allocated their max bitrate.
MaxRateAllocation(const std::vector<AllocatableTrack> & allocatable_tracks,uint32_t bitrate,uint32_t sum_max_bitrates)295 std::map<BitrateAllocatorObserver*, int> MaxRateAllocation(
296     const std::vector<AllocatableTrack>& allocatable_tracks,
297     uint32_t bitrate,
298     uint32_t sum_max_bitrates) {
299   std::map<BitrateAllocatorObserver*, int> allocation;
300 
301   for (const auto& observer_config : allocatable_tracks) {
302     allocation[observer_config.observer] =
303         observer_config.config.max_bitrate_bps;
304     bitrate -= observer_config.config.max_bitrate_bps;
305   }
306   DistributeBitrateEvenly(allocatable_tracks, bitrate, true,
307                           kTransmissionMaxBitrateMultiplier, &allocation);
308   return allocation;
309 }
310 
311 // Allocates zero bitrate to all observers.
ZeroRateAllocation(const std::vector<AllocatableTrack> & allocatable_tracks)312 std::map<BitrateAllocatorObserver*, int> ZeroRateAllocation(
313     const std::vector<AllocatableTrack>& allocatable_tracks) {
314   std::map<BitrateAllocatorObserver*, int> allocation;
315   for (const auto& observer_config : allocatable_tracks)
316     allocation[observer_config.observer] = 0;
317   return allocation;
318 }
319 
AllocateBitrates(const std::vector<AllocatableTrack> & allocatable_tracks,uint32_t bitrate)320 std::map<BitrateAllocatorObserver*, int> AllocateBitrates(
321     const std::vector<AllocatableTrack>& allocatable_tracks,
322     uint32_t bitrate) {
323   if (allocatable_tracks.empty())
324     return std::map<BitrateAllocatorObserver*, int>();
325 
326   if (bitrate == 0)
327     return ZeroRateAllocation(allocatable_tracks);
328 
329   uint32_t sum_min_bitrates = 0;
330   uint32_t sum_max_bitrates = 0;
331   for (const auto& observer_config : allocatable_tracks) {
332     sum_min_bitrates += observer_config.config.min_bitrate_bps;
333     sum_max_bitrates += observer_config.config.max_bitrate_bps;
334   }
335 
336   // Not enough for all observers to get an allocation, allocate according to:
337   // enforced min bitrate -> allocated bitrate previous round -> restart paused
338   // streams.
339   if (!EnoughBitrateForAllObservers(allocatable_tracks, bitrate,
340                                     sum_min_bitrates))
341     return LowRateAllocation(allocatable_tracks, bitrate);
342 
343   // All observers will get their min bitrate plus a share of the rest. This
344   // share is allocated to each observer based on its bitrate_priority.
345   if (bitrate <= sum_max_bitrates)
346     return NormalRateAllocation(allocatable_tracks, bitrate, sum_min_bitrates);
347 
348   // All observers will get up to transmission_max_bitrate_multiplier_ x max.
349   return MaxRateAllocation(allocatable_tracks, bitrate, sum_max_bitrates);
350 }
351 
352 }  // namespace
353 
BitrateAllocator(LimitObserver * limit_observer)354 BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
355     : limit_observer_(limit_observer),
356       last_target_bps_(0),
357       last_stable_target_bps_(0),
358       last_non_zero_bitrate_bps_(kDefaultBitrateBps),
359       last_fraction_loss_(0),
360       last_rtt_(0),
361       last_bwe_period_ms_(1000),
362       num_pause_events_(0),
363       last_bwe_log_time_(0) {
364   sequenced_checker_.Detach();
365 }
366 
~BitrateAllocator()367 BitrateAllocator::~BitrateAllocator() {
368   RTC_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
369                            num_pause_events_);
370 }
371 
UpdateStartRate(uint32_t start_rate_bps)372 void BitrateAllocator::UpdateStartRate(uint32_t start_rate_bps) {
373   RTC_DCHECK_RUN_ON(&sequenced_checker_);
374   last_non_zero_bitrate_bps_ = start_rate_bps;
375 }
376 
OnNetworkEstimateChanged(TargetTransferRate msg)377 void BitrateAllocator::OnNetworkEstimateChanged(TargetTransferRate msg) {
378   RTC_DCHECK_RUN_ON(&sequenced_checker_);
379   last_target_bps_ = msg.target_rate.bps();
380   last_stable_target_bps_ = msg.stable_target_rate.bps();
381   last_non_zero_bitrate_bps_ =
382       last_target_bps_ > 0 ? last_target_bps_ : last_non_zero_bitrate_bps_;
383 
384   int loss_ratio_255 = msg.network_estimate.loss_rate_ratio * 255;
385   last_fraction_loss_ =
386       rtc::dchecked_cast<uint8_t>(rtc::SafeClamp(loss_ratio_255, 0, 255));
387   last_rtt_ = msg.network_estimate.round_trip_time.ms();
388   last_bwe_period_ms_ = msg.network_estimate.bwe_period.ms();
389 
390   // Periodically log the incoming BWE.
391   int64_t now = msg.at_time.ms();
392   if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
393     RTC_LOG(LS_INFO) << "Current BWE " << last_target_bps_;
394     last_bwe_log_time_ = now;
395   }
396 
397   auto allocation = AllocateBitrates(allocatable_tracks_, last_target_bps_);
398   auto stable_bitrate_allocation =
399       AllocateBitrates(allocatable_tracks_, last_stable_target_bps_);
400 
401   for (auto& config : allocatable_tracks_) {
402     uint32_t allocated_bitrate = allocation[config.observer];
403     uint32_t allocated_stable_target_rate =
404         stable_bitrate_allocation[config.observer];
405     BitrateAllocationUpdate update;
406     update.target_bitrate = DataRate::BitsPerSec(allocated_bitrate);
407     update.stable_target_bitrate =
408         DataRate::BitsPerSec(allocated_stable_target_rate);
409     update.packet_loss_ratio = last_fraction_loss_ / 256.0;
410     update.round_trip_time = TimeDelta::Millis(last_rtt_);
411     update.bwe_period = TimeDelta::Millis(last_bwe_period_ms_);
412     update.cwnd_reduce_ratio = msg.cwnd_reduce_ratio;
413     uint32_t protection_bitrate = config.observer->OnBitrateUpdated(update);
414 
415     if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
416       if (last_target_bps_ > 0)
417         ++num_pause_events_;
418       // The protection bitrate is an estimate based on the ratio between media
419       // and protection used before this observer was muted.
420       uint32_t predicted_protection_bps =
421           (1.0 - config.media_ratio) * config.config.min_bitrate_bps;
422       RTC_LOG(LS_INFO) << "Pausing observer " << config.observer
423                        << " with configured min bitrate "
424                        << config.config.min_bitrate_bps
425                        << " and current estimate of " << last_target_bps_
426                        << " and protection bitrate "
427                        << predicted_protection_bps;
428     } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
429       if (last_target_bps_ > 0)
430         ++num_pause_events_;
431       RTC_LOG(LS_INFO) << "Resuming observer " << config.observer
432                        << ", configured min bitrate "
433                        << config.config.min_bitrate_bps
434                        << ", current allocation " << allocated_bitrate
435                        << " and protection bitrate " << protection_bitrate;
436     }
437 
438     // Only update the media ratio if the observer got an allocation.
439     if (allocated_bitrate > 0)
440       config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
441     config.allocated_bitrate_bps = allocated_bitrate;
442   }
443   UpdateAllocationLimits();
444 }
445 
AddObserver(BitrateAllocatorObserver * observer,MediaStreamAllocationConfig config)446 void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
447                                    MediaStreamAllocationConfig config) {
448   RTC_DCHECK_RUN_ON(&sequenced_checker_);
449   RTC_DCHECK_GT(config.bitrate_priority, 0);
450   RTC_DCHECK(std::isnormal(config.bitrate_priority));
451   auto it = absl::c_find_if(
452       allocatable_tracks_,
453       [observer](const auto& config) { return config.observer == observer; });
454   // Update settings if the observer already exists, create a new one otherwise.
455   if (it != allocatable_tracks_.end()) {
456     it->config = config;
457   } else {
458     allocatable_tracks_.push_back(AllocatableTrack(observer, config));
459   }
460 
461   if (last_target_bps_ > 0) {
462     // Calculate a new allocation and update all observers.
463 
464     auto allocation = AllocateBitrates(allocatable_tracks_, last_target_bps_);
465     auto stable_bitrate_allocation =
466         AllocateBitrates(allocatable_tracks_, last_stable_target_bps_);
467     for (auto& config : allocatable_tracks_) {
468       uint32_t allocated_bitrate = allocation[config.observer];
469       uint32_t allocated_stable_bitrate =
470           stable_bitrate_allocation[config.observer];
471       BitrateAllocationUpdate update;
472       update.target_bitrate = DataRate::BitsPerSec(allocated_bitrate);
473       update.stable_target_bitrate =
474           DataRate::BitsPerSec(allocated_stable_bitrate);
475       update.packet_loss_ratio = last_fraction_loss_ / 256.0;
476       update.round_trip_time = TimeDelta::Millis(last_rtt_);
477       update.bwe_period = TimeDelta::Millis(last_bwe_period_ms_);
478       uint32_t protection_bitrate = config.observer->OnBitrateUpdated(update);
479       config.allocated_bitrate_bps = allocated_bitrate;
480       if (allocated_bitrate > 0)
481         config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
482     }
483   } else {
484     // Currently, an encoder is not allowed to produce frames.
485     // But we still have to return the initial config bitrate + let the
486     // observer know that it can not produce frames.
487 
488     BitrateAllocationUpdate update;
489     update.target_bitrate = DataRate::Zero();
490     update.stable_target_bitrate = DataRate::Zero();
491     update.packet_loss_ratio = last_fraction_loss_ / 256.0;
492     update.round_trip_time = TimeDelta::Millis(last_rtt_);
493     update.bwe_period = TimeDelta::Millis(last_bwe_period_ms_);
494     observer->OnBitrateUpdated(update);
495   }
496   UpdateAllocationLimits();
497 }
498 
UpdateAllocationLimits()499 void BitrateAllocator::UpdateAllocationLimits() {
500   BitrateAllocationLimits limits;
501   for (const auto& config : allocatable_tracks_) {
502     uint32_t stream_padding = config.config.pad_up_bitrate_bps;
503     if (config.config.enforce_min_bitrate) {
504       limits.min_allocatable_rate +=
505           DataRate::BitsPerSec(config.config.min_bitrate_bps);
506     } else if (config.allocated_bitrate_bps == 0) {
507       stream_padding =
508           std::max(config.MinBitrateWithHysteresis(), stream_padding);
509     }
510     limits.max_padding_rate += DataRate::BitsPerSec(stream_padding);
511     limits.max_allocatable_rate +=
512         DataRate::BitsPerSec(config.config.max_bitrate_bps);
513   }
514 
515   if (limits.min_allocatable_rate == current_limits_.min_allocatable_rate &&
516       limits.max_allocatable_rate == current_limits_.max_allocatable_rate &&
517       limits.max_padding_rate == current_limits_.max_padding_rate) {
518     return;
519   }
520   current_limits_ = limits;
521 
522   RTC_LOG(LS_INFO) << "UpdateAllocationLimits : total_requested_min_bitrate: "
523                    << ToString(limits.min_allocatable_rate)
524                    << ", total_requested_padding_bitrate: "
525                    << ToString(limits.max_padding_rate)
526                    << ", total_requested_max_bitrate: "
527                    << ToString(limits.max_allocatable_rate);
528 
529   limit_observer_->OnAllocationLimitsChanged(limits);
530 }
531 
RemoveObserver(BitrateAllocatorObserver * observer)532 void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
533   RTC_DCHECK_RUN_ON(&sequenced_checker_);
534   for (auto it = allocatable_tracks_.begin(); it != allocatable_tracks_.end();
535        ++it) {
536     if (it->observer == observer) {
537       allocatable_tracks_.erase(it);
538       break;
539     }
540   }
541 
542   UpdateAllocationLimits();
543 }
544 
GetStartBitrate(BitrateAllocatorObserver * observer) const545 int BitrateAllocator::GetStartBitrate(
546     BitrateAllocatorObserver* observer) const {
547   RTC_DCHECK_RUN_ON(&sequenced_checker_);
548   auto it = absl::c_find_if(
549       allocatable_tracks_,
550       [observer](const auto& config) { return config.observer == observer; });
551   if (it == allocatable_tracks_.end()) {
552     // This observer hasn't been added yet, just give it its fair share.
553     return last_non_zero_bitrate_bps_ /
554            static_cast<int>((allocatable_tracks_.size() + 1));
555   } else if (it->allocated_bitrate_bps == -1) {
556     // This observer hasn't received an allocation yet, so do the same.
557     return last_non_zero_bitrate_bps_ /
558            static_cast<int>(allocatable_tracks_.size());
559   } else {
560     // This observer already has an allocation.
561     return it->allocated_bitrate_bps;
562   }
563 }
564 
LastAllocatedBitrate() const565 uint32_t bitrate_allocator_impl::AllocatableTrack::LastAllocatedBitrate()
566     const {
567   // Return the configured minimum bitrate for newly added observers, to avoid
568   // requiring an extra high bitrate for the observer to get an allocated
569   // bitrate.
570   return allocated_bitrate_bps == -1 ? config.min_bitrate_bps
571                                      : allocated_bitrate_bps;
572 }
573 
MinBitrateWithHysteresis() const574 uint32_t bitrate_allocator_impl::AllocatableTrack::MinBitrateWithHysteresis()
575     const {
576   uint32_t min_bitrate = config.min_bitrate_bps;
577   if (LastAllocatedBitrate() == 0) {
578     min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
579                             kMinToggleBitrateBps);
580   }
581   // Account for protection bitrate used by this observer in the previous
582   // allocation.
583   // Note: the ratio will only be updated when the stream is active, meaning a
584   // paused stream won't get any ratio updates. This might lead to waiting a bit
585   // longer than necessary if the network condition improves, but this is to
586   // avoid too much toggling.
587   if (media_ratio > 0.0 && media_ratio < 1.0)
588     min_bitrate += min_bitrate * (1.0 - media_ratio);
589 
590   return min_bitrate;
591 }
592 
593 }  // namespace webrtc
594