blob: e82123a8b09c9069342aa4aaa62e0793d3da5190 [file] [log] [blame]
stefan@webrtc.org3ada29b2015-03-04 12:24:261/*
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
mflodman1b78cc32015-11-13 05:02:4212#include "webrtc/call/bitrate_allocator.h"
stefan@webrtc.org3ada29b2015-03-04 12:24:2613
14#include <algorithm>
15#include <utility>
16
mflodmanbe623892016-05-13 08:43:5117#include "webrtc/base/checks.h"
stefan@webrtc.org3ada29b2015-03-04 12:24:2618#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
19
20namespace webrtc {
21
Stefan Holmerca55fa12015-03-26 10:11:0622// 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
mflodmane956cc42016-06-09 15:21:1927// Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
28const double kToggleFactor = 0.1;
29const uint32_t kMinToggleBitrateBps = 20000;
30
perkj42209be2016-06-15 07:47:5331BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
32 : limit_observer_(limit_observer),
33 bitrate_observer_configs_(),
Stefan Holmerca55fa12015-03-26 10:11:0634 last_bitrate_bps_(kDefaultBitrateBps),
perkj9323ef02016-05-14 07:58:4835 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
Stefan Holmerca55fa12015-03-26 10:11:0636 last_fraction_loss_(0),
sprang2cded7a2015-11-05 12:25:4937 last_rtt_(0) {}
stefan@webrtc.org3ada29b2015-03-04 12:24:2638
perkj42209be2016-06-15 07:47:5339void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
40 uint8_t fraction_loss,
41 int64_t rtt) {
tommie2095e42016-01-20 10:32:5442 rtc::CritScope lock(&crit_sect_);
mflodmane956cc42016-06-09 15:21:1943 last_bitrate_bps_ = target_bitrate_bps;
perkj9323ef02016-05-14 07:58:4844 last_non_zero_bitrate_bps_ =
mflodmane956cc42016-06-09 15:21:1945 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
Stefan Holmerca55fa12015-03-26 10:11:0646 last_fraction_loss_ = fraction_loss;
47 last_rtt_ = rtt;
mflodmanbe623892016-05-13 08:43:5148
mflodmane956cc42016-06-09 15:21:1949 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
sprang2cded7a2015-11-05 12:25:4950 for (const auto& kv : allocation) {
mflodman3e089d32016-03-11 14:44:3251 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
sprang2cded7a2015-11-05 12:25:4952 }
mflodmane956cc42016-06-09 15:21:1953 last_allocation_ = allocation;
Stefan Holmerca55fa12015-03-26 10:11:0654}
55
perkjb3f05f42016-06-17 14:27:1656void 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) {
tommie2095e42016-01-20 10:32:5461 rtc::CritScope lock(&crit_sect_);
mflodmanbe623892016-05-13 08:43:5162 auto it = FindObserverConfig(observer);
stefan@webrtc.org3ada29b2015-03-04 12:24:2663
mflodmane956cc42016-06-09 15:21:1964 // Update settings if the observer already exists, create a new one otherwise.
mflodmanbe623892016-05-13 08:43:5165 if (it != bitrate_observer_configs_.end()) {
mflodmanbe623892016-05-13 08:43:5166 it->min_bitrate_bps = min_bitrate_bps;
67 it->max_bitrate_bps = max_bitrate_bps;
perkj42209be2016-06-15 07:47:5368 it->pad_up_bitrate_bps = pad_up_bitrate_bps;
mflodmane956cc42016-06-09 15:21:1969 it->enforce_min_bitrate = enforce_min_bitrate;
stefan@webrtc.org3ada29b2015-03-04 12:24:2670 } else {
perkj42209be2016-06-15 07:47:5371 bitrate_observer_configs_.push_back(
72 ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
73 pad_up_bitrate_bps, enforce_min_bitrate));
stefan@webrtc.org3ada29b2015-03-04 12:24:2674 }
Stefan Holmerca55fa12015-03-26 10:11:0675
mflodmane956cc42016-06-09 15:21:1976 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)
perkj9323ef02016-05-14 07:58:4881 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
perkj9323ef02016-05-14 07:58:4882 } 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.
mflodmane956cc42016-06-09 15:21:1986 allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
perkj9323ef02016-05-14 07:58:4887 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_);
Stefan Holmerca55fa12015-03-26 10:11:0688 }
perkj42209be2016-06-15 07:47:5389 UpdateAllocationLimits();
90
mflodmane956cc42016-06-09 15:21:1991 last_allocation_ = allocation;
stefan@webrtc.org3ada29b2015-03-04 12:24:2692}
93
perkj42209be2016-06-15 07:47:5394void 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.org3ada29b2015-03-04 12:24:26106 }
perkj42209be2016-06-15 07:47:53107
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.org3ada29b2015-03-04 12:24:26121}
122
perkjb3f05f42016-06-17 14:27:16123int 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
mflodmanbe623892016-05-13 08:43:51135BitrateAllocator::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
perkj9323ef02016-05-14 07:58:48146BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
147 uint32_t bitrate) {
mflodmanbe623892016-05-13 08:43:51148 if (bitrate_observer_configs_.empty())
149 return ObserverAllocation();
150
perkj9323ef02016-05-14 07:58:48151 if (bitrate == 0)
mflodmanbe623892016-05-13 08:43:51152 return ZeroRateAllocation();
153
154 uint32_t sum_min_bitrates = 0;
mflodmane956cc42016-06-09 15:21:19155 uint32_t sum_max_bitrates = 0;
156 for (const auto& observer_config : bitrate_observer_configs_) {
mflodmanbe623892016-05-13 08:43:51157 sum_min_bitrates += observer_config.min_bitrate_bps;
mflodmane956cc42016-06-09 15:21:19158 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))
perkj9323ef02016-05-14 07:58:48165 return LowRateAllocation(bitrate);
mflodmanbe623892016-05-13 08:43:51166
mflodmane956cc42016-06-09 15:21:19167 // 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);
mflodmanbe623892016-05-13 08:43:51170
mflodmane956cc42016-06-09 15:21:19171 // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
172 return MaxRateAllocation(bitrate, sum_max_bitrates);
stefan@webrtc.org3ada29b2015-03-04 12:24:26173}
174
mflodmanbe623892016-05-13 08:43:51175BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
176 ObserverAllocation allocation;
mflodmanbe623892016-05-13 08:43:51177 for (const auto& observer_config : bitrate_observer_configs_)
178 allocation[observer_config.observer] = 0;
perkjd6e6c8d2016-05-11 13:01:13179 return allocation;
180}
181
mflodmanbe623892016-05-13 08:43:51182BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
Stefan Holmerca55fa12015-03-26 10:11:06183 uint32_t bitrate) {
mflodmanbe623892016-05-13 08:43:51184 ObserverAllocation allocation;
mflodmane956cc42016-06-09 15:21:19185
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) {
mflodmanbe623892016-05-13 08:43:51200 for (const auto& observer_config : bitrate_observer_configs_) {
mflodmane956cc42016-06-09 15:21:19201 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.org3ada29b2015-03-04 12:24:26209 }
210 }
mflodmane956cc42016-06-09 15:21:19211
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 Holmerca55fa12015-03-26 10:11:06232 return allocation;
stefan@webrtc.org3ada29b2015-03-04 12:24:26233}
mflodmane956cc42016-06-09 15:21:19234
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.org3ada29b2015-03-04 12:24:26334} // namespace webrtc