blob: c0a05183df1670fccbeabd467c2b1b97366b2fed [file] [log] [blame]
stefan@webrtc.org792f1a12015-03-04 12:24:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020012#include "call/bitrate_allocator.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000013
14#include <algorithm>
Seth Hampsonfe73d6a2017-11-14 10:49:06 -080015#include <cmath>
Alex Narest78609d52017-10-20 10:37:47 +020016#include <memory>
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000017#include <utility>
18
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/bitrate_controller/include/bitrate_controller.h"
20#include "rtc_base/checks.h"
21#include "rtc_base/logging.h"
22#include "system_wrappers/include/clock.h"
23#include "system_wrappers/include/metrics.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000024
25namespace webrtc {
26
Stefan Holmere5904162015-03-26 11:11:06 +010027// Allow packets to be transmitted in up to 2 times max video bitrate if the
28// bandwidth estimate allows it.
Alex Nareste0b2ff52017-11-16 20:03:46 +010029// TODO(bugs.webrtc.org/8541): May be worth to refactor to keep this logic in
30// video send stream. Similar logic is implemented in
31// AudioPriorityBitrateAllocationStrategy.
Stefan Holmere5904162015-03-26 11:11:06 +010032const int kTransmissionMaxBitrateMultiplier = 2;
33const int kDefaultBitrateBps = 300000;
34
mflodman101f2502016-06-09 17:21:19 +020035// Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
36const double kToggleFactor = 0.1;
37const uint32_t kMinToggleBitrateBps = 20000;
38
mflodman48a4beb2016-07-01 13:03:59 +020039const int64_t kBweLogIntervalMs = 5000;
40
41namespace {
42
43double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) {
kwibergaf476c72016-11-28 15:21:39 -080044 RTC_DCHECK_GT(allocated_bitrate, 0);
mflodman48a4beb2016-07-01 13:03:59 +020045 if (protection_bitrate == 0)
46 return 1.0;
47
48 uint32_t media_bitrate = allocated_bitrate - protection_bitrate;
49 return media_bitrate / static_cast<double>(allocated_bitrate);
50}
51} // namespace
52
perkj71ee44c2016-06-15 00:47:53 -070053BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
54 : limit_observer_(limit_observer),
Sergey Ulanove2b15012016-11-22 16:08:30 -080055 last_bitrate_bps_(0),
perkjfea93092016-05-14 00:58:48 -070056 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
Stefan Holmere5904162015-03-26 11:11:06 +010057 last_fraction_loss_(0),
mflodman48a4beb2016-07-01 13:03:59 +020058 last_rtt_(0),
59 num_pause_events_(0),
60 clock_(Clock::GetRealTimeClock()),
philipel5ef2bc12017-02-21 07:28:31 -080061 last_bwe_log_time_(0),
62 total_requested_padding_bitrate_(0),
Alex Narest78609d52017-10-20 10:37:47 +020063 total_requested_min_bitrate_(0),
64 bitrate_allocation_strategy_(nullptr) {
perkj26091b12016-09-01 01:17:40 -070065 sequenced_checker_.Detach();
66}
mflodman48a4beb2016-07-01 13:03:59 +020067
68BitrateAllocator::~BitrateAllocator() {
asapersson1d02d3e2016-09-09 22:40:25 -070069 RTC_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
70 num_pause_events_);
mflodman48a4beb2016-07-01 13:03:59 +020071}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000072
perkj71ee44c2016-06-15 00:47:53 -070073void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
74 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -080075 int64_t rtt,
minyue93e45222017-05-18 14:32:41 -070076 int64_t bwe_period_ms) {
perkj26091b12016-09-01 01:17:40 -070077 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman101f2502016-06-09 17:21:19 +020078 last_bitrate_bps_ = target_bitrate_bps;
perkjfea93092016-05-14 00:58:48 -070079 last_non_zero_bitrate_bps_ =
mflodman101f2502016-06-09 17:21:19 +020080 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
Stefan Holmere5904162015-03-26 11:11:06 +010081 last_fraction_loss_ = fraction_loss;
82 last_rtt_ = rtt;
minyue93e45222017-05-18 14:32:41 -070083 last_bwe_period_ms_ = bwe_period_ms;
mflodman2ebe5b12016-05-13 01:43:51 -070084
mflodman48a4beb2016-07-01 13:03:59 +020085 // Periodically log the incoming BWE.
86 int64_t now = clock_->TimeInMilliseconds();
87 if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010088 RTC_LOG(LS_INFO) << "Current BWE " << target_bitrate_bps;
mflodman48a4beb2016-07-01 13:03:59 +020089 last_bwe_log_time_ = now;
sprang2f48d942015-11-05 04:25:49 -080090 }
mflodman48a4beb2016-07-01 13:03:59 +020091
92 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
93
94 for (auto& config : bitrate_observer_configs_) {
95 uint32_t allocated_bitrate = allocation[config.observer];
96 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
minyue78b4d562016-11-30 04:47:39 -080097 allocated_bitrate, last_fraction_loss_, last_rtt_,
minyue93e45222017-05-18 14:32:41 -070098 last_bwe_period_ms_);
mflodman48a4beb2016-07-01 13:03:59 +020099
100 if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
101 if (target_bitrate_bps > 0)
102 ++num_pause_events_;
103 // The protection bitrate is an estimate based on the ratio between media
104 // and protection used before this observer was muted.
105 uint32_t predicted_protection_bps =
106 (1.0 - config.media_ratio) * config.min_bitrate_bps;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100107 RTC_LOG(LS_INFO) << "Pausing observer " << config.observer
108 << " with configured min bitrate "
109 << config.min_bitrate_bps << " and current estimate of "
110 << target_bitrate_bps << " and protection bitrate "
111 << predicted_protection_bps;
mflodman48a4beb2016-07-01 13:03:59 +0200112 } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
113 if (target_bitrate_bps > 0)
114 ++num_pause_events_;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100115 RTC_LOG(LS_INFO) << "Resuming observer " << config.observer
116 << ", configured min bitrate " << config.min_bitrate_bps
117 << ", current allocation " << allocated_bitrate
118 << " and protection bitrate " << protection_bitrate;
mflodman48a4beb2016-07-01 13:03:59 +0200119 }
120
121 // Only update the media ratio if the observer got an allocation.
122 if (allocated_bitrate > 0)
123 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
124 config.allocated_bitrate_bps = allocated_bitrate;
125 }
philipel5ef2bc12017-02-21 07:28:31 -0800126 UpdateAllocationLimits();
Stefan Holmere5904162015-03-26 11:11:06 +0100127}
128
perkj57c21f92016-06-17 07:27:16 -0700129void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
130 uint32_t min_bitrate_bps,
131 uint32_t max_bitrate_bps,
132 uint32_t pad_up_bitrate_bps,
Alex Narestb3944f02017-10-13 14:56:18 +0200133 bool enforce_min_bitrate,
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800134 std::string track_id,
135 double bitrate_priority) {
perkj26091b12016-09-01 01:17:40 -0700136 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800137 RTC_DCHECK_GT(bitrate_priority, 0);
138 RTC_DCHECK(std::isnormal(bitrate_priority));
mflodman2ebe5b12016-05-13 01:43:51 -0700139 auto it = FindObserverConfig(observer);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000140
mflodman101f2502016-06-09 17:21:19 +0200141 // Update settings if the observer already exists, create a new one otherwise.
mflodman2ebe5b12016-05-13 01:43:51 -0700142 if (it != bitrate_observer_configs_.end()) {
mflodman2ebe5b12016-05-13 01:43:51 -0700143 it->min_bitrate_bps = min_bitrate_bps;
144 it->max_bitrate_bps = max_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700145 it->pad_up_bitrate_bps = pad_up_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200146 it->enforce_min_bitrate = enforce_min_bitrate;
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800147 it->bitrate_priority = bitrate_priority;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000148 } else {
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800149 bitrate_observer_configs_.push_back(ObserverConfig(
150 observer, min_bitrate_bps, max_bitrate_bps, pad_up_bitrate_bps,
151 enforce_min_bitrate, track_id, bitrate_priority));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000152 }
Stefan Holmere5904162015-03-26 11:11:06 +0100153
mflodman101f2502016-06-09 17:21:19 +0200154 ObserverAllocation allocation;
155 if (last_bitrate_bps_ > 0) {
156 // Calculate a new allocation and update all observers.
157 allocation = AllocateBitrates(last_bitrate_bps_);
mflodman48a4beb2016-07-01 13:03:59 +0200158 for (auto& config : bitrate_observer_configs_) {
159 uint32_t allocated_bitrate = allocation[config.observer];
160 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
minyue78b4d562016-11-30 04:47:39 -0800161 allocated_bitrate, last_fraction_loss_, last_rtt_,
minyue93e45222017-05-18 14:32:41 -0700162 last_bwe_period_ms_);
mflodman48a4beb2016-07-01 13:03:59 +0200163 config.allocated_bitrate_bps = allocated_bitrate;
164 if (allocated_bitrate > 0)
165 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
166 }
perkjfea93092016-05-14 00:58:48 -0700167 } else {
168 // Currently, an encoder is not allowed to produce frames.
169 // But we still have to return the initial config bitrate + let the
170 // observer know that it can not produce frames.
mflodman101f2502016-06-09 17:21:19 +0200171 allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
minyue78b4d562016-11-30 04:47:39 -0800172 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_,
minyue93e45222017-05-18 14:32:41 -0700173 last_bwe_period_ms_);
Stefan Holmere5904162015-03-26 11:11:06 +0100174 }
perkj71ee44c2016-06-15 00:47:53 -0700175 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000176}
177
perkj71ee44c2016-06-15 00:47:53 -0700178void BitrateAllocator::UpdateAllocationLimits() {
perkj26091b12016-09-01 01:17:40 -0700179 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
perkj71ee44c2016-06-15 00:47:53 -0700180 uint32_t total_requested_padding_bitrate = 0;
181 uint32_t total_requested_min_bitrate = 0;
philipelf69e7682018-02-28 13:06:28 +0100182 uint32_t total_requested_bitrate = 0;
perkj71ee44c2016-06-15 00:47:53 -0700183
perkj26091b12016-09-01 01:17:40 -0700184 for (const auto& config : bitrate_observer_configs_) {
philipel5ef2bc12017-02-21 07:28:31 -0800185 uint32_t stream_padding = config.pad_up_bitrate_bps;
perkj26091b12016-09-01 01:17:40 -0700186 if (config.enforce_min_bitrate) {
187 total_requested_min_bitrate += config.min_bitrate_bps;
philipel5ef2bc12017-02-21 07:28:31 -0800188 } else if (config.allocated_bitrate_bps == 0) {
189 stream_padding =
srte1eb051c2017-11-29 11:23:59 +0100190 std::max(config.MinBitrateWithHysteresis(), stream_padding);
perkj71ee44c2016-06-15 00:47:53 -0700191 }
philipel5ef2bc12017-02-21 07:28:31 -0800192 total_requested_padding_bitrate += stream_padding;
philipelf69e7682018-02-28 13:06:28 +0100193 total_requested_bitrate += config.max_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000194 }
perkj71ee44c2016-06-15 00:47:53 -0700195
philipel5ef2bc12017-02-21 07:28:31 -0800196 if (total_requested_padding_bitrate == total_requested_padding_bitrate_ &&
197 total_requested_min_bitrate == total_requested_min_bitrate_) {
198 return;
199 }
200
201 total_requested_min_bitrate_ = total_requested_min_bitrate;
202 total_requested_padding_bitrate_ = total_requested_padding_bitrate;
203
Mirko Bonadei675513b2017-11-09 11:09:25 +0100204 RTC_LOG(LS_INFO) << "UpdateAllocationLimits : total_requested_min_bitrate: "
205 << total_requested_min_bitrate
206 << "bps, total_requested_padding_bitrate: "
207 << total_requested_padding_bitrate << "bps";
perkj71ee44c2016-06-15 00:47:53 -0700208 limit_observer_->OnAllocationLimitsChanged(total_requested_min_bitrate,
philipelf69e7682018-02-28 13:06:28 +0100209 total_requested_padding_bitrate,
210 total_requested_bitrate);
perkj71ee44c2016-06-15 00:47:53 -0700211}
212
213void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
perkj26091b12016-09-01 01:17:40 -0700214 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
Alex Narest78609d52017-10-20 10:37:47 +0200215
perkj26091b12016-09-01 01:17:40 -0700216 auto it = FindObserverConfig(observer);
217 if (it != bitrate_observer_configs_.end()) {
218 bitrate_observer_configs_.erase(it);
perkj71ee44c2016-06-15 00:47:53 -0700219 }
perkj26091b12016-09-01 01:17:40 -0700220
perkj71ee44c2016-06-15 00:47:53 -0700221 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000222}
223
perkj57c21f92016-06-17 07:27:16 -0700224int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
perkj26091b12016-09-01 01:17:40 -0700225 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman48a4beb2016-07-01 13:03:59 +0200226 const auto& it = FindObserverConfig(observer);
227 if (it == bitrate_observer_configs_.end()) {
228 // This observer hasn't been added yet, just give it its fair share.
229 return last_non_zero_bitrate_bps_ /
perkj26091b12016-09-01 01:17:40 -0700230 static_cast<int>((bitrate_observer_configs_.size() + 1));
mflodman48a4beb2016-07-01 13:03:59 +0200231 } else if (it->allocated_bitrate_bps == -1) {
232 // This observer hasn't received an allocation yet, so do the same.
233 return last_non_zero_bitrate_bps_ /
perkj26091b12016-09-01 01:17:40 -0700234 static_cast<int>(bitrate_observer_configs_.size());
mflodman48a4beb2016-07-01 13:03:59 +0200235 } else {
236 // This observer already has an allocation.
237 return it->allocated_bitrate_bps;
238 }
perkj57c21f92016-06-17 07:27:16 -0700239}
240
Alex Narest78609d52017-10-20 10:37:47 +0200241void BitrateAllocator::SetBitrateAllocationStrategy(
242 std::unique_ptr<rtc::BitrateAllocationStrategy>
243 bitrate_allocation_strategy) {
244 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
245 bitrate_allocation_strategy_ = std::move(bitrate_allocation_strategy);
246}
247
mflodman48a4beb2016-07-01 13:03:59 +0200248BitrateAllocator::ObserverConfigs::iterator
perkj26091b12016-09-01 01:17:40 -0700249BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) {
250 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman2ebe5b12016-05-13 01:43:51 -0700251 for (auto it = bitrate_observer_configs_.begin();
252 it != bitrate_observer_configs_.end(); ++it) {
253 if (it->observer == observer)
254 return it;
255 }
256 return bitrate_observer_configs_.end();
257}
258
perkjfea93092016-05-14 00:58:48 -0700259BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
260 uint32_t bitrate) {
perkj26091b12016-09-01 01:17:40 -0700261 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman2ebe5b12016-05-13 01:43:51 -0700262 if (bitrate_observer_configs_.empty())
263 return ObserverAllocation();
264
Alex Narest78609d52017-10-20 10:37:47 +0200265 if (bitrate_allocation_strategy_ != nullptr) {
266 std::vector<const rtc::BitrateAllocationStrategy::TrackConfig*>
267 track_configs(bitrate_observer_configs_.size());
268 int i = 0;
269 for (const auto& c : bitrate_observer_configs_) {
270 track_configs[i++] = &c;
271 }
272 std::vector<uint32_t> track_allocations =
273 bitrate_allocation_strategy_->AllocateBitrates(bitrate, track_configs);
274 // The strategy should return allocation for all tracks.
275 RTC_CHECK(track_allocations.size() == bitrate_observer_configs_.size());
276 ObserverAllocation allocation;
277 auto track_allocations_it = track_allocations.begin();
278 for (const auto& observer_config : bitrate_observer_configs_) {
279 allocation[observer_config.observer] = *track_allocations_it++;
280 }
281 return allocation;
282 }
283
perkjfea93092016-05-14 00:58:48 -0700284 if (bitrate == 0)
mflodman2ebe5b12016-05-13 01:43:51 -0700285 return ZeroRateAllocation();
286
287 uint32_t sum_min_bitrates = 0;
mflodman101f2502016-06-09 17:21:19 +0200288 uint32_t sum_max_bitrates = 0;
289 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman2ebe5b12016-05-13 01:43:51 -0700290 sum_min_bitrates += observer_config.min_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200291 sum_max_bitrates += observer_config.max_bitrate_bps;
292 }
293
294 // Not enough for all observers to get an allocation, allocate according to:
295 // enforced min bitrate -> allocated bitrate previous round -> restart paused
296 // streams.
297 if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
perkjfea93092016-05-14 00:58:48 -0700298 return LowRateAllocation(bitrate);
mflodman2ebe5b12016-05-13 01:43:51 -0700299
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800300 // All observers will get their min bitrate plus a share of the rest. This
301 // share is allocated to each observer based on its bitrate_priority.
mflodman101f2502016-06-09 17:21:19 +0200302 if (bitrate <= sum_max_bitrates)
303 return NormalRateAllocation(bitrate, sum_min_bitrates);
mflodman2ebe5b12016-05-13 01:43:51 -0700304
mflodman101f2502016-06-09 17:21:19 +0200305 // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
306 return MaxRateAllocation(bitrate, sum_max_bitrates);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000307}
308
mflodman2ebe5b12016-05-13 01:43:51 -0700309BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
perkj26091b12016-09-01 01:17:40 -0700310 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman2ebe5b12016-05-13 01:43:51 -0700311 ObserverAllocation allocation;
mflodman2ebe5b12016-05-13 01:43:51 -0700312 for (const auto& observer_config : bitrate_observer_configs_)
313 allocation[observer_config.observer] = 0;
perkjec81bcd2016-05-11 06:01:13 -0700314 return allocation;
315}
316
mflodman2ebe5b12016-05-13 01:43:51 -0700317BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
Stefan Holmere5904162015-03-26 11:11:06 +0100318 uint32_t bitrate) {
perkj26091b12016-09-01 01:17:40 -0700319 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman2ebe5b12016-05-13 01:43:51 -0700320 ObserverAllocation allocation;
mflodman101f2502016-06-09 17:21:19 +0200321 // Start by allocating bitrate to observers enforcing a min bitrate, hence
322 // remaining_bitrate might turn negative.
323 int64_t remaining_bitrate = bitrate;
324 for (const auto& observer_config : bitrate_observer_configs_) {
325 int32_t allocated_bitrate = 0;
326 if (observer_config.enforce_min_bitrate)
327 allocated_bitrate = observer_config.min_bitrate_bps;
328
329 allocation[observer_config.observer] = allocated_bitrate;
330 remaining_bitrate -= allocated_bitrate;
331 }
332
333 // Allocate bitrate to all previously active streams.
334 if (remaining_bitrate > 0) {
mflodman2ebe5b12016-05-13 01:43:51 -0700335 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman101f2502016-06-09 17:21:19 +0200336 if (observer_config.enforce_min_bitrate ||
srte1eb051c2017-11-29 11:23:59 +0100337 observer_config.LastAllocatedBitrate() == 0)
mflodman101f2502016-06-09 17:21:19 +0200338 continue;
339
srte1eb051c2017-11-29 11:23:59 +0100340 uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
mflodman48a4beb2016-07-01 13:03:59 +0200341 if (remaining_bitrate >= required_bitrate) {
342 allocation[observer_config.observer] = required_bitrate;
343 remaining_bitrate -= required_bitrate;
mflodman101f2502016-06-09 17:21:19 +0200344 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000345 }
346 }
mflodman101f2502016-06-09 17:21:19 +0200347
348 // Allocate bitrate to previously paused streams.
349 if (remaining_bitrate > 0) {
350 for (const auto& observer_config : bitrate_observer_configs_) {
srte1eb051c2017-11-29 11:23:59 +0100351 if (observer_config.LastAllocatedBitrate() != 0)
mflodman101f2502016-06-09 17:21:19 +0200352 continue;
353
354 // Add a hysteresis to avoid toggling.
srte1eb051c2017-11-29 11:23:59 +0100355 uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
mflodman101f2502016-06-09 17:21:19 +0200356 if (remaining_bitrate >= required_bitrate) {
357 allocation[observer_config.observer] = required_bitrate;
358 remaining_bitrate -= required_bitrate;
359 }
360 }
361 }
362
363 // Split a possible remainder evenly on all streams with an allocation.
364 if (remaining_bitrate > 0)
365 DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
366
367 RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
Stefan Holmere5904162015-03-26 11:11:06 +0100368 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000369}
mflodman101f2502016-06-09 17:21:19 +0200370
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800371// Allocates the bitrate based on the bitrate priority of each observer. This
372// bitrate priority defines the priority for bitrate to be allocated to that
373// observer in relation to other observers. For example with two observers, if
374// observer 1 had a bitrate_priority = 1.0, and observer 2 has a
375// bitrate_priority = 2.0, the expected behavior is that observer 2 will be
376// allocated twice the bitrate as observer 1 above the each observer's
377// min_bitrate_bps values, until one of the observers hits its max_bitrate_bps.
mflodman101f2502016-06-09 17:21:19 +0200378BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
379 uint32_t bitrate,
380 uint32_t sum_min_bitrates) {
perkj26091b12016-09-01 01:17:40 -0700381 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman101f2502016-06-09 17:21:19 +0200382 ObserverAllocation allocation;
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800383 ObserverAllocation observers_capacities;
384 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman101f2502016-06-09 17:21:19 +0200385 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800386 observers_capacities[observer_config.observer] =
387 observer_config.max_bitrate_bps - observer_config.min_bitrate_bps;
388 }
mflodman101f2502016-06-09 17:21:19 +0200389
390 bitrate -= sum_min_bitrates;
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800391 // From the remaining bitrate, allocate a proportional amount to each observer
392 // above the min bitrate already allocated.
mflodman101f2502016-06-09 17:21:19 +0200393 if (bitrate > 0)
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800394 DistributeBitrateRelatively(bitrate, observers_capacities, &allocation);
mflodman101f2502016-06-09 17:21:19 +0200395
396 return allocation;
397}
398
399BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
perkj26091b12016-09-01 01:17:40 -0700400 uint32_t bitrate,
401 uint32_t sum_max_bitrates) {
402 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman101f2502016-06-09 17:21:19 +0200403 ObserverAllocation allocation;
404
405 for (const auto& observer_config : bitrate_observer_configs_) {
406 allocation[observer_config.observer] = observer_config.max_bitrate_bps;
407 bitrate -= observer_config.max_bitrate_bps;
408 }
409 DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
410 &allocation);
411 return allocation;
412}
413
srte1eb051c2017-11-29 11:23:59 +0100414uint32_t BitrateAllocator::ObserverConfig::LastAllocatedBitrate() const {
mflodman101f2502016-06-09 17:21:19 +0200415 // Return the configured minimum bitrate for newly added observers, to avoid
416 // requiring an extra high bitrate for the observer to get an allocated
417 // bitrate.
srte1eb051c2017-11-29 11:23:59 +0100418 return allocated_bitrate_bps == -1 ? min_bitrate_bps : allocated_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200419}
420
srte1eb051c2017-11-29 11:23:59 +0100421uint32_t BitrateAllocator::ObserverConfig::MinBitrateWithHysteresis() const {
422 uint32_t min_bitrate = min_bitrate_bps;
423 if (LastAllocatedBitrate() == 0) {
mflodman101f2502016-06-09 17:21:19 +0200424 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
425 kMinToggleBitrateBps);
426 }
mflodman48a4beb2016-07-01 13:03:59 +0200427 // Account for protection bitrate used by this observer in the previous
428 // allocation.
429 // Note: the ratio will only be updated when the stream is active, meaning a
430 // paused stream won't get any ratio updates. This might lead to waiting a bit
431 // longer than necessary if the network condition improves, but this is to
432 // avoid too much toggling.
srte1eb051c2017-11-29 11:23:59 +0100433 if (media_ratio > 0.0 && media_ratio < 1.0)
434 min_bitrate += min_bitrate * (1.0 - media_ratio);
mflodman48a4beb2016-07-01 13:03:59 +0200435
mflodman101f2502016-06-09 17:21:19 +0200436 return min_bitrate;
437}
438
439void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
440 bool include_zero_allocations,
441 int max_multiplier,
442 ObserverAllocation* allocation) {
perkj26091b12016-09-01 01:17:40 -0700443 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman101f2502016-06-09 17:21:19 +0200444 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
445
446 ObserverSortingMap list_max_bitrates;
447 for (const auto& observer_config : bitrate_observer_configs_) {
448 if (include_zero_allocations ||
449 allocation->at(observer_config.observer) != 0) {
450 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
451 observer_config.max_bitrate_bps, &observer_config));
452 }
453 }
454 auto it = list_max_bitrates.begin();
455 while (it != list_max_bitrates.end()) {
kwibergaf476c72016-11-28 15:21:39 -0800456 RTC_DCHECK_GT(bitrate, 0);
mflodman101f2502016-06-09 17:21:19 +0200457 uint32_t extra_allocation =
458 bitrate / static_cast<uint32_t>(list_max_bitrates.size());
459 uint32_t total_allocation =
460 extra_allocation + allocation->at(it->second->observer);
461 bitrate -= extra_allocation;
462 if (total_allocation > max_multiplier * it->first) {
463 // There is more than we can fit for this observer, carry over to the
464 // remaining observers.
465 bitrate += total_allocation - max_multiplier * it->first;
466 total_allocation = max_multiplier * it->first;
467 }
468 // Finally, update the allocation for this observer.
469 allocation->at(it->second->observer) = total_allocation;
470 it = list_max_bitrates.erase(it);
471 }
472}
473
474bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
475 uint32_t sum_min_bitrates) {
perkj26091b12016-09-01 01:17:40 -0700476 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman101f2502016-06-09 17:21:19 +0200477 if (bitrate < sum_min_bitrates)
478 return false;
479
perkj26091b12016-09-01 01:17:40 -0700480 uint32_t extra_bitrate_per_observer =
481 (bitrate - sum_min_bitrates) /
mflodman101f2502016-06-09 17:21:19 +0200482 static_cast<uint32_t>(bitrate_observer_configs_.size());
483 for (const auto& observer_config : bitrate_observer_configs_) {
484 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
srte1eb051c2017-11-29 11:23:59 +0100485 observer_config.MinBitrateWithHysteresis()) {
mflodman101f2502016-06-09 17:21:19 +0200486 return false;
philipel5ef2bc12017-02-21 07:28:31 -0800487 }
mflodman101f2502016-06-09 17:21:19 +0200488 }
489 return true;
490}
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800491
492void BitrateAllocator::DistributeBitrateRelatively(
493 uint32_t remaining_bitrate,
494 const ObserverAllocation& observers_capacities,
495 ObserverAllocation* allocation) {
496 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
497 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
498 RTC_DCHECK_EQ(observers_capacities.size(), bitrate_observer_configs_.size());
499
500 struct PriorityRateObserverConfig {
501 PriorityRateObserverConfig(BitrateAllocatorObserver* allocation_key,
502 uint32_t capacity_bps,
503 double bitrate_priority)
504 : allocation_key(allocation_key),
505 capacity_bps(capacity_bps),
506 bitrate_priority(bitrate_priority) {}
507
508 BitrateAllocatorObserver* allocation_key;
509 // The amount of bitrate bps that can be allocated to this observer.
510 uint32_t capacity_bps;
511 double bitrate_priority;
512
513 // We want to sort by which observers will be allocated their full capacity
514 // first. By dividing each observer's capacity by its bitrate priority we
515 // are "normalizing" the capacity of an observer by the rate it will be
516 // filled. This is because the amount allocated is based upon bitrate
517 // priority. We allocate twice as much bitrate to an observer with twice the
518 // bitrate priority of another.
519 bool operator<(const PriorityRateObserverConfig& other) const {
520 return capacity_bps / bitrate_priority <
521 other.capacity_bps / other.bitrate_priority;
522 }
523 };
524
525 double bitrate_priority_sum = 0;
526 std::vector<PriorityRateObserverConfig> priority_rate_observers;
527 for (const auto& observer_config : bitrate_observer_configs_) {
528 uint32_t capacity_bps = observers_capacities.at(observer_config.observer);
529 priority_rate_observers.emplace_back(observer_config.observer, capacity_bps,
530 observer_config.bitrate_priority);
531 bitrate_priority_sum += observer_config.bitrate_priority;
532 }
533
534 // Iterate in the order observers can be allocated their full capacity.
535 std::sort(priority_rate_observers.begin(), priority_rate_observers.end());
536 size_t i;
537 for (i = 0; i < priority_rate_observers.size(); ++i) {
538 const auto& priority_rate_observer = priority_rate_observers[i];
539 // We allocate the full capacity to an observer only if its relative
540 // portion from the remaining bitrate is sufficient to allocate its full
541 // capacity. This means we aren't greedily allocating the full capacity, but
542 // that it is only done when there is also enough bitrate to allocate the
543 // proportional amounts to all other observers.
544 double observer_share =
545 priority_rate_observer.bitrate_priority / bitrate_priority_sum;
546 double allocation_bps = observer_share * remaining_bitrate;
547 bool enough_bitrate = allocation_bps >= priority_rate_observer.capacity_bps;
548 if (!enough_bitrate)
549 break;
550 allocation->at(priority_rate_observer.allocation_key) +=
551 priority_rate_observer.capacity_bps;
552 remaining_bitrate -= priority_rate_observer.capacity_bps;
553 bitrate_priority_sum -= priority_rate_observer.bitrate_priority;
554 }
555
556 // From the remaining bitrate, allocate the proportional amounts to the
557 // observers that aren't allocated their max capacity.
558 for (; i < priority_rate_observers.size(); ++i) {
559 const auto& priority_rate_observer = priority_rate_observers[i];
560 double fraction_allocated =
561 priority_rate_observer.bitrate_priority / bitrate_priority_sum;
562 allocation->at(priority_rate_observer.allocation_key) +=
563 fraction_allocated * remaining_bitrate;
564 }
565}
566
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000567} // namespace webrtc