blob: 3672ef520ca3422bc372d2108b75abf9b5390666 [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
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000027BitrateAllocator::BitrateAllocator()
mflodman2ebe5b12016-05-13 01:43:51 -070028 : bitrate_observer_configs_(),
Stefan Holmere5904162015-03-26 11:11:06 +010029 enforce_min_bitrate_(true),
30 last_bitrate_bps_(kDefaultBitrateBps),
perkjfea93092016-05-14 00:58:48 -070031 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
Stefan Holmere5904162015-03-26 11:11:06 +010032 last_fraction_loss_(0),
sprang2f48d942015-11-05 04:25:49 -080033 last_rtt_(0) {}
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000034
sprang2f48d942015-11-05 04:25:49 -080035uint32_t BitrateAllocator::OnNetworkChanged(uint32_t bitrate,
36 uint8_t fraction_loss,
37 int64_t rtt) {
tommi63cb4342016-01-20 02:32:54 -080038 rtc::CritScope lock(&crit_sect_);
Stefan Holmere5904162015-03-26 11:11:06 +010039 last_bitrate_bps_ = bitrate;
perkjfea93092016-05-14 00:58:48 -070040 last_non_zero_bitrate_bps_ =
41 bitrate > 0 ? bitrate : last_non_zero_bitrate_bps_;
Stefan Holmere5904162015-03-26 11:11:06 +010042 last_fraction_loss_ = fraction_loss;
43 last_rtt_ = rtt;
mflodman2ebe5b12016-05-13 01:43:51 -070044
sprang2f48d942015-11-05 04:25:49 -080045 uint32_t allocated_bitrate_bps = 0;
perkjfea93092016-05-14 00:58:48 -070046 ObserverAllocation allocation = AllocateBitrates(bitrate);
sprang2f48d942015-11-05 04:25:49 -080047 for (const auto& kv : allocation) {
mflodman86aabb22016-03-11 15:44:32 +010048 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
sprang2f48d942015-11-05 04:25:49 -080049 allocated_bitrate_bps += kv.second;
50 }
51 return allocated_bitrate_bps;
Stefan Holmere5904162015-03-26 11:11:06 +010052}
53
mflodman86aabb22016-03-11 15:44:32 +010054int BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
55 uint32_t min_bitrate_bps,
mflodman2ebe5b12016-05-13 01:43:51 -070056 uint32_t max_bitrate_bps,
57 bool enforce_min_bitrate) {
tommi63cb4342016-01-20 02:32:54 -080058 rtc::CritScope lock(&crit_sect_);
mflodman2ebe5b12016-05-13 01:43:51 -070059 // TODO(mflodman): Enforce this per observer.
60 EnforceMinBitrate(enforce_min_bitrate);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000061
mflodman2ebe5b12016-05-13 01:43:51 -070062 auto it = FindObserverConfig(observer);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000063
Stefan Holmere5904162015-03-26 11:11:06 +010064 // Allow the max bitrate to be exceeded for FEC and retransmissions.
65 // TODO(holmer): We have to get rid of this hack as it makes it difficult to
66 // properly allocate bitrate. The allocator should instead distribute any
67 // extra bitrate after all streams have maxed out.
68 max_bitrate_bps *= kTransmissionMaxBitrateMultiplier;
mflodman2ebe5b12016-05-13 01:43:51 -070069 if (it != bitrate_observer_configs_.end()) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000070 // Update current configuration.
mflodman2ebe5b12016-05-13 01:43:51 -070071 it->min_bitrate_bps = min_bitrate_bps;
72 it->max_bitrate_bps = max_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000073 } else {
74 // Add new settings.
mflodman2ebe5b12016-05-13 01:43:51 -070075 bitrate_observer_configs_.push_back(ObserverConfig(
76 observer, min_bitrate_bps, max_bitrate_bps, enforce_min_bitrate));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000077 }
Stefan Holmere5904162015-03-26 11:11:06 +010078
Peter Boström8e4e8b02015-09-15 15:08:03 +020079 int new_observer_bitrate_bps = 0;
perkjfea93092016-05-14 00:58:48 -070080 if (last_bitrate_bps_ > 0) { // We have a bitrate to allocate.
81 ObserverAllocation allocation = AllocateBitrates(last_bitrate_bps_);
82 for (auto& kv : allocation) {
83 // Update all observers with the new allocation.
84 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
85 if (kv.first == observer)
86 new_observer_bitrate_bps = kv.second;
87 }
88 } else {
89 // Currently, an encoder is not allowed to produce frames.
90 // But we still have to return the initial config bitrate + let the
91 // observer know that it can not produce frames.
92 ObserverAllocation allocation =
93 AllocateBitrates(last_non_zero_bitrate_bps_);
94 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_);
95 new_observer_bitrate_bps = allocation[observer];
Stefan Holmere5904162015-03-26 11:11:06 +010096 }
Peter Boström8e4e8b02015-09-15 15:08:03 +020097 return new_observer_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000098}
99
mflodman86aabb22016-03-11 15:44:32 +0100100void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
tommi63cb4342016-01-20 02:32:54 -0800101 rtc::CritScope lock(&crit_sect_);
mflodman2ebe5b12016-05-13 01:43:51 -0700102 auto it = FindObserverConfig(observer);
103 if (it != bitrate_observer_configs_.end()) {
104 bitrate_observer_configs_.erase(it);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000105 }
106}
107
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000108void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000109 enforce_min_bitrate_ = enforce_min_bitrate;
110}
111
mflodman2ebe5b12016-05-13 01:43:51 -0700112BitrateAllocator::ObserverConfigList::iterator
113BitrateAllocator::FindObserverConfig(
114 const BitrateAllocatorObserver* observer) {
115 for (auto it = bitrate_observer_configs_.begin();
116 it != bitrate_observer_configs_.end(); ++it) {
117 if (it->observer == observer)
118 return it;
119 }
120 return bitrate_observer_configs_.end();
121}
122
perkjfea93092016-05-14 00:58:48 -0700123BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
124 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700125 if (bitrate_observer_configs_.empty())
126 return ObserverAllocation();
127
perkjfea93092016-05-14 00:58:48 -0700128 if (bitrate == 0)
mflodman2ebe5b12016-05-13 01:43:51 -0700129 return ZeroRateAllocation();
130
131 uint32_t sum_min_bitrates = 0;
132 for (const auto& observer_config : bitrate_observer_configs_)
133 sum_min_bitrates += observer_config.min_bitrate_bps;
perkjfea93092016-05-14 00:58:48 -0700134 if (bitrate <= sum_min_bitrates)
135 return LowRateAllocation(bitrate);
mflodman2ebe5b12016-05-13 01:43:51 -0700136
perkjfea93092016-05-14 00:58:48 -0700137 return NormalRateAllocation(bitrate, sum_min_bitrates);
mflodman2ebe5b12016-05-13 01:43:51 -0700138}
139
140BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
Stefan Holmere5904162015-03-26 11:11:06 +0100141 uint32_t bitrate,
142 uint32_t sum_min_bitrates) {
mflodman2ebe5b12016-05-13 01:43:51 -0700143 uint32_t num_remaining_observers =
144 static_cast<uint32_t>(bitrate_observer_configs_.size());
145 RTC_DCHECK_GT(num_remaining_observers, 0u);
146
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000147 uint32_t bitrate_per_observer =
mflodman2ebe5b12016-05-13 01:43:51 -0700148 (bitrate - sum_min_bitrates) / num_remaining_observers;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000149 // Use map to sort list based on max bitrate.
150 ObserverSortingMap list_max_bitrates;
mflodman2ebe5b12016-05-13 01:43:51 -0700151 for (const auto& config : bitrate_observer_configs_) {
152 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
153 config.max_bitrate_bps, &config));
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000154 }
mflodman2ebe5b12016-05-13 01:43:51 -0700155
156 ObserverAllocation allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000157 ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
158 while (max_it != list_max_bitrates.end()) {
mflodman2ebe5b12016-05-13 01:43:51 -0700159 num_remaining_observers--;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000160 uint32_t observer_allowance =
mflodman2ebe5b12016-05-13 01:43:51 -0700161 max_it->second->min_bitrate_bps + bitrate_per_observer;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000162 if (max_it->first < observer_allowance) {
163 // We have more than enough for this observer.
164 // Carry the remainder forward.
165 uint32_t remainder = observer_allowance - max_it->first;
mflodman2ebe5b12016-05-13 01:43:51 -0700166 if (num_remaining_observers != 0)
167 bitrate_per_observer += remainder / num_remaining_observers;
168 allocation[max_it->second->observer] = max_it->first;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000169 } else {
mflodman2ebe5b12016-05-13 01:43:51 -0700170 allocation[max_it->second->observer] = observer_allowance;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000171 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000172 list_max_bitrates.erase(max_it);
173 // Prepare next iteration.
174 max_it = list_max_bitrates.begin();
175 }
Stefan Holmere5904162015-03-26 11:11:06 +0100176 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000177}
178
mflodman2ebe5b12016-05-13 01:43:51 -0700179BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
180 ObserverAllocation allocation;
perkjec81bcd2016-05-11 06:01:13 -0700181 // Zero bitrate to all observers.
mflodman2ebe5b12016-05-13 01:43:51 -0700182 for (const auto& observer_config : bitrate_observer_configs_)
183 allocation[observer_config.observer] = 0;
perkjec81bcd2016-05-11 06:01:13 -0700184 return allocation;
185}
186
mflodman2ebe5b12016-05-13 01:43:51 -0700187BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
Stefan Holmere5904162015-03-26 11:11:06 +0100188 uint32_t bitrate) {
mflodman2ebe5b12016-05-13 01:43:51 -0700189 ObserverAllocation allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000190 if (enforce_min_bitrate_) {
191 // Min bitrate to all observers.
mflodman2ebe5b12016-05-13 01:43:51 -0700192 for (const auto& observer_config : bitrate_observer_configs_)
193 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000194 } else {
mflodman2ebe5b12016-05-13 01:43:51 -0700195 // Allocate up to |min_bitrate_bps| to one observer at a time, until
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000196 // |bitrate| is depleted.
197 uint32_t remainder = bitrate;
mflodman2ebe5b12016-05-13 01:43:51 -0700198 for (const auto& observer_config : bitrate_observer_configs_) {
Stefan Holmere5904162015-03-26 11:11:06 +0100199 uint32_t allocated_bitrate =
mflodman2ebe5b12016-05-13 01:43:51 -0700200 std::min(remainder, observer_config.min_bitrate_bps);
201 allocation[observer_config.observer] = allocated_bitrate;
Stefan Holmere5904162015-03-26 11:11:06 +0100202 remainder -= allocated_bitrate;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000203 }
204 }
Stefan Holmere5904162015-03-26 11:11:06 +0100205 return allocation;
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000206}
207} // namespace webrtc