blob: e20c34e05d560e2d32657600a25d64a8d5838a0e [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
mflodman0e7e2592015-11-12 21:02:42 -080012#include "webrtc/call/bitrate_allocator.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000013
14#include <algorithm>
15#include <utility>
16
mflodman2ebe5b12016-05-13 01:43:51 -070017#include "webrtc/base/checks.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000018#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
19
20namespace webrtc {
21
Stefan Holmere5904162015-03-26 11:11:06 +010022// Allow packets to be transmitted in up to 2 times max video bitrate if the
23// bandwidth estimate allows it.
24const int kTransmissionMaxBitrateMultiplier = 2;
25const int kDefaultBitrateBps = 300000;
26
mflodman101f2502016-06-09 17:21:19 +020027// Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
28const double kToggleFactor = 0.1;
29const uint32_t kMinToggleBitrateBps = 20000;
30
perkj71ee44c2016-06-15 00:47:53 -070031BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
32 : limit_observer_(limit_observer),
33 bitrate_observer_configs_(),
Stefan Holmere5904162015-03-26 11:11:06 +010034 last_bitrate_bps_(kDefaultBitrateBps),
perkjfea93092016-05-14 00:58:48 -070035 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
Stefan Holmere5904162015-03-26 11:11:06 +010036 last_fraction_loss_(0),
sprang2f48d942015-11-05 04:25:49 -080037 last_rtt_(0) {}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000038
perkj71ee44c2016-06-15 00:47:53 -070039void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
40 uint8_t fraction_loss,
41 int64_t rtt) {
tommi63cb4342016-01-20 02:32:54 -080042 rtc::CritScope lock(&crit_sect_);
mflodman101f2502016-06-09 17:21:19 +020043 last_bitrate_bps_ = target_bitrate_bps;
perkjfea93092016-05-14 00:58:48 -070044 last_non_zero_bitrate_bps_ =
mflodman101f2502016-06-09 17:21:19 +020045 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
Stefan Holmere5904162015-03-26 11:11:06 +010046 last_fraction_loss_ = fraction_loss;
47 last_rtt_ = rtt;
mflodman2ebe5b12016-05-13 01:43:51 -070048
mflodman101f2502016-06-09 17:21:19 +020049 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
sprang2f48d942015-11-05 04:25:49 -080050 for (const auto& kv : allocation) {
mflodman86aabb22016-03-11 15:44:32 +010051 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
sprang2f48d942015-11-05 04:25:49 -080052 }
mflodman101f2502016-06-09 17:21:19 +020053 last_allocation_ = allocation;
Stefan Holmere5904162015-03-26 11:11:06 +010054}
55
mflodman86aabb22016-03-11 15:44:32 +010056int BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
57 uint32_t min_bitrate_bps,
mflodman2ebe5b12016-05-13 01:43:51 -070058 uint32_t max_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -070059 uint32_t pad_up_bitrate_bps,
mflodman2ebe5b12016-05-13 01:43:51 -070060 bool enforce_min_bitrate) {
tommi63cb4342016-01-20 02:32:54 -080061 rtc::CritScope lock(&crit_sect_);
mflodman2ebe5b12016-05-13 01:43:51 -070062 auto it = FindObserverConfig(observer);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000063
mflodman101f2502016-06-09 17:21:19 +020064 // Update settings if the observer already exists, create a new one otherwise.
mflodman2ebe5b12016-05-13 01:43:51 -070065 if (it != bitrate_observer_configs_.end()) {
mflodman2ebe5b12016-05-13 01:43:51 -070066 it->min_bitrate_bps = min_bitrate_bps;
67 it->max_bitrate_bps = max_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -070068 it->pad_up_bitrate_bps = pad_up_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +020069 it->enforce_min_bitrate = enforce_min_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000070 } else {
perkj71ee44c2016-06-15 00:47:53 -070071 bitrate_observer_configs_.push_back(
72 ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
73 pad_up_bitrate_bps, enforce_min_bitrate));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000074 }
Stefan Holmere5904162015-03-26 11:11:06 +010075
mflodman101f2502016-06-09 17:21:19 +020076 ObserverAllocation allocation;
77 if (last_bitrate_bps_ > 0) {
78 // Calculate a new allocation and update all observers.
79 allocation = AllocateBitrates(last_bitrate_bps_);
80 for (const auto& kv : allocation)
perkjfea93092016-05-14 00:58:48 -070081 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
perkjfea93092016-05-14 00:58:48 -070082 } else {
83 // Currently, an encoder is not allowed to produce frames.
84 // But we still have to return the initial config bitrate + let the
85 // observer know that it can not produce frames.
mflodman101f2502016-06-09 17:21:19 +020086 allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
perkjfea93092016-05-14 00:58:48 -070087 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_);
Stefan Holmere5904162015-03-26 11:11:06 +010088 }
perkj71ee44c2016-06-15 00:47:53 -070089 UpdateAllocationLimits();
90
mflodman101f2502016-06-09 17:21:19 +020091 last_allocation_ = allocation;
92 return allocation[observer];
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000093}
94
perkj71ee44c2016-06-15 00:47:53 -070095void BitrateAllocator::UpdateAllocationLimits() {
96 uint32_t total_requested_padding_bitrate = 0;
97 uint32_t total_requested_min_bitrate = 0;
98
99 {
100 rtc::CritScope lock(&crit_sect_);
101 for (const auto& config : bitrate_observer_configs_) {
102 if (config.enforce_min_bitrate) {
103 total_requested_min_bitrate += config.min_bitrate_bps;
104 }
105 total_requested_padding_bitrate += config.pad_up_bitrate_bps;
106 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000107 }
perkj71ee44c2016-06-15 00:47:53 -0700108
109 limit_observer_->OnAllocationLimitsChanged(total_requested_min_bitrate,
110 total_requested_padding_bitrate);
111}
112
113void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
114 {
115 rtc::CritScope lock(&crit_sect_);
116 auto it = FindObserverConfig(observer);
117 if (it != bitrate_observer_configs_.end()) {
118 bitrate_observer_configs_.erase(it);
119 }
120 }
121 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000122}
123
mflodman2ebe5b12016-05-13 01:43:51 -0700124BitrateAllocator::ObserverConfigList::iterator
125BitrateAllocator::FindObserverConfig(
126 const BitrateAllocatorObserver* observer) {
127 for (auto it = bitrate_observer_configs_.begin();
128 it != bitrate_observer_configs_.end(); ++it) {
129 if (it->observer == observer)
130 return it;
131 }
132 return bitrate_observer_configs_.end();
133}
134
perkjfea93092016-05-14 00:58:48 -0700135BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
136 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700137 if (bitrate_observer_configs_.empty())
138 return ObserverAllocation();
139
perkjfea93092016-05-14 00:58:48 -0700140 if (bitrate == 0)
mflodman2ebe5b12016-05-13 01:43:51 -0700141 return ZeroRateAllocation();
142
143 uint32_t sum_min_bitrates = 0;
mflodman101f2502016-06-09 17:21:19 +0200144 uint32_t sum_max_bitrates = 0;
145 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman2ebe5b12016-05-13 01:43:51 -0700146 sum_min_bitrates += observer_config.min_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200147 sum_max_bitrates += observer_config.max_bitrate_bps;
148 }
149
150 // Not enough for all observers to get an allocation, allocate according to:
151 // enforced min bitrate -> allocated bitrate previous round -> restart paused
152 // streams.
153 if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
perkjfea93092016-05-14 00:58:48 -0700154 return LowRateAllocation(bitrate);
mflodman2ebe5b12016-05-13 01:43:51 -0700155
mflodman101f2502016-06-09 17:21:19 +0200156 // All observers will get their min bitrate plus an even share of the rest.
157 if (bitrate <= sum_max_bitrates)
158 return NormalRateAllocation(bitrate, sum_min_bitrates);
mflodman2ebe5b12016-05-13 01:43:51 -0700159
mflodman101f2502016-06-09 17:21:19 +0200160 // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
161 return MaxRateAllocation(bitrate, sum_max_bitrates);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000162}
163
mflodman2ebe5b12016-05-13 01:43:51 -0700164BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
165 ObserverAllocation allocation;
mflodman2ebe5b12016-05-13 01:43:51 -0700166 for (const auto& observer_config : bitrate_observer_configs_)
167 allocation[observer_config.observer] = 0;
perkjec81bcd2016-05-11 06:01:13 -0700168 return allocation;
169}
170
mflodman2ebe5b12016-05-13 01:43:51 -0700171BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
Stefan Holmere5904162015-03-26 11:11:06 +0100172 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700173 ObserverAllocation allocation;
mflodman101f2502016-06-09 17:21:19 +0200174
175 // Start by allocating bitrate to observers enforcing a min bitrate, hence
176 // remaining_bitrate might turn negative.
177 int64_t remaining_bitrate = bitrate;
178 for (const auto& observer_config : bitrate_observer_configs_) {
179 int32_t allocated_bitrate = 0;
180 if (observer_config.enforce_min_bitrate)
181 allocated_bitrate = observer_config.min_bitrate_bps;
182
183 allocation[observer_config.observer] = allocated_bitrate;
184 remaining_bitrate -= allocated_bitrate;
185 }
186
187 // Allocate bitrate to all previously active streams.
188 if (remaining_bitrate > 0) {
mflodman2ebe5b12016-05-13 01:43:51 -0700189 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman101f2502016-06-09 17:21:19 +0200190 if (observer_config.enforce_min_bitrate ||
191 LastAllocatedBitrate(observer_config) == 0)
192 continue;
193
194 if (remaining_bitrate >= observer_config.min_bitrate_bps) {
195 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
196 remaining_bitrate -= observer_config.min_bitrate_bps;
197 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000198 }
199 }
mflodman101f2502016-06-09 17:21:19 +0200200
201 // Allocate bitrate to previously paused streams.
202 if (remaining_bitrate > 0) {
203 for (const auto& observer_config : bitrate_observer_configs_) {
204 if (LastAllocatedBitrate(observer_config) != 0)
205 continue;
206
207 // Add a hysteresis to avoid toggling.
208 uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
209 if (remaining_bitrate >= required_bitrate) {
210 allocation[observer_config.observer] = required_bitrate;
211 remaining_bitrate -= required_bitrate;
212 }
213 }
214 }
215
216 // Split a possible remainder evenly on all streams with an allocation.
217 if (remaining_bitrate > 0)
218 DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
219
220 RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
Stefan Holmere5904162015-03-26 11:11:06 +0100221 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000222}
mflodman101f2502016-06-09 17:21:19 +0200223
224BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
225 uint32_t bitrate,
226 uint32_t sum_min_bitrates) {
227
228 ObserverAllocation allocation;
229 for (const auto& observer_config : bitrate_observer_configs_)
230 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
231
232 bitrate -= sum_min_bitrates;
233 if (bitrate > 0)
234 DistributeBitrateEvenly(bitrate, true, 1, &allocation);
235
236 return allocation;
237}
238
239BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
240 uint32_t bitrate, uint32_t sum_max_bitrates) {
241 ObserverAllocation allocation;
242
243 for (const auto& observer_config : bitrate_observer_configs_) {
244 allocation[observer_config.observer] = observer_config.max_bitrate_bps;
245 bitrate -= observer_config.max_bitrate_bps;
246 }
247 DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
248 &allocation);
249 return allocation;
250}
251
252uint32_t BitrateAllocator::LastAllocatedBitrate(
253 const ObserverConfig& observer_config) {
254
255 const auto& it = last_allocation_.find(observer_config.observer);
256 if (it != last_allocation_.end())
257 return it->second;
258
259 // Return the configured minimum bitrate for newly added observers, to avoid
260 // requiring an extra high bitrate for the observer to get an allocated
261 // bitrate.
262 return observer_config.min_bitrate_bps;
263}
264
265uint32_t BitrateAllocator::MinBitrateWithHysteresis(
266 const ObserverConfig& observer_config) {
267 uint32_t min_bitrate = observer_config.min_bitrate_bps;
268 if (LastAllocatedBitrate(observer_config) == 0) {
269 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
270 kMinToggleBitrateBps);
271 }
272 return min_bitrate;
273}
274
275void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
276 bool include_zero_allocations,
277 int max_multiplier,
278 ObserverAllocation* allocation) {
279 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
280
281 ObserverSortingMap list_max_bitrates;
282 for (const auto& observer_config : bitrate_observer_configs_) {
283 if (include_zero_allocations ||
284 allocation->at(observer_config.observer) != 0) {
285 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
286 observer_config.max_bitrate_bps, &observer_config));
287 }
288 }
289 auto it = list_max_bitrates.begin();
290 while (it != list_max_bitrates.end()) {
291 RTC_DCHECK_GT(bitrate, 0u);
292 uint32_t extra_allocation =
293 bitrate / static_cast<uint32_t>(list_max_bitrates.size());
294 uint32_t total_allocation =
295 extra_allocation + allocation->at(it->second->observer);
296 bitrate -= extra_allocation;
297 if (total_allocation > max_multiplier * it->first) {
298 // There is more than we can fit for this observer, carry over to the
299 // remaining observers.
300 bitrate += total_allocation - max_multiplier * it->first;
301 total_allocation = max_multiplier * it->first;
302 }
303 // Finally, update the allocation for this observer.
304 allocation->at(it->second->observer) = total_allocation;
305 it = list_max_bitrates.erase(it);
306 }
307}
308
309bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
310 uint32_t sum_min_bitrates) {
311 if (bitrate < sum_min_bitrates)
312 return false;
313
314 uint32_t extra_bitrate_per_observer = (bitrate - sum_min_bitrates) /
315 static_cast<uint32_t>(bitrate_observer_configs_.size());
316 for (const auto& observer_config : bitrate_observer_configs_) {
317 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
318 MinBitrateWithHysteresis(observer_config))
319 return false;
320 }
321 return true;
322}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000323} // namespace webrtc