blob: e82123a8b09c9069342aa4aaa62e0793d3da5190 [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
perkj57c21f92016-06-17 07:27:16 -070056void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
57 uint32_t min_bitrate_bps,
58 uint32_t max_bitrate_bps,
59 uint32_t pad_up_bitrate_bps,
60 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;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000092}
93
perkj71ee44c2016-06-15 00:47:53 -070094void BitrateAllocator::UpdateAllocationLimits() {
95 uint32_t total_requested_padding_bitrate = 0;
96 uint32_t total_requested_min_bitrate = 0;
97
98 {
99 rtc::CritScope lock(&crit_sect_);
100 for (const auto& config : bitrate_observer_configs_) {
101 if (config.enforce_min_bitrate) {
102 total_requested_min_bitrate += config.min_bitrate_bps;
103 }
104 total_requested_padding_bitrate += config.pad_up_bitrate_bps;
105 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000106 }
perkj71ee44c2016-06-15 00:47:53 -0700107
108 limit_observer_->OnAllocationLimitsChanged(total_requested_min_bitrate,
109 total_requested_padding_bitrate);
110}
111
112void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
113 {
114 rtc::CritScope lock(&crit_sect_);
115 auto it = FindObserverConfig(observer);
116 if (it != bitrate_observer_configs_.end()) {
117 bitrate_observer_configs_.erase(it);
118 }
119 }
120 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000121}
122
perkj57c21f92016-06-17 07:27:16 -0700123int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
124 rtc::CritScope lock(&crit_sect_);
125 const auto& it = last_allocation_.find(observer);
126 if (it != last_allocation_.end())
127 return it->second;
128
129 // This is a new observer that has not yet been started. Assume that if it is
130 // added, all observers would split the available bitrate evenly.
131 return last_non_zero_bitrate_bps_ /
132 static_cast<int>((bitrate_observer_configs_.size() + 1));
133}
134
mflodman2ebe5b12016-05-13 01:43:51 -0700135BitrateAllocator::ObserverConfigList::iterator
136BitrateAllocator::FindObserverConfig(
137 const BitrateAllocatorObserver* observer) {
138 for (auto it = bitrate_observer_configs_.begin();
139 it != bitrate_observer_configs_.end(); ++it) {
140 if (it->observer == observer)
141 return it;
142 }
143 return bitrate_observer_configs_.end();
144}
145
perkjfea93092016-05-14 00:58:48 -0700146BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
147 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700148 if (bitrate_observer_configs_.empty())
149 return ObserverAllocation();
150
perkjfea93092016-05-14 00:58:48 -0700151 if (bitrate == 0)
mflodman2ebe5b12016-05-13 01:43:51 -0700152 return ZeroRateAllocation();
153
154 uint32_t sum_min_bitrates = 0;
mflodman101f2502016-06-09 17:21:19 +0200155 uint32_t sum_max_bitrates = 0;
156 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman2ebe5b12016-05-13 01:43:51 -0700157 sum_min_bitrates += observer_config.min_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200158 sum_max_bitrates += observer_config.max_bitrate_bps;
159 }
160
161 // Not enough for all observers to get an allocation, allocate according to:
162 // enforced min bitrate -> allocated bitrate previous round -> restart paused
163 // streams.
164 if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
perkjfea93092016-05-14 00:58:48 -0700165 return LowRateAllocation(bitrate);
mflodman2ebe5b12016-05-13 01:43:51 -0700166
mflodman101f2502016-06-09 17:21:19 +0200167 // All observers will get their min bitrate plus an even share of the rest.
168 if (bitrate <= sum_max_bitrates)
169 return NormalRateAllocation(bitrate, sum_min_bitrates);
mflodman2ebe5b12016-05-13 01:43:51 -0700170
mflodman101f2502016-06-09 17:21:19 +0200171 // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
172 return MaxRateAllocation(bitrate, sum_max_bitrates);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000173}
174
mflodman2ebe5b12016-05-13 01:43:51 -0700175BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
176 ObserverAllocation allocation;
mflodman2ebe5b12016-05-13 01:43:51 -0700177 for (const auto& observer_config : bitrate_observer_configs_)
178 allocation[observer_config.observer] = 0;
perkjec81bcd2016-05-11 06:01:13 -0700179 return allocation;
180}
181
mflodman2ebe5b12016-05-13 01:43:51 -0700182BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
Stefan Holmere5904162015-03-26 11:11:06 +0100183 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700184 ObserverAllocation allocation;
mflodman101f2502016-06-09 17:21:19 +0200185
186 // Start by allocating bitrate to observers enforcing a min bitrate, hence
187 // remaining_bitrate might turn negative.
188 int64_t remaining_bitrate = bitrate;
189 for (const auto& observer_config : bitrate_observer_configs_) {
190 int32_t allocated_bitrate = 0;
191 if (observer_config.enforce_min_bitrate)
192 allocated_bitrate = observer_config.min_bitrate_bps;
193
194 allocation[observer_config.observer] = allocated_bitrate;
195 remaining_bitrate -= allocated_bitrate;
196 }
197
198 // Allocate bitrate to all previously active streams.
199 if (remaining_bitrate > 0) {
mflodman2ebe5b12016-05-13 01:43:51 -0700200 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman101f2502016-06-09 17:21:19 +0200201 if (observer_config.enforce_min_bitrate ||
202 LastAllocatedBitrate(observer_config) == 0)
203 continue;
204
205 if (remaining_bitrate >= observer_config.min_bitrate_bps) {
206 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
207 remaining_bitrate -= observer_config.min_bitrate_bps;
208 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000209 }
210 }
mflodman101f2502016-06-09 17:21:19 +0200211
212 // Allocate bitrate to previously paused streams.
213 if (remaining_bitrate > 0) {
214 for (const auto& observer_config : bitrate_observer_configs_) {
215 if (LastAllocatedBitrate(observer_config) != 0)
216 continue;
217
218 // Add a hysteresis to avoid toggling.
219 uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
220 if (remaining_bitrate >= required_bitrate) {
221 allocation[observer_config.observer] = required_bitrate;
222 remaining_bitrate -= required_bitrate;
223 }
224 }
225 }
226
227 // Split a possible remainder evenly on all streams with an allocation.
228 if (remaining_bitrate > 0)
229 DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
230
231 RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
Stefan Holmere5904162015-03-26 11:11:06 +0100232 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000233}
mflodman101f2502016-06-09 17:21:19 +0200234
235BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
236 uint32_t bitrate,
237 uint32_t sum_min_bitrates) {
238
239 ObserverAllocation allocation;
240 for (const auto& observer_config : bitrate_observer_configs_)
241 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
242
243 bitrate -= sum_min_bitrates;
244 if (bitrate > 0)
245 DistributeBitrateEvenly(bitrate, true, 1, &allocation);
246
247 return allocation;
248}
249
250BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
251 uint32_t bitrate, uint32_t sum_max_bitrates) {
252 ObserverAllocation allocation;
253
254 for (const auto& observer_config : bitrate_observer_configs_) {
255 allocation[observer_config.observer] = observer_config.max_bitrate_bps;
256 bitrate -= observer_config.max_bitrate_bps;
257 }
258 DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
259 &allocation);
260 return allocation;
261}
262
263uint32_t BitrateAllocator::LastAllocatedBitrate(
264 const ObserverConfig& observer_config) {
265
266 const auto& it = last_allocation_.find(observer_config.observer);
267 if (it != last_allocation_.end())
268 return it->second;
269
270 // Return the configured minimum bitrate for newly added observers, to avoid
271 // requiring an extra high bitrate for the observer to get an allocated
272 // bitrate.
273 return observer_config.min_bitrate_bps;
274}
275
276uint32_t BitrateAllocator::MinBitrateWithHysteresis(
277 const ObserverConfig& observer_config) {
278 uint32_t min_bitrate = observer_config.min_bitrate_bps;
279 if (LastAllocatedBitrate(observer_config) == 0) {
280 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
281 kMinToggleBitrateBps);
282 }
283 return min_bitrate;
284}
285
286void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
287 bool include_zero_allocations,
288 int max_multiplier,
289 ObserverAllocation* allocation) {
290 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
291
292 ObserverSortingMap list_max_bitrates;
293 for (const auto& observer_config : bitrate_observer_configs_) {
294 if (include_zero_allocations ||
295 allocation->at(observer_config.observer) != 0) {
296 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
297 observer_config.max_bitrate_bps, &observer_config));
298 }
299 }
300 auto it = list_max_bitrates.begin();
301 while (it != list_max_bitrates.end()) {
302 RTC_DCHECK_GT(bitrate, 0u);
303 uint32_t extra_allocation =
304 bitrate / static_cast<uint32_t>(list_max_bitrates.size());
305 uint32_t total_allocation =
306 extra_allocation + allocation->at(it->second->observer);
307 bitrate -= extra_allocation;
308 if (total_allocation > max_multiplier * it->first) {
309 // There is more than we can fit for this observer, carry over to the
310 // remaining observers.
311 bitrate += total_allocation - max_multiplier * it->first;
312 total_allocation = max_multiplier * it->first;
313 }
314 // Finally, update the allocation for this observer.
315 allocation->at(it->second->observer) = total_allocation;
316 it = list_max_bitrates.erase(it);
317 }
318}
319
320bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
321 uint32_t sum_min_bitrates) {
322 if (bitrate < sum_min_bitrates)
323 return false;
324
325 uint32_t extra_bitrate_per_observer = (bitrate - sum_min_bitrates) /
326 static_cast<uint32_t>(bitrate_observer_configs_.size());
327 for (const auto& observer_config : bitrate_observer_configs_) {
328 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
329 MinBitrateWithHysteresis(observer_config))
330 return false;
331 }
332 return true;
333}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000334} // namespace webrtc