Line data Source code
1 : /*
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 :
12 : #include "webrtc/call/bitrate_allocator.h"
13 :
14 : #include <algorithm>
15 : #include <utility>
16 :
17 : #include "webrtc/base/checks.h"
18 : #include "webrtc/base/logging.h"
19 : #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
20 : #include "webrtc/system_wrappers/include/clock.h"
21 : #include "webrtc/system_wrappers/include/metrics.h"
22 :
23 : namespace webrtc {
24 :
25 : // Allow packets to be transmitted in up to 2 times max video bitrate if the
26 : // bandwidth estimate allows it.
27 : const int kTransmissionMaxBitrateMultiplier = 2;
28 : const int kDefaultBitrateBps = 300000;
29 :
30 : // Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
31 : const double kToggleFactor = 0.1;
32 : const uint32_t kMinToggleBitrateBps = 20000;
33 :
34 : const int64_t kBweLogIntervalMs = 5000;
35 :
36 : namespace {
37 :
38 0 : double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) {
39 0 : RTC_DCHECK_GT(allocated_bitrate, 0);
40 0 : if (protection_bitrate == 0)
41 0 : return 1.0;
42 :
43 0 : uint32_t media_bitrate = allocated_bitrate - protection_bitrate;
44 0 : return media_bitrate / static_cast<double>(allocated_bitrate);
45 : }
46 : } // namespace
47 :
48 0 : BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
49 : : limit_observer_(limit_observer),
50 : bitrate_observer_configs_(),
51 : last_bitrate_bps_(0),
52 : last_non_zero_bitrate_bps_(kDefaultBitrateBps),
53 : last_fraction_loss_(0),
54 : last_rtt_(0),
55 : num_pause_events_(0),
56 0 : clock_(Clock::GetRealTimeClock()),
57 0 : last_bwe_log_time_(0) {
58 0 : sequenced_checker_.Detach();
59 0 : }
60 :
61 0 : BitrateAllocator::~BitrateAllocator() {
62 0 : RTC_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
63 : num_pause_events_);
64 0 : }
65 :
66 0 : void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
67 : uint8_t fraction_loss,
68 : int64_t rtt,
69 : int64_t probing_interval_ms) {
70 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
71 0 : last_bitrate_bps_ = target_bitrate_bps;
72 0 : last_non_zero_bitrate_bps_ =
73 0 : target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
74 0 : last_fraction_loss_ = fraction_loss;
75 0 : last_rtt_ = rtt;
76 0 : last_probing_interval_ms_ = probing_interval_ms;
77 :
78 : // Periodically log the incoming BWE.
79 0 : int64_t now = clock_->TimeInMilliseconds();
80 0 : if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
81 0 : LOG(LS_INFO) << "Current BWE " << target_bitrate_bps;
82 0 : last_bwe_log_time_ = now;
83 : }
84 :
85 0 : ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
86 :
87 0 : for (auto& config : bitrate_observer_configs_) {
88 0 : uint32_t allocated_bitrate = allocation[config.observer];
89 0 : uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
90 0 : allocated_bitrate, last_fraction_loss_, last_rtt_,
91 0 : last_probing_interval_ms_);
92 :
93 0 : if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
94 0 : if (target_bitrate_bps > 0)
95 0 : ++num_pause_events_;
96 : // The protection bitrate is an estimate based on the ratio between media
97 : // and protection used before this observer was muted.
98 : uint32_t predicted_protection_bps =
99 0 : (1.0 - config.media_ratio) * config.min_bitrate_bps;
100 0 : LOG(LS_INFO) << "Pausing observer " << config.observer
101 0 : << " with configured min bitrate " << config.min_bitrate_bps
102 0 : << " and current estimate of " << target_bitrate_bps
103 0 : << " and protection bitrate " << predicted_protection_bps;
104 0 : } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
105 0 : if (target_bitrate_bps > 0)
106 0 : ++num_pause_events_;
107 0 : LOG(LS_INFO) << "Resuming observer " << config.observer
108 0 : << ", configured min bitrate " << config.min_bitrate_bps
109 0 : << ", current allocation " << allocated_bitrate
110 0 : << " and protection bitrate " << protection_bitrate;
111 : }
112 :
113 : // Only update the media ratio if the observer got an allocation.
114 0 : if (allocated_bitrate > 0)
115 0 : config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
116 0 : config.allocated_bitrate_bps = allocated_bitrate;
117 : }
118 0 : }
119 :
120 0 : void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
121 : uint32_t min_bitrate_bps,
122 : uint32_t max_bitrate_bps,
123 : uint32_t pad_up_bitrate_bps,
124 : bool enforce_min_bitrate) {
125 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
126 0 : auto it = FindObserverConfig(observer);
127 :
128 : // Update settings if the observer already exists, create a new one otherwise.
129 0 : if (it != bitrate_observer_configs_.end()) {
130 0 : it->min_bitrate_bps = min_bitrate_bps;
131 0 : it->max_bitrate_bps = max_bitrate_bps;
132 0 : it->pad_up_bitrate_bps = pad_up_bitrate_bps;
133 0 : it->enforce_min_bitrate = enforce_min_bitrate;
134 : } else {
135 0 : bitrate_observer_configs_.push_back(
136 0 : ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
137 0 : pad_up_bitrate_bps, enforce_min_bitrate));
138 : }
139 :
140 0 : ObserverAllocation allocation;
141 0 : if (last_bitrate_bps_ > 0) {
142 : // Calculate a new allocation and update all observers.
143 0 : allocation = AllocateBitrates(last_bitrate_bps_);
144 0 : for (auto& config : bitrate_observer_configs_) {
145 0 : uint32_t allocated_bitrate = allocation[config.observer];
146 0 : uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
147 0 : allocated_bitrate, last_fraction_loss_, last_rtt_,
148 0 : last_probing_interval_ms_);
149 0 : config.allocated_bitrate_bps = allocated_bitrate;
150 0 : if (allocated_bitrate > 0)
151 0 : config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
152 : }
153 : } else {
154 : // Currently, an encoder is not allowed to produce frames.
155 : // But we still have to return the initial config bitrate + let the
156 : // observer know that it can not produce frames.
157 0 : allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
158 0 : observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_,
159 0 : last_probing_interval_ms_);
160 : }
161 0 : UpdateAllocationLimits();
162 0 : }
163 :
164 0 : void BitrateAllocator::UpdateAllocationLimits() {
165 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
166 0 : uint32_t total_requested_padding_bitrate = 0;
167 0 : uint32_t total_requested_min_bitrate = 0;
168 :
169 0 : for (const auto& config : bitrate_observer_configs_) {
170 0 : if (config.enforce_min_bitrate) {
171 0 : total_requested_min_bitrate += config.min_bitrate_bps;
172 : }
173 0 : total_requested_padding_bitrate += config.pad_up_bitrate_bps;
174 : }
175 :
176 0 : LOG(LS_INFO) << "UpdateAllocationLimits : total_requested_min_bitrate: "
177 0 : << total_requested_min_bitrate
178 0 : << "bps, total_requested_padding_bitrate: "
179 0 : << total_requested_padding_bitrate << "bps";
180 0 : limit_observer_->OnAllocationLimitsChanged(total_requested_min_bitrate,
181 0 : total_requested_padding_bitrate);
182 0 : }
183 :
184 0 : void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
185 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
186 0 : auto it = FindObserverConfig(observer);
187 0 : if (it != bitrate_observer_configs_.end()) {
188 0 : bitrate_observer_configs_.erase(it);
189 : }
190 :
191 0 : UpdateAllocationLimits();
192 0 : }
193 :
194 0 : int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
195 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
196 0 : const auto& it = FindObserverConfig(observer);
197 0 : if (it == bitrate_observer_configs_.end()) {
198 : // This observer hasn't been added yet, just give it its fair share.
199 0 : return last_non_zero_bitrate_bps_ /
200 0 : static_cast<int>((bitrate_observer_configs_.size() + 1));
201 0 : } else if (it->allocated_bitrate_bps == -1) {
202 : // This observer hasn't received an allocation yet, so do the same.
203 0 : return last_non_zero_bitrate_bps_ /
204 0 : static_cast<int>(bitrate_observer_configs_.size());
205 : } else {
206 : // This observer already has an allocation.
207 0 : return it->allocated_bitrate_bps;
208 : }
209 : }
210 :
211 : BitrateAllocator::ObserverConfigs::iterator
212 0 : BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) {
213 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
214 0 : for (auto it = bitrate_observer_configs_.begin();
215 0 : it != bitrate_observer_configs_.end(); ++it) {
216 0 : if (it->observer == observer)
217 0 : return it;
218 : }
219 0 : return bitrate_observer_configs_.end();
220 : }
221 :
222 0 : BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
223 : uint32_t bitrate) {
224 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
225 0 : if (bitrate_observer_configs_.empty())
226 0 : return ObserverAllocation();
227 :
228 0 : if (bitrate == 0)
229 0 : return ZeroRateAllocation();
230 :
231 0 : uint32_t sum_min_bitrates = 0;
232 0 : uint32_t sum_max_bitrates = 0;
233 0 : for (const auto& observer_config : bitrate_observer_configs_) {
234 0 : sum_min_bitrates += observer_config.min_bitrate_bps;
235 0 : sum_max_bitrates += observer_config.max_bitrate_bps;
236 : }
237 :
238 : // Not enough for all observers to get an allocation, allocate according to:
239 : // enforced min bitrate -> allocated bitrate previous round -> restart paused
240 : // streams.
241 0 : if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
242 0 : return LowRateAllocation(bitrate);
243 :
244 : // All observers will get their min bitrate plus an even share of the rest.
245 0 : if (bitrate <= sum_max_bitrates)
246 0 : return NormalRateAllocation(bitrate, sum_min_bitrates);
247 :
248 : // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
249 0 : return MaxRateAllocation(bitrate, sum_max_bitrates);
250 : }
251 :
252 0 : BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
253 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
254 0 : ObserverAllocation allocation;
255 0 : for (const auto& observer_config : bitrate_observer_configs_)
256 0 : allocation[observer_config.observer] = 0;
257 0 : return allocation;
258 : }
259 :
260 0 : BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
261 : uint32_t bitrate) {
262 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
263 0 : ObserverAllocation allocation;
264 : // Start by allocating bitrate to observers enforcing a min bitrate, hence
265 : // remaining_bitrate might turn negative.
266 0 : int64_t remaining_bitrate = bitrate;
267 0 : for (const auto& observer_config : bitrate_observer_configs_) {
268 0 : int32_t allocated_bitrate = 0;
269 0 : if (observer_config.enforce_min_bitrate)
270 0 : allocated_bitrate = observer_config.min_bitrate_bps;
271 :
272 0 : allocation[observer_config.observer] = allocated_bitrate;
273 0 : remaining_bitrate -= allocated_bitrate;
274 : }
275 :
276 : // Allocate bitrate to all previously active streams.
277 0 : if (remaining_bitrate > 0) {
278 0 : for (const auto& observer_config : bitrate_observer_configs_) {
279 0 : if (observer_config.enforce_min_bitrate ||
280 0 : LastAllocatedBitrate(observer_config) == 0)
281 0 : continue;
282 :
283 0 : uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
284 0 : if (remaining_bitrate >= required_bitrate) {
285 0 : allocation[observer_config.observer] = required_bitrate;
286 0 : remaining_bitrate -= required_bitrate;
287 : }
288 : }
289 : }
290 :
291 : // Allocate bitrate to previously paused streams.
292 0 : if (remaining_bitrate > 0) {
293 0 : for (const auto& observer_config : bitrate_observer_configs_) {
294 0 : if (LastAllocatedBitrate(observer_config) != 0)
295 0 : continue;
296 :
297 : // Add a hysteresis to avoid toggling.
298 0 : uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
299 0 : if (remaining_bitrate >= required_bitrate) {
300 0 : allocation[observer_config.observer] = required_bitrate;
301 0 : remaining_bitrate -= required_bitrate;
302 : }
303 : }
304 : }
305 :
306 : // Split a possible remainder evenly on all streams with an allocation.
307 0 : if (remaining_bitrate > 0)
308 0 : DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
309 :
310 0 : RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
311 0 : return allocation;
312 : }
313 :
314 0 : BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
315 : uint32_t bitrate,
316 : uint32_t sum_min_bitrates) {
317 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
318 0 : ObserverAllocation allocation;
319 0 : for (const auto& observer_config : bitrate_observer_configs_)
320 0 : allocation[observer_config.observer] = observer_config.min_bitrate_bps;
321 :
322 0 : bitrate -= sum_min_bitrates;
323 0 : if (bitrate > 0)
324 0 : DistributeBitrateEvenly(bitrate, true, 1, &allocation);
325 :
326 0 : return allocation;
327 : }
328 :
329 0 : BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
330 : uint32_t bitrate,
331 : uint32_t sum_max_bitrates) {
332 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
333 0 : ObserverAllocation allocation;
334 :
335 0 : for (const auto& observer_config : bitrate_observer_configs_) {
336 0 : allocation[observer_config.observer] = observer_config.max_bitrate_bps;
337 0 : bitrate -= observer_config.max_bitrate_bps;
338 : }
339 : DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
340 0 : &allocation);
341 0 : return allocation;
342 : }
343 :
344 0 : uint32_t BitrateAllocator::LastAllocatedBitrate(
345 : const ObserverConfig& observer_config) {
346 : // Return the configured minimum bitrate for newly added observers, to avoid
347 : // requiring an extra high bitrate for the observer to get an allocated
348 : // bitrate.
349 0 : return observer_config.allocated_bitrate_bps == -1
350 : ? observer_config.min_bitrate_bps
351 0 : : observer_config.allocated_bitrate_bps;
352 : }
353 :
354 0 : uint32_t BitrateAllocator::MinBitrateWithHysteresis(
355 : const ObserverConfig& observer_config) {
356 0 : uint32_t min_bitrate = observer_config.min_bitrate_bps;
357 0 : if (LastAllocatedBitrate(observer_config) == 0) {
358 0 : min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
359 0 : kMinToggleBitrateBps);
360 : }
361 : // Account for protection bitrate used by this observer in the previous
362 : // allocation.
363 : // Note: the ratio will only be updated when the stream is active, meaning a
364 : // paused stream won't get any ratio updates. This might lead to waiting a bit
365 : // longer than necessary if the network condition improves, but this is to
366 : // avoid too much toggling.
367 0 : if (observer_config.media_ratio > 0.0 && observer_config.media_ratio < 1.0)
368 0 : min_bitrate += min_bitrate * (1.0 - observer_config.media_ratio);
369 :
370 0 : return min_bitrate;
371 : }
372 :
373 0 : void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
374 : bool include_zero_allocations,
375 : int max_multiplier,
376 : ObserverAllocation* allocation) {
377 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
378 0 : RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
379 :
380 0 : ObserverSortingMap list_max_bitrates;
381 0 : for (const auto& observer_config : bitrate_observer_configs_) {
382 0 : if (include_zero_allocations ||
383 0 : allocation->at(observer_config.observer) != 0) {
384 0 : list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
385 0 : observer_config.max_bitrate_bps, &observer_config));
386 : }
387 : }
388 0 : auto it = list_max_bitrates.begin();
389 0 : while (it != list_max_bitrates.end()) {
390 0 : RTC_DCHECK_GT(bitrate, 0);
391 : uint32_t extra_allocation =
392 0 : bitrate / static_cast<uint32_t>(list_max_bitrates.size());
393 : uint32_t total_allocation =
394 0 : extra_allocation + allocation->at(it->second->observer);
395 0 : bitrate -= extra_allocation;
396 0 : if (total_allocation > max_multiplier * it->first) {
397 : // There is more than we can fit for this observer, carry over to the
398 : // remaining observers.
399 0 : bitrate += total_allocation - max_multiplier * it->first;
400 0 : total_allocation = max_multiplier * it->first;
401 : }
402 : // Finally, update the allocation for this observer.
403 0 : allocation->at(it->second->observer) = total_allocation;
404 0 : it = list_max_bitrates.erase(it);
405 : }
406 0 : }
407 :
408 0 : bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
409 : uint32_t sum_min_bitrates) {
410 0 : RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
411 0 : if (bitrate < sum_min_bitrates)
412 0 : return false;
413 :
414 : uint32_t extra_bitrate_per_observer =
415 0 : (bitrate - sum_min_bitrates) /
416 0 : static_cast<uint32_t>(bitrate_observer_configs_.size());
417 0 : for (const auto& observer_config : bitrate_observer_configs_) {
418 0 : if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
419 0 : MinBitrateWithHysteresis(observer_config))
420 0 : return false;
421 : }
422 0 : return true;
423 : }
424 : } // namespace webrtc
|