blob: e23fa89db3892ad92eefd13e2908df3b5de3760c [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020012#include "call/bitrate_allocator.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000013
14#include <algorithm>
Seth Hampsonfe73d6a2017-11-14 10:49:06 -080015#include <cmath>
Alex Narest78609d52017-10-20 10:37:47 +020016#include <memory>
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000017#include <utility>
18
Sebastian Jansson6736df12018-11-21 19:18:39 +010019#include "api/units/data_rate.h"
20#include "api/units/time_delta.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/bitrate_controller/include/bitrate_controller.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/logging.h"
24#include "system_wrappers/include/clock.h"
Ying Wanga646d302018-03-02 17:04:11 +010025#include "system_wrappers/include/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "system_wrappers/include/metrics.h"
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000027
28namespace webrtc {
29
Stefan Holmere5904162015-03-26 11:11:06 +010030// Allow packets to be transmitted in up to 2 times max video bitrate if the
31// bandwidth estimate allows it.
Ying Wanga646d302018-03-02 17:04:11 +010032const uint8_t kTransmissionMaxBitrateMultiplier = 2;
Stefan Holmere5904162015-03-26 11:11:06 +010033const int kDefaultBitrateBps = 300000;
34
mflodman101f2502016-06-09 17:21:19 +020035// Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
36const double kToggleFactor = 0.1;
37const uint32_t kMinToggleBitrateBps = 20000;
38
mflodman48a4beb2016-07-01 13:03:59 +020039const int64_t kBweLogIntervalMs = 5000;
40
41namespace {
42
43double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) {
kwibergaf476c72016-11-28 15:21:39 -080044 RTC_DCHECK_GT(allocated_bitrate, 0);
mflodman48a4beb2016-07-01 13:03:59 +020045 if (protection_bitrate == 0)
46 return 1.0;
47
48 uint32_t media_bitrate = allocated_bitrate - protection_bitrate;
49 return media_bitrate / static_cast<double>(allocated_bitrate);
50}
51} // namespace
52
perkj71ee44c2016-06-15 00:47:53 -070053BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
54 : limit_observer_(limit_observer),
Sebastian Jansson89c94b92018-11-20 17:16:36 +010055 last_target_bps_(0),
56 last_link_capacity_bps_(0),
perkjfea93092016-05-14 00:58:48 -070057 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
Stefan Holmere5904162015-03-26 11:11:06 +010058 last_fraction_loss_(0),
mflodman48a4beb2016-07-01 13:03:59 +020059 last_rtt_(0),
Sebastian Jansson13e59032018-11-21 19:13:07 +010060 last_bwe_period_ms_(1000),
mflodman48a4beb2016-07-01 13:03:59 +020061 num_pause_events_(0),
62 clock_(Clock::GetRealTimeClock()),
philipel5ef2bc12017-02-21 07:28:31 -080063 last_bwe_log_time_(0),
64 total_requested_padding_bitrate_(0),
Alex Narest78609d52017-10-20 10:37:47 +020065 total_requested_min_bitrate_(0),
Sebastian Jansson448f4d52018-04-04 14:52:07 +020066 total_requested_max_bitrate_(0),
Sebastian Jansson35fa2802018-10-01 09:16:12 +020067 allocated_without_feedback_(0),
Sebastian Jansson29b204e2018-03-21 12:45:27 +010068 has_packet_feedback_(false),
Ying Wanga646d302018-03-02 17:04:11 +010069 bitrate_allocation_strategy_(nullptr),
70 transmission_max_bitrate_multiplier_(
71 GetTransmissionMaxBitrateMultiplier()) {
perkj26091b12016-09-01 01:17:40 -070072 sequenced_checker_.Detach();
73}
mflodman48a4beb2016-07-01 13:03:59 +020074
75BitrateAllocator::~BitrateAllocator() {
asapersson1d02d3e2016-09-09 22:40:25 -070076 RTC_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
77 num_pause_events_);
mflodman48a4beb2016-07-01 13:03:59 +020078}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000079
Sebastian Jansson2701bc92018-12-11 15:02:47 +010080void BitrateAllocator::UpdateStartRate(uint32_t start_rate_bps) {
81 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
82 last_non_zero_bitrate_bps_ = start_rate_bps;
83}
84
Niels Möller74e5f802018-04-25 14:03:46 +020085// static
Ying Wanga646d302018-03-02 17:04:11 +010086uint8_t BitrateAllocator::GetTransmissionMaxBitrateMultiplier() {
87 uint64_t multiplier = strtoul(webrtc::field_trial::FindFullName(
88 "WebRTC-TransmissionMaxBitrateMultiplier")
89 .c_str(),
90 nullptr, 10);
91 if (multiplier > 0 && multiplier <= kTransmissionMaxBitrateMultiplier) {
Ying Wang012b7e72018-03-05 15:44:23 +010092 RTC_LOG(LS_INFO) << "TransmissionMaxBitrateMultiplier is set to "
93 << multiplier;
Ying Wanga646d302018-03-02 17:04:11 +010094 return static_cast<uint8_t>(multiplier);
95 }
96 return kTransmissionMaxBitrateMultiplier;
97}
98
perkj71ee44c2016-06-15 00:47:53 -070099void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
Sebastian Jansson89c94b92018-11-20 17:16:36 +0100100 uint32_t link_capacity_bps,
perkj71ee44c2016-06-15 00:47:53 -0700101 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800102 int64_t rtt,
minyue93e45222017-05-18 14:32:41 -0700103 int64_t bwe_period_ms) {
perkj26091b12016-09-01 01:17:40 -0700104 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
Sebastian Jansson89c94b92018-11-20 17:16:36 +0100105 last_target_bps_ = target_bitrate_bps;
106 last_link_capacity_bps_ = link_capacity_bps;
perkjfea93092016-05-14 00:58:48 -0700107 last_non_zero_bitrate_bps_ =
mflodman101f2502016-06-09 17:21:19 +0200108 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
Stefan Holmere5904162015-03-26 11:11:06 +0100109 last_fraction_loss_ = fraction_loss;
110 last_rtt_ = rtt;
minyue93e45222017-05-18 14:32:41 -0700111 last_bwe_period_ms_ = bwe_period_ms;
mflodman2ebe5b12016-05-13 01:43:51 -0700112
mflodman48a4beb2016-07-01 13:03:59 +0200113 // Periodically log the incoming BWE.
114 int64_t now = clock_->TimeInMilliseconds();
115 if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100116 RTC_LOG(LS_INFO) << "Current BWE " << target_bitrate_bps;
mflodman48a4beb2016-07-01 13:03:59 +0200117 last_bwe_log_time_ = now;
sprang2f48d942015-11-05 04:25:49 -0800118 }
mflodman48a4beb2016-07-01 13:03:59 +0200119
120 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
Sebastian Jansson89c94b92018-11-20 17:16:36 +0100121 ObserverAllocation bandwidth_allocation = AllocateBitrates(link_capacity_bps);
mflodman48a4beb2016-07-01 13:03:59 +0200122
123 for (auto& config : bitrate_observer_configs_) {
124 uint32_t allocated_bitrate = allocation[config.observer];
Sebastian Jansson89c94b92018-11-20 17:16:36 +0100125 uint32_t allocated_bandwidth = bandwidth_allocation[config.observer];
Sebastian Jansson13e59032018-11-21 19:13:07 +0100126 BitrateAllocationUpdate update;
127 update.target_bitrate = DataRate::bps(allocated_bitrate);
128 update.link_capacity = DataRate::bps(allocated_bandwidth);
129 update.packet_loss_ratio = last_fraction_loss_ / 256.0;
130 update.round_trip_time = TimeDelta::ms(last_rtt_);
131 update.bwe_period = TimeDelta::ms(last_bwe_period_ms_);
132 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(update);
mflodman48a4beb2016-07-01 13:03:59 +0200133
134 if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
135 if (target_bitrate_bps > 0)
136 ++num_pause_events_;
137 // The protection bitrate is an estimate based on the ratio between media
138 // and protection used before this observer was muted.
139 uint32_t predicted_protection_bps =
140 (1.0 - config.media_ratio) * config.min_bitrate_bps;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100141 RTC_LOG(LS_INFO) << "Pausing observer " << config.observer
142 << " with configured min bitrate "
143 << config.min_bitrate_bps << " and current estimate of "
144 << target_bitrate_bps << " and protection bitrate "
145 << predicted_protection_bps;
mflodman48a4beb2016-07-01 13:03:59 +0200146 } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
147 if (target_bitrate_bps > 0)
148 ++num_pause_events_;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100149 RTC_LOG(LS_INFO) << "Resuming observer " << config.observer
150 << ", configured min bitrate " << config.min_bitrate_bps
151 << ", current allocation " << allocated_bitrate
152 << " and protection bitrate " << protection_bitrate;
mflodman48a4beb2016-07-01 13:03:59 +0200153 }
154
155 // Only update the media ratio if the observer got an allocation.
156 if (allocated_bitrate > 0)
157 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
158 config.allocated_bitrate_bps = allocated_bitrate;
159 }
philipel5ef2bc12017-02-21 07:28:31 -0800160 UpdateAllocationLimits();
Stefan Holmere5904162015-03-26 11:11:06 +0100161}
162
perkj57c21f92016-06-17 07:27:16 -0700163void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200164 MediaStreamAllocationConfig config) {
perkj26091b12016-09-01 01:17:40 -0700165 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200166 RTC_DCHECK_GT(config.bitrate_priority, 0);
167 RTC_DCHECK(std::isnormal(config.bitrate_priority));
mflodman2ebe5b12016-05-13 01:43:51 -0700168 auto it = FindObserverConfig(observer);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000169
mflodman101f2502016-06-09 17:21:19 +0200170 // Update settings if the observer already exists, create a new one otherwise.
mflodman2ebe5b12016-05-13 01:43:51 -0700171 if (it != bitrate_observer_configs_.end()) {
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200172 it->min_bitrate_bps = config.min_bitrate_bps;
173 it->max_bitrate_bps = config.max_bitrate_bps;
174 it->pad_up_bitrate_bps = config.pad_up_bitrate_bps;
175 it->enforce_min_bitrate = config.enforce_min_bitrate;
176 it->bitrate_priority = config.bitrate_priority;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000177 } else {
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800178 bitrate_observer_configs_.push_back(ObserverConfig(
Sebastian Jansson24ad7202018-04-19 08:25:12 +0200179 observer, config.min_bitrate_bps, config.max_bitrate_bps,
180 config.pad_up_bitrate_bps, config.enforce_min_bitrate, config.track_id,
181 config.bitrate_priority, config.has_packet_feedback));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000182 }
Stefan Holmere5904162015-03-26 11:11:06 +0100183
Sebastian Jansson89c94b92018-11-20 17:16:36 +0100184 if (last_target_bps_ > 0) {
mflodman101f2502016-06-09 17:21:19 +0200185 // Calculate a new allocation and update all observers.
Sebastian Jansson89c94b92018-11-20 17:16:36 +0100186
187 ObserverAllocation allocation = AllocateBitrates(last_target_bps_);
188 ObserverAllocation bandwidth_allocation =
189 AllocateBitrates(last_link_capacity_bps_);
mflodman48a4beb2016-07-01 13:03:59 +0200190 for (auto& config : bitrate_observer_configs_) {
191 uint32_t allocated_bitrate = allocation[config.observer];
Sebastian Jansson89c94b92018-11-20 17:16:36 +0100192 uint32_t bandwidth = bandwidth_allocation[config.observer];
Sebastian Jansson13e59032018-11-21 19:13:07 +0100193 BitrateAllocationUpdate update;
194 update.target_bitrate = DataRate::bps(allocated_bitrate);
195 update.link_capacity = DataRate::bps(bandwidth);
196 update.packet_loss_ratio = last_fraction_loss_ / 256.0;
197 update.round_trip_time = TimeDelta::ms(last_rtt_);
198 update.bwe_period = TimeDelta::ms(last_bwe_period_ms_);
199 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(update);
mflodman48a4beb2016-07-01 13:03:59 +0200200 config.allocated_bitrate_bps = allocated_bitrate;
201 if (allocated_bitrate > 0)
202 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
203 }
perkjfea93092016-05-14 00:58:48 -0700204 } else {
205 // Currently, an encoder is not allowed to produce frames.
206 // But we still have to return the initial config bitrate + let the
207 // observer know that it can not produce frames.
Sebastian Jansson13e59032018-11-21 19:13:07 +0100208
209 BitrateAllocationUpdate update;
210 update.target_bitrate = DataRate::Zero();
211 update.link_capacity = DataRate::Zero();
212 update.packet_loss_ratio = last_fraction_loss_ / 256.0;
213 update.round_trip_time = TimeDelta::ms(last_rtt_);
214 update.bwe_period = TimeDelta::ms(last_bwe_period_ms_);
215 observer->OnBitrateUpdated(update);
Stefan Holmere5904162015-03-26 11:11:06 +0100216 }
perkj71ee44c2016-06-15 00:47:53 -0700217 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000218}
219
perkj71ee44c2016-06-15 00:47:53 -0700220void BitrateAllocator::UpdateAllocationLimits() {
221 uint32_t total_requested_padding_bitrate = 0;
222 uint32_t total_requested_min_bitrate = 0;
Sebastian Jansson448f4d52018-04-04 14:52:07 +0200223 uint32_t total_requested_max_bitrate = 0;
Sebastian Jansson29b204e2018-03-21 12:45:27 +0100224 bool has_packet_feedback = false;
Sebastian Jansson35fa2802018-10-01 09:16:12 +0200225 uint32_t allocated_without_feedback = 0;
perkj26091b12016-09-01 01:17:40 -0700226 for (const auto& config : bitrate_observer_configs_) {
philipel5ef2bc12017-02-21 07:28:31 -0800227 uint32_t stream_padding = config.pad_up_bitrate_bps;
perkj26091b12016-09-01 01:17:40 -0700228 if (config.enforce_min_bitrate) {
229 total_requested_min_bitrate += config.min_bitrate_bps;
philipel5ef2bc12017-02-21 07:28:31 -0800230 } else if (config.allocated_bitrate_bps == 0) {
231 stream_padding =
srte1eb051c2017-11-29 11:23:59 +0100232 std::max(config.MinBitrateWithHysteresis(), stream_padding);
perkj71ee44c2016-06-15 00:47:53 -0700233 }
philipel5ef2bc12017-02-21 07:28:31 -0800234 total_requested_padding_bitrate += stream_padding;
Erik Språngd1d7b232018-12-06 17:31:25 +0100235 uint32_t max_bitrate_bps = config.max_bitrate_bps;
Erik Språng00672b12018-12-11 15:29:29 +0100236 if (config.media_ratio < 1.0) {
237 // Account for protection overhead (eg FEC). Assumption is that overhead
238 // is never more than 100%. Don't adjust based exact value as that might
239 // trigger too frequent calls to OnAllocationLimitsChanged().
240 max_bitrate_bps *= 2;
Erik Språngd1d7b232018-12-06 17:31:25 +0100241 }
242 total_requested_max_bitrate += max_bitrate_bps;
Sebastian Jansson29b204e2018-03-21 12:45:27 +0100243 if (config.allocated_bitrate_bps > 0 && config.has_packet_feedback)
244 has_packet_feedback = true;
Sebastian Jansson35fa2802018-10-01 09:16:12 +0200245 // TODO(srte): Remove field trial check.
246 if (!config.has_packet_feedback &&
247 field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC"))
248 allocated_without_feedback += config.allocated_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000249 }
perkj71ee44c2016-06-15 00:47:53 -0700250
philipel5ef2bc12017-02-21 07:28:31 -0800251 if (total_requested_padding_bitrate == total_requested_padding_bitrate_ &&
Sebastian Jansson29b204e2018-03-21 12:45:27 +0100252 total_requested_min_bitrate == total_requested_min_bitrate_ &&
Sebastian Jansson448f4d52018-04-04 14:52:07 +0200253 total_requested_max_bitrate == total_requested_max_bitrate_ &&
Sebastian Jansson35fa2802018-10-01 09:16:12 +0200254 allocated_without_feedback == allocated_without_feedback_ &&
Sebastian Jansson29b204e2018-03-21 12:45:27 +0100255 has_packet_feedback == has_packet_feedback_) {
philipel5ef2bc12017-02-21 07:28:31 -0800256 return;
257 }
258
259 total_requested_min_bitrate_ = total_requested_min_bitrate;
260 total_requested_padding_bitrate_ = total_requested_padding_bitrate;
Sebastian Jansson448f4d52018-04-04 14:52:07 +0200261 total_requested_max_bitrate_ = total_requested_max_bitrate;
Sebastian Jansson35fa2802018-10-01 09:16:12 +0200262 allocated_without_feedback_ = allocated_without_feedback;
Sebastian Jansson29b204e2018-03-21 12:45:27 +0100263 has_packet_feedback_ = has_packet_feedback;
philipel5ef2bc12017-02-21 07:28:31 -0800264
Mirko Bonadei675513b2017-11-09 11:09:25 +0100265 RTC_LOG(LS_INFO) << "UpdateAllocationLimits : total_requested_min_bitrate: "
266 << total_requested_min_bitrate
267 << "bps, total_requested_padding_bitrate: "
Sebastian Jansson448f4d52018-04-04 14:52:07 +0200268 << total_requested_padding_bitrate
269 << "bps, total_requested_max_bitrate: "
270 << total_requested_max_bitrate << "bps";
Sebastian Jansson29b204e2018-03-21 12:45:27 +0100271 limit_observer_->OnAllocationLimitsChanged(
272 total_requested_min_bitrate, total_requested_padding_bitrate,
Sebastian Jansson35fa2802018-10-01 09:16:12 +0200273 total_requested_max_bitrate, allocated_without_feedback,
274 has_packet_feedback);
perkj71ee44c2016-06-15 00:47:53 -0700275}
276
277void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
perkj26091b12016-09-01 01:17:40 -0700278 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
Alex Narest78609d52017-10-20 10:37:47 +0200279
perkj26091b12016-09-01 01:17:40 -0700280 auto it = FindObserverConfig(observer);
281 if (it != bitrate_observer_configs_.end()) {
282 bitrate_observer_configs_.erase(it);
perkj71ee44c2016-06-15 00:47:53 -0700283 }
perkj26091b12016-09-01 01:17:40 -0700284
perkj71ee44c2016-06-15 00:47:53 -0700285 UpdateAllocationLimits();
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000286}
287
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200288int BitrateAllocator::GetStartBitrate(
289 BitrateAllocatorObserver* observer) const {
perkj26091b12016-09-01 01:17:40 -0700290 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
mflodman48a4beb2016-07-01 13:03:59 +0200291 const auto& it = FindObserverConfig(observer);
292 if (it == bitrate_observer_configs_.end()) {
293 // This observer hasn't been added yet, just give it its fair share.
294 return last_non_zero_bitrate_bps_ /
perkj26091b12016-09-01 01:17:40 -0700295 static_cast<int>((bitrate_observer_configs_.size() + 1));
mflodman48a4beb2016-07-01 13:03:59 +0200296 } else if (it->allocated_bitrate_bps == -1) {
297 // This observer hasn't received an allocation yet, so do the same.
298 return last_non_zero_bitrate_bps_ /
perkj26091b12016-09-01 01:17:40 -0700299 static_cast<int>(bitrate_observer_configs_.size());
mflodman48a4beb2016-07-01 13:03:59 +0200300 } else {
301 // This observer already has an allocation.
302 return it->allocated_bitrate_bps;
303 }
perkj57c21f92016-06-17 07:27:16 -0700304}
305
Alex Narest78609d52017-10-20 10:37:47 +0200306void BitrateAllocator::SetBitrateAllocationStrategy(
307 std::unique_ptr<rtc::BitrateAllocationStrategy>
308 bitrate_allocation_strategy) {
309 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
310 bitrate_allocation_strategy_ = std::move(bitrate_allocation_strategy);
311}
312
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200313BitrateAllocator::ObserverConfigs::const_iterator
314BitrateAllocator::FindObserverConfig(
315 const BitrateAllocatorObserver* observer) const {
316 for (auto it = bitrate_observer_configs_.begin();
317 it != bitrate_observer_configs_.end(); ++it) {
318 if (it->observer == observer)
319 return it;
320 }
321 return bitrate_observer_configs_.end();
322}
323
mflodman48a4beb2016-07-01 13:03:59 +0200324BitrateAllocator::ObserverConfigs::iterator
perkj26091b12016-09-01 01:17:40 -0700325BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) {
mflodman2ebe5b12016-05-13 01:43:51 -0700326 for (auto it = bitrate_observer_configs_.begin();
327 it != bitrate_observer_configs_.end(); ++it) {
328 if (it->observer == observer)
329 return it;
330 }
331 return bitrate_observer_configs_.end();
332}
333
perkjfea93092016-05-14 00:58:48 -0700334BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200335 uint32_t bitrate) const {
mflodman2ebe5b12016-05-13 01:43:51 -0700336 if (bitrate_observer_configs_.empty())
337 return ObserverAllocation();
338
Alex Narest78609d52017-10-20 10:37:47 +0200339 if (bitrate_allocation_strategy_ != nullptr) {
Sebastian Janssone2754c92018-10-24 16:02:26 +0200340 // Note: This intentionally causes slicing, we only copy the fields in
341 // ObserverConfig that are inherited from TrackConfig.
342 std::vector<rtc::BitrateAllocationStrategy::TrackConfig> track_configs(
343 bitrate_observer_configs_.begin(), bitrate_observer_configs_.end());
344
Alex Narest78609d52017-10-20 10:37:47 +0200345 std::vector<uint32_t> track_allocations =
Sebastian Janssone2754c92018-10-24 16:02:26 +0200346 bitrate_allocation_strategy_->AllocateBitrates(
347 bitrate, std::move(track_configs));
Alex Narest78609d52017-10-20 10:37:47 +0200348 // The strategy should return allocation for all tracks.
349 RTC_CHECK(track_allocations.size() == bitrate_observer_configs_.size());
350 ObserverAllocation allocation;
351 auto track_allocations_it = track_allocations.begin();
352 for (const auto& observer_config : bitrate_observer_configs_) {
353 allocation[observer_config.observer] = *track_allocations_it++;
354 }
355 return allocation;
356 }
357
perkjfea93092016-05-14 00:58:48 -0700358 if (bitrate == 0)
mflodman2ebe5b12016-05-13 01:43:51 -0700359 return ZeroRateAllocation();
360
361 uint32_t sum_min_bitrates = 0;
mflodman101f2502016-06-09 17:21:19 +0200362 uint32_t sum_max_bitrates = 0;
363 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman2ebe5b12016-05-13 01:43:51 -0700364 sum_min_bitrates += observer_config.min_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200365 sum_max_bitrates += observer_config.max_bitrate_bps;
366 }
367
368 // Not enough for all observers to get an allocation, allocate according to:
369 // enforced min bitrate -> allocated bitrate previous round -> restart paused
370 // streams.
371 if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
perkjfea93092016-05-14 00:58:48 -0700372 return LowRateAllocation(bitrate);
mflodman2ebe5b12016-05-13 01:43:51 -0700373
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800374 // All observers will get their min bitrate plus a share of the rest. This
375 // share is allocated to each observer based on its bitrate_priority.
mflodman101f2502016-06-09 17:21:19 +0200376 if (bitrate <= sum_max_bitrates)
377 return NormalRateAllocation(bitrate, sum_min_bitrates);
mflodman2ebe5b12016-05-13 01:43:51 -0700378
Ying Wanga646d302018-03-02 17:04:11 +0100379 // All observers will get up to transmission_max_bitrate_multiplier_ x max.
mflodman101f2502016-06-09 17:21:19 +0200380 return MaxRateAllocation(bitrate, sum_max_bitrates);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000381}
382
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200383BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation()
384 const {
mflodman2ebe5b12016-05-13 01:43:51 -0700385 ObserverAllocation allocation;
mflodman2ebe5b12016-05-13 01:43:51 -0700386 for (const auto& observer_config : bitrate_observer_configs_)
387 allocation[observer_config.observer] = 0;
perkjec81bcd2016-05-11 06:01:13 -0700388 return allocation;
389}
390
mflodman2ebe5b12016-05-13 01:43:51 -0700391BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200392 uint32_t bitrate) const {
mflodman2ebe5b12016-05-13 01:43:51 -0700393 ObserverAllocation allocation;
mflodman101f2502016-06-09 17:21:19 +0200394 // Start by allocating bitrate to observers enforcing a min bitrate, hence
395 // remaining_bitrate might turn negative.
396 int64_t remaining_bitrate = bitrate;
397 for (const auto& observer_config : bitrate_observer_configs_) {
398 int32_t allocated_bitrate = 0;
399 if (observer_config.enforce_min_bitrate)
400 allocated_bitrate = observer_config.min_bitrate_bps;
401
402 allocation[observer_config.observer] = allocated_bitrate;
403 remaining_bitrate -= allocated_bitrate;
404 }
405
406 // Allocate bitrate to all previously active streams.
407 if (remaining_bitrate > 0) {
mflodman2ebe5b12016-05-13 01:43:51 -0700408 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman101f2502016-06-09 17:21:19 +0200409 if (observer_config.enforce_min_bitrate ||
srte1eb051c2017-11-29 11:23:59 +0100410 observer_config.LastAllocatedBitrate() == 0)
mflodman101f2502016-06-09 17:21:19 +0200411 continue;
412
srte1eb051c2017-11-29 11:23:59 +0100413 uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
mflodman48a4beb2016-07-01 13:03:59 +0200414 if (remaining_bitrate >= required_bitrate) {
415 allocation[observer_config.observer] = required_bitrate;
416 remaining_bitrate -= required_bitrate;
mflodman101f2502016-06-09 17:21:19 +0200417 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000418 }
419 }
mflodman101f2502016-06-09 17:21:19 +0200420
421 // Allocate bitrate to previously paused streams.
422 if (remaining_bitrate > 0) {
423 for (const auto& observer_config : bitrate_observer_configs_) {
srte1eb051c2017-11-29 11:23:59 +0100424 if (observer_config.LastAllocatedBitrate() != 0)
mflodman101f2502016-06-09 17:21:19 +0200425 continue;
426
427 // Add a hysteresis to avoid toggling.
srte1eb051c2017-11-29 11:23:59 +0100428 uint32_t required_bitrate = observer_config.MinBitrateWithHysteresis();
mflodman101f2502016-06-09 17:21:19 +0200429 if (remaining_bitrate >= required_bitrate) {
430 allocation[observer_config.observer] = required_bitrate;
431 remaining_bitrate -= required_bitrate;
432 }
433 }
434 }
435
436 // Split a possible remainder evenly on all streams with an allocation.
437 if (remaining_bitrate > 0)
438 DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
439
440 RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
Stefan Holmere5904162015-03-26 11:11:06 +0100441 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000442}
mflodman101f2502016-06-09 17:21:19 +0200443
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800444// Allocates the bitrate based on the bitrate priority of each observer. This
445// bitrate priority defines the priority for bitrate to be allocated to that
446// observer in relation to other observers. For example with two observers, if
447// observer 1 had a bitrate_priority = 1.0, and observer 2 has a
448// bitrate_priority = 2.0, the expected behavior is that observer 2 will be
449// allocated twice the bitrate as observer 1 above the each observer's
450// min_bitrate_bps values, until one of the observers hits its max_bitrate_bps.
mflodman101f2502016-06-09 17:21:19 +0200451BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
452 uint32_t bitrate,
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200453 uint32_t sum_min_bitrates) const {
mflodman101f2502016-06-09 17:21:19 +0200454 ObserverAllocation allocation;
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800455 ObserverAllocation observers_capacities;
456 for (const auto& observer_config : bitrate_observer_configs_) {
mflodman101f2502016-06-09 17:21:19 +0200457 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800458 observers_capacities[observer_config.observer] =
459 observer_config.max_bitrate_bps - observer_config.min_bitrate_bps;
460 }
mflodman101f2502016-06-09 17:21:19 +0200461
462 bitrate -= sum_min_bitrates;
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800463 // From the remaining bitrate, allocate a proportional amount to each observer
464 // above the min bitrate already allocated.
mflodman101f2502016-06-09 17:21:19 +0200465 if (bitrate > 0)
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800466 DistributeBitrateRelatively(bitrate, observers_capacities, &allocation);
mflodman101f2502016-06-09 17:21:19 +0200467
468 return allocation;
469}
470
471BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
perkj26091b12016-09-01 01:17:40 -0700472 uint32_t bitrate,
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200473 uint32_t sum_max_bitrates) const {
mflodman101f2502016-06-09 17:21:19 +0200474 ObserverAllocation allocation;
475
476 for (const auto& observer_config : bitrate_observer_configs_) {
477 allocation[observer_config.observer] = observer_config.max_bitrate_bps;
478 bitrate -= observer_config.max_bitrate_bps;
479 }
Ying Wanga646d302018-03-02 17:04:11 +0100480 DistributeBitrateEvenly(bitrate, true, transmission_max_bitrate_multiplier_,
mflodman101f2502016-06-09 17:21:19 +0200481 &allocation);
482 return allocation;
483}
484
srte1eb051c2017-11-29 11:23:59 +0100485uint32_t BitrateAllocator::ObserverConfig::LastAllocatedBitrate() const {
mflodman101f2502016-06-09 17:21:19 +0200486 // Return the configured minimum bitrate for newly added observers, to avoid
487 // requiring an extra high bitrate for the observer to get an allocated
488 // bitrate.
srte1eb051c2017-11-29 11:23:59 +0100489 return allocated_bitrate_bps == -1 ? min_bitrate_bps : allocated_bitrate_bps;
mflodman101f2502016-06-09 17:21:19 +0200490}
491
srte1eb051c2017-11-29 11:23:59 +0100492uint32_t BitrateAllocator::ObserverConfig::MinBitrateWithHysteresis() const {
493 uint32_t min_bitrate = min_bitrate_bps;
494 if (LastAllocatedBitrate() == 0) {
mflodman101f2502016-06-09 17:21:19 +0200495 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
496 kMinToggleBitrateBps);
497 }
mflodman48a4beb2016-07-01 13:03:59 +0200498 // Account for protection bitrate used by this observer in the previous
499 // allocation.
500 // Note: the ratio will only be updated when the stream is active, meaning a
501 // paused stream won't get any ratio updates. This might lead to waiting a bit
502 // longer than necessary if the network condition improves, but this is to
503 // avoid too much toggling.
srte1eb051c2017-11-29 11:23:59 +0100504 if (media_ratio > 0.0 && media_ratio < 1.0)
505 min_bitrate += min_bitrate * (1.0 - media_ratio);
mflodman48a4beb2016-07-01 13:03:59 +0200506
mflodman101f2502016-06-09 17:21:19 +0200507 return min_bitrate;
508}
509
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200510void BitrateAllocator::DistributeBitrateEvenly(
511 uint32_t bitrate,
512 bool include_zero_allocations,
513 int max_multiplier,
514 ObserverAllocation* allocation) const {
mflodman101f2502016-06-09 17:21:19 +0200515 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
516
517 ObserverSortingMap list_max_bitrates;
518 for (const auto& observer_config : bitrate_observer_configs_) {
519 if (include_zero_allocations ||
520 allocation->at(observer_config.observer) != 0) {
521 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
522 observer_config.max_bitrate_bps, &observer_config));
523 }
524 }
525 auto it = list_max_bitrates.begin();
526 while (it != list_max_bitrates.end()) {
kwibergaf476c72016-11-28 15:21:39 -0800527 RTC_DCHECK_GT(bitrate, 0);
mflodman101f2502016-06-09 17:21:19 +0200528 uint32_t extra_allocation =
529 bitrate / static_cast<uint32_t>(list_max_bitrates.size());
530 uint32_t total_allocation =
531 extra_allocation + allocation->at(it->second->observer);
532 bitrate -= extra_allocation;
533 if (total_allocation > max_multiplier * it->first) {
534 // There is more than we can fit for this observer, carry over to the
535 // remaining observers.
536 bitrate += total_allocation - max_multiplier * it->first;
537 total_allocation = max_multiplier * it->first;
538 }
539 // Finally, update the allocation for this observer.
540 allocation->at(it->second->observer) = total_allocation;
541 it = list_max_bitrates.erase(it);
542 }
543}
544
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200545bool BitrateAllocator::EnoughBitrateForAllObservers(
546 uint32_t bitrate,
547 uint32_t sum_min_bitrates) const {
mflodman101f2502016-06-09 17:21:19 +0200548 if (bitrate < sum_min_bitrates)
549 return false;
550
perkj26091b12016-09-01 01:17:40 -0700551 uint32_t extra_bitrate_per_observer =
552 (bitrate - sum_min_bitrates) /
mflodman101f2502016-06-09 17:21:19 +0200553 static_cast<uint32_t>(bitrate_observer_configs_.size());
554 for (const auto& observer_config : bitrate_observer_configs_) {
555 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
srte1eb051c2017-11-29 11:23:59 +0100556 observer_config.MinBitrateWithHysteresis()) {
mflodman101f2502016-06-09 17:21:19 +0200557 return false;
philipel5ef2bc12017-02-21 07:28:31 -0800558 }
mflodman101f2502016-06-09 17:21:19 +0200559 }
560 return true;
561}
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800562
563void BitrateAllocator::DistributeBitrateRelatively(
564 uint32_t remaining_bitrate,
565 const ObserverAllocation& observers_capacities,
Sebastian Jansson44a262a2018-10-24 16:07:20 +0200566 ObserverAllocation* allocation) const {
Seth Hampsonfe73d6a2017-11-14 10:49:06 -0800567 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
568 RTC_DCHECK_EQ(observers_capacities.size(), bitrate_observer_configs_.size());
569
570 struct PriorityRateObserverConfig {
571 PriorityRateObserverConfig(BitrateAllocatorObserver* allocation_key,
572 uint32_t capacity_bps,
573 double bitrate_priority)
574 : allocation_key(allocation_key),
575 capacity_bps(capacity_bps),
576 bitrate_priority(bitrate_priority) {}
577
578 BitrateAllocatorObserver* allocation_key;
579 // The amount of bitrate bps that can be allocated to this observer.
580 uint32_t capacity_bps;
581 double bitrate_priority;
582
583 // We want to sort by which observers will be allocated their full capacity
584 // first. By dividing each observer's capacity by its bitrate priority we
585 // are "normalizing" the capacity of an observer by the rate it will be
586 // filled. This is because the amount allocated is based upon bitrate
587 // priority. We allocate twice as much bitrate to an observer with twice the
588 // bitrate priority of another.
589 bool operator<(const PriorityRateObserverConfig& other) const {
590 return capacity_bps / bitrate_priority <
591 other.capacity_bps / other.bitrate_priority;
592 }
593 };
594
595 double bitrate_priority_sum = 0;
596 std::vector<PriorityRateObserverConfig> priority_rate_observers;
597 for (const auto& observer_config : bitrate_observer_configs_) {
598 uint32_t capacity_bps = observers_capacities.at(observer_config.observer);
599 priority_rate_observers.emplace_back(observer_config.observer, capacity_bps,
600 observer_config.bitrate_priority);
601 bitrate_priority_sum += observer_config.bitrate_priority;
602 }
603
604 // Iterate in the order observers can be allocated their full capacity.
605 std::sort(priority_rate_observers.begin(), priority_rate_observers.end());
606 size_t i;
607 for (i = 0; i < priority_rate_observers.size(); ++i) {
608 const auto& priority_rate_observer = priority_rate_observers[i];
609 // We allocate the full capacity to an observer only if its relative
610 // portion from the remaining bitrate is sufficient to allocate its full
611 // capacity. This means we aren't greedily allocating the full capacity, but
612 // that it is only done when there is also enough bitrate to allocate the
613 // proportional amounts to all other observers.
614 double observer_share =
615 priority_rate_observer.bitrate_priority / bitrate_priority_sum;
616 double allocation_bps = observer_share * remaining_bitrate;
617 bool enough_bitrate = allocation_bps >= priority_rate_observer.capacity_bps;
618 if (!enough_bitrate)
619 break;
620 allocation->at(priority_rate_observer.allocation_key) +=
621 priority_rate_observer.capacity_bps;
622 remaining_bitrate -= priority_rate_observer.capacity_bps;
623 bitrate_priority_sum -= priority_rate_observer.bitrate_priority;
624 }
625
626 // From the remaining bitrate, allocate the proportional amounts to the
627 // observers that aren't allocated their max capacity.
628 for (; i < priority_rate_observers.size(); ++i) {
629 const auto& priority_rate_observer = priority_rate_observers[i];
630 double fraction_allocated =
631 priority_rate_observer.bitrate_priority / bitrate_priority_sum;
632 allocation->at(priority_rate_observer.allocation_key) +=
633 fraction_allocated * remaining_bitrate;
634 }
635}
636
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000637} // namespace webrtc