blob: 7e6242210cff6c78845446a9b3f65b67dfce5fa5 [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"
mflodman48a4beb2016-07-01 13:03:59 +020018#include "webrtc/base/logging.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000019#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
mflodman48a4beb2016-07-01 13:03:59 +020020#include "webrtc/system_wrappers/include/clock.h"
21#include "webrtc/system_wrappers/include/metrics.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000022
23namespace webrtc {
24
Stefan Holmere5904162015-03-26 11:11:06 +010025// Allow packets to be transmitted in up to 2 times max video bitrate if the
26// bandwidth estimate allows it.
27const int kTransmissionMaxBitrateMultiplier = 2;
28const int kDefaultBitrateBps = 300000;
29
mflodman101f2502016-06-09 17:21:19 +020030// Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
31const double kToggleFactor = 0.1;
32const uint32_t kMinToggleBitrateBps = 20000;
33
mflodman48a4beb2016-07-01 13:03:59 +020034const int64_t kBweLogIntervalMs = 5000;
35
36namespace {
37
38double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) {
39 RTC_DCHECK_GT(allocated_bitrate, 0u);
40 if (protection_bitrate == 0)
41 return 1.0;
42
43 uint32_t media_bitrate = allocated_bitrate - protection_bitrate;
44 return media_bitrate / static_cast<double>(allocated_bitrate);
45}
46} // namespace
47
perkj71ee44c2016-06-15 00:47:53 -070048BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
49 : limit_observer_(limit_observer),
50 bitrate_observer_configs_(),
Stefan Holmere5904162015-03-26 11:11:06 +010051 last_bitrate_bps_(kDefaultBitrateBps),
perkjfea93092016-05-14 00:58:48 -070052 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
Stefan Holmere5904162015-03-26 11:11:06 +010053 last_fraction_loss_(0),
mflodman48a4beb2016-07-01 13:03:59 +020054 last_rtt_(0),
55 num_pause_events_(0),
56 clock_(Clock::GetRealTimeClock()),
57 last_bwe_log_time_(0) {}
58
59BitrateAllocator::~BitrateAllocator() {
60 RTC_LOGGED_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
61 num_pause_events_);
62}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000063
perkj71ee44c2016-06-15 00:47:53 -070064void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
65 uint8_t fraction_loss,
66 int64_t rtt) {
tommi63cb4342016-01-20 02:32:54 -080067 rtc::CritScope lock(&crit_sect_);
mflodman101f2502016-06-09 17:21:19 +020068 last_bitrate_bps_ = target_bitrate_bps;
perkjfea93092016-05-14 00:58:48 -070069 last_non_zero_bitrate_bps_ =
mflodman101f2502016-06-09 17:21:19 +020070 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
Stefan Holmere5904162015-03-26 11:11:06 +010071 last_fraction_loss_ = fraction_loss;
72 last_rtt_ = rtt;
mflodman2ebe5b12016-05-13 01:43:51 -070073
mflodman48a4beb2016-07-01 13:03:59 +020074 // Periodically log the incoming BWE.
75 int64_t now = clock_->TimeInMilliseconds();
76 if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
77 LOG(LS_INFO) << "Current BWE " << target_bitrate_bps;
78 last_bwe_log_time_ = now;
sprang2f48d942015-11-05 04:25:49 -080079 }
mflodman48a4beb2016-07-01 13:03:59 +020080
81 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
82
83 for (auto& config : bitrate_observer_configs_) {
84 uint32_t allocated_bitrate = allocation[config.observer];
85 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
86 allocated_bitrate, last_fraction_loss_, last_rtt_);
87
88 if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
89 if (target_bitrate_bps > 0)
90 ++num_pause_events_;
91 // The protection bitrate is an estimate based on the ratio between media
92 // and protection used before this observer was muted.
93 uint32_t predicted_protection_bps =
94 (1.0 - config.media_ratio) * config.min_bitrate_bps;
95 LOG(LS_INFO) << "Pausing observer " << config.observer
96 << " with configured min bitrate " << config.min_bitrate_bps
97 << " and current estimate of " << target_bitrate_bps
98 << " and protection bitrate " << predicted_protection_bps;
99 } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
100 if (target_bitrate_bps > 0)
101 ++num_pause_events_;
102 LOG(LS_INFO) << "Resuming observer " << config.observer
103 << ", configured min bitrate " << config.min_bitrate_bps
104 << ", current allocation " << allocated_bitrate
105 << " and protection bitrate " << protection_bitrate;
106 }
107
108 // Only update the media ratio if the observer got an allocation.
109 if (allocated_bitrate > 0)
110 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
111 config.allocated_bitrate_bps = allocated_bitrate;
112 }
Stefan Holmere5904162015-03-26 11:11:06 +0100113}
114
perkj57c21f92016-06-17 07:27:16 -0700115void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
116 uint32_t min_bitrate_bps,
117 uint32_t max_bitrate_bps,
118 uint32_t pad_up_bitrate_bps,
119 bool enforce_min_bitrate) {
tommi63cb4342016-01-20 02:32:54 -0800120 rtc::CritScope lock(&crit_sect_);
mflodman2ebe5b12016-05-13 01:43:51 -0700121 auto it = FindObserverConfig(observer);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000122
mflodman101f2502016-06-09 17:21:19 +0200123 // Update settings if the observer already exists, create a new one otherwise.
mflodman2ebe5b12016-05-13 01:43:51 -0700124 if (it != bitrate_observer_configs_.end()) {
mflodman2ebe5b12016-05-13 01:43:51 -0700125 it->min_bitrate_bps = min_bitrate_bps;
126 it->max_bitrate_bps = max_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700127 it->pad_up_bitrate_bps = pad_up_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200128 it->enforce_min_bitrate = enforce_min_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000129 } else {
perkj71ee44c2016-06-15 00:47:53 -0700130 bitrate_observer_configs_.push_back(
131 ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
132 pad_up_bitrate_bps, enforce_min_bitrate));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000133 }
Stefan Holmere5904162015-03-26 11:11:06 +0100134
mflodman101f2502016-06-09 17:21:19 +0200135 ObserverAllocation allocation;
136 if (last_bitrate_bps_ > 0) {
137 // Calculate a new allocation and update all observers.
138 allocation = AllocateBitrates(last_bitrate_bps_);
mflodman48a4beb2016-07-01 13:03:59 +0200139 for (auto& config : bitrate_observer_configs_) {
140 uint32_t allocated_bitrate = allocation[config.observer];
141 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
142 allocated_bitrate, last_fraction_loss_, last_rtt_);
143 config.allocated_bitrate_bps = allocated_bitrate;
144 if (allocated_bitrate > 0)
145 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
146 }
perkjfea93092016-05-14 00:58:48 -0700147 } else {
148 // Currently, an encoder is not allowed to produce frames.
149 // But we still have to return the initial config bitrate + let the
150 // observer know that it can not produce frames.
mflodman101f2502016-06-09 17:21:19 +0200151 allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
perkjfea93092016-05-14 00:58:48 -0700152 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_);
Stefan Holmere5904162015-03-26 11:11:06 +0100153 }
perkj71ee44c2016-06-15 00:47:53 -0700154 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000155}
156
perkj71ee44c2016-06-15 00:47:53 -0700157void BitrateAllocator::UpdateAllocationLimits() {
158 uint32_t total_requested_padding_bitrate = 0;
159 uint32_t total_requested_min_bitrate = 0;
160
161 {
162 rtc::CritScope lock(&crit_sect_);
163 for (const auto& config : bitrate_observer_configs_) {
164 if (config.enforce_min_bitrate) {
165 total_requested_min_bitrate += config.min_bitrate_bps;
166 }
167 total_requested_padding_bitrate += config.pad_up_bitrate_bps;
168 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000169 }
perkj71ee44c2016-06-15 00:47:53 -0700170
171 limit_observer_->OnAllocationLimitsChanged(total_requested_min_bitrate,
172 total_requested_padding_bitrate);
173}
174
175void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
176 {
177 rtc::CritScope lock(&crit_sect_);
178 auto it = FindObserverConfig(observer);
179 if (it != bitrate_observer_configs_.end()) {
180 bitrate_observer_configs_.erase(it);
181 }
182 }
183 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000184}
185
perkj57c21f92016-06-17 07:27:16 -0700186int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
187 rtc::CritScope lock(&crit_sect_);
mflodman48a4beb2016-07-01 13:03:59 +0200188 const auto& it = FindObserverConfig(observer);
189 if (it == bitrate_observer_configs_.end()) {
190 // This observer hasn't been added yet, just give it its fair share.
191 return last_non_zero_bitrate_bps_ /
192 static_cast<int>((bitrate_observer_configs_.size() + 1));
193 } else if (it->allocated_bitrate_bps == -1) {
194 // This observer hasn't received an allocation yet, so do the same.
195 return last_non_zero_bitrate_bps_ /
196 static_cast<int>(bitrate_observer_configs_.size());
197 } else {
198 // This observer already has an allocation.
199 return it->allocated_bitrate_bps;
200 }
perkj57c21f92016-06-17 07:27:16 -0700201}
202
mflodman48a4beb2016-07-01 13:03:59 +0200203BitrateAllocator::ObserverConfigs::iterator
mflodman2ebe5b12016-05-13 01:43:51 -0700204BitrateAllocator::FindObserverConfig(
205 const BitrateAllocatorObserver* observer) {
206 for (auto it = bitrate_observer_configs_.begin();
207 it != bitrate_observer_configs_.end(); ++it) {
208 if (it->observer == observer)
209 return it;
210 }
211 return bitrate_observer_configs_.end();
212}
213
perkjfea93092016-05-14 00:58:48 -0700214BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
215 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700216 if (bitrate_observer_configs_.empty())
217 return ObserverAllocation();
218
perkjfea93092016-05-14 00:58:48 -0700219 if (bitrate == 0)
mflodman2ebe5b12016-05-13 01:43:51 -0700220 return ZeroRateAllocation();
221
222 uint32_t sum_min_bitrates = 0;
mflodman101f2502016-06-09 17:21:19 +0200223 uint32_t sum_max_bitrates = 0;
224 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman2ebe5b12016-05-13 01:43:51 -0700225 sum_min_bitrates += observer_config.min_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200226 sum_max_bitrates += observer_config.max_bitrate_bps;
227 }
228
229 // Not enough for all observers to get an allocation, allocate according to:
230 // enforced min bitrate -> allocated bitrate previous round -> restart paused
231 // streams.
232 if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
perkjfea93092016-05-14 00:58:48 -0700233 return LowRateAllocation(bitrate);
mflodman2ebe5b12016-05-13 01:43:51 -0700234
mflodman101f2502016-06-09 17:21:19 +0200235 // All observers will get their min bitrate plus an even share of the rest.
236 if (bitrate <= sum_max_bitrates)
237 return NormalRateAllocation(bitrate, sum_min_bitrates);
mflodman2ebe5b12016-05-13 01:43:51 -0700238
mflodman101f2502016-06-09 17:21:19 +0200239 // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
240 return MaxRateAllocation(bitrate, sum_max_bitrates);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000241}
242
mflodman2ebe5b12016-05-13 01:43:51 -0700243BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
244 ObserverAllocation allocation;
mflodman2ebe5b12016-05-13 01:43:51 -0700245 for (const auto& observer_config : bitrate_observer_configs_)
246 allocation[observer_config.observer] = 0;
perkjec81bcd2016-05-11 06:01:13 -0700247 return allocation;
248}
249
mflodman2ebe5b12016-05-13 01:43:51 -0700250BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
Stefan Holmere5904162015-03-26 11:11:06 +0100251 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700252 ObserverAllocation allocation;
mflodman101f2502016-06-09 17:21:19 +0200253
254 // Start by allocating bitrate to observers enforcing a min bitrate, hence
255 // remaining_bitrate might turn negative.
256 int64_t remaining_bitrate = bitrate;
257 for (const auto& observer_config : bitrate_observer_configs_) {
258 int32_t allocated_bitrate = 0;
259 if (observer_config.enforce_min_bitrate)
260 allocated_bitrate = observer_config.min_bitrate_bps;
261
262 allocation[observer_config.observer] = allocated_bitrate;
263 remaining_bitrate -= allocated_bitrate;
264 }
265
266 // Allocate bitrate to all previously active streams.
267 if (remaining_bitrate > 0) {
mflodman2ebe5b12016-05-13 01:43:51 -0700268 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman101f2502016-06-09 17:21:19 +0200269 if (observer_config.enforce_min_bitrate ||
270 LastAllocatedBitrate(observer_config) == 0)
271 continue;
272
mflodman48a4beb2016-07-01 13:03:59 +0200273 uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
274 if (remaining_bitrate >= required_bitrate) {
275 allocation[observer_config.observer] = required_bitrate;
276 remaining_bitrate -= required_bitrate;
mflodman101f2502016-06-09 17:21:19 +0200277 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000278 }
279 }
mflodman101f2502016-06-09 17:21:19 +0200280
281 // Allocate bitrate to previously paused streams.
282 if (remaining_bitrate > 0) {
283 for (const auto& observer_config : bitrate_observer_configs_) {
284 if (LastAllocatedBitrate(observer_config) != 0)
285 continue;
286
287 // Add a hysteresis to avoid toggling.
288 uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
289 if (remaining_bitrate >= required_bitrate) {
290 allocation[observer_config.observer] = required_bitrate;
291 remaining_bitrate -= required_bitrate;
292 }
293 }
294 }
295
296 // Split a possible remainder evenly on all streams with an allocation.
297 if (remaining_bitrate > 0)
298 DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
299
300 RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
Stefan Holmere5904162015-03-26 11:11:06 +0100301 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000302}
mflodman101f2502016-06-09 17:21:19 +0200303
304BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
305 uint32_t bitrate,
306 uint32_t sum_min_bitrates) {
307
308 ObserverAllocation allocation;
309 for (const auto& observer_config : bitrate_observer_configs_)
310 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
311
312 bitrate -= sum_min_bitrates;
313 if (bitrate > 0)
314 DistributeBitrateEvenly(bitrate, true, 1, &allocation);
315
316 return allocation;
317}
318
319BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
320 uint32_t bitrate, uint32_t sum_max_bitrates) {
321 ObserverAllocation allocation;
322
323 for (const auto& observer_config : bitrate_observer_configs_) {
324 allocation[observer_config.observer] = observer_config.max_bitrate_bps;
325 bitrate -= observer_config.max_bitrate_bps;
326 }
327 DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
328 &allocation);
329 return allocation;
330}
331
332uint32_t BitrateAllocator::LastAllocatedBitrate(
333 const ObserverConfig& observer_config) {
334
mflodman101f2502016-06-09 17:21:19 +0200335 // Return the configured minimum bitrate for newly added observers, to avoid
336 // requiring an extra high bitrate for the observer to get an allocated
337 // bitrate.
mflodman48a4beb2016-07-01 13:03:59 +0200338 return observer_config.allocated_bitrate_bps == -1 ?
339 observer_config.min_bitrate_bps : observer_config.allocated_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200340}
341
342uint32_t BitrateAllocator::MinBitrateWithHysteresis(
343 const ObserverConfig& observer_config) {
344 uint32_t min_bitrate = observer_config.min_bitrate_bps;
345 if (LastAllocatedBitrate(observer_config) == 0) {
346 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
347 kMinToggleBitrateBps);
348 }
mflodman48a4beb2016-07-01 13:03:59 +0200349 // Account for protection bitrate used by this observer in the previous
350 // allocation.
351 // Note: the ratio will only be updated when the stream is active, meaning a
352 // paused stream won't get any ratio updates. This might lead to waiting a bit
353 // longer than necessary if the network condition improves, but this is to
354 // avoid too much toggling.
355 if (observer_config.media_ratio > 0.0 && observer_config.media_ratio < 1.0)
356 min_bitrate += min_bitrate * (1.0 - observer_config.media_ratio);
357
mflodman101f2502016-06-09 17:21:19 +0200358 return min_bitrate;
359}
360
361void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
362 bool include_zero_allocations,
363 int max_multiplier,
364 ObserverAllocation* allocation) {
365 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
366
367 ObserverSortingMap list_max_bitrates;
368 for (const auto& observer_config : bitrate_observer_configs_) {
369 if (include_zero_allocations ||
370 allocation->at(observer_config.observer) != 0) {
371 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
372 observer_config.max_bitrate_bps, &observer_config));
373 }
374 }
375 auto it = list_max_bitrates.begin();
376 while (it != list_max_bitrates.end()) {
377 RTC_DCHECK_GT(bitrate, 0u);
378 uint32_t extra_allocation =
379 bitrate / static_cast<uint32_t>(list_max_bitrates.size());
380 uint32_t total_allocation =
381 extra_allocation + allocation->at(it->second->observer);
382 bitrate -= extra_allocation;
383 if (total_allocation > max_multiplier * it->first) {
384 // There is more than we can fit for this observer, carry over to the
385 // remaining observers.
386 bitrate += total_allocation - max_multiplier * it->first;
387 total_allocation = max_multiplier * it->first;
388 }
389 // Finally, update the allocation for this observer.
390 allocation->at(it->second->observer) = total_allocation;
391 it = list_max_bitrates.erase(it);
392 }
393}
394
395bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
396 uint32_t sum_min_bitrates) {
397 if (bitrate < sum_min_bitrates)
398 return false;
399
400 uint32_t extra_bitrate_per_observer = (bitrate - sum_min_bitrates) /
401 static_cast<uint32_t>(bitrate_observer_configs_.size());
402 for (const auto& observer_config : bitrate_observer_configs_) {
403 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
404 MinBitrateWithHysteresis(observer_config))
405 return false;
406 }
407 return true;
408}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000409} // namespace webrtc