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/modules/bitrate_controller/include/bitrate_allocator.h"
13
14 #include <algorithm>
15 #include <utility>
16
17 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
18
19 namespace webrtc {
20
21 // Allow packets to be transmitted in up to 2 times max video bitrate if the
22 // bandwidth estimate allows it.
23 const int kTransmissionMaxBitrateMultiplier = 2;
24 const int kDefaultBitrateBps = 300000;
25
BitrateAllocator()26 BitrateAllocator::BitrateAllocator()
27 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
28 bitrate_observers_(),
29 enforce_min_bitrate_(true),
30 last_bitrate_bps_(kDefaultBitrateBps),
31 last_fraction_loss_(0),
32 last_rtt_(0) {
33 }
34
35
OnNetworkChanged(uint32_t bitrate,uint8_t fraction_loss,int64_t rtt)36 void BitrateAllocator::OnNetworkChanged(uint32_t bitrate,
37 uint8_t fraction_loss,
38 int64_t rtt) {
39 CriticalSectionScoped lock(crit_sect_.get());
40 last_bitrate_bps_ = bitrate;
41 last_fraction_loss_ = fraction_loss;
42 last_rtt_ = rtt;
43 ObserverBitrateMap allocation = AllocateBitrates();
44 for (const auto& kv : allocation)
45 kv.first->OnNetworkChanged(kv.second, last_fraction_loss_, last_rtt_);
46 }
47
AllocateBitrates()48 BitrateAllocator::ObserverBitrateMap BitrateAllocator::AllocateBitrates() {
49 if (bitrate_observers_.empty())
50 return ObserverBitrateMap();
51
52 uint32_t sum_min_bitrates = 0;
53 for (const auto& observer : bitrate_observers_)
54 sum_min_bitrates += observer.second.min_bitrate_;
55 if (last_bitrate_bps_ <= sum_min_bitrates)
56 return LowRateAllocation(last_bitrate_bps_);
57 else
58 return NormalRateAllocation(last_bitrate_bps_, sum_min_bitrates);
59 }
60
AddBitrateObserver(BitrateObserver * observer,uint32_t start_bitrate_bps,uint32_t min_bitrate_bps,uint32_t max_bitrate_bps,int * new_observer_bitrate_bps)61 int BitrateAllocator::AddBitrateObserver(BitrateObserver* observer,
62 uint32_t start_bitrate_bps,
63 uint32_t min_bitrate_bps,
64 uint32_t max_bitrate_bps,
65 int* new_observer_bitrate_bps) {
66 CriticalSectionScoped lock(crit_sect_.get());
67
68 BitrateObserverConfList::iterator it =
69 FindObserverConfigurationPair(observer);
70
71 // Allow the max bitrate to be exceeded for FEC and retransmissions.
72 // TODO(holmer): We have to get rid of this hack as it makes it difficult to
73 // properly allocate bitrate. The allocator should instead distribute any
74 // extra bitrate after all streams have maxed out.
75 max_bitrate_bps *= kTransmissionMaxBitrateMultiplier;
76 int new_bwe_candidate_bps = 0;
77 if (it != bitrate_observers_.end()) {
78 // Update current configuration.
79 it->second.start_bitrate_ = start_bitrate_bps;
80 it->second.min_bitrate_ = min_bitrate_bps;
81 it->second.max_bitrate_ = max_bitrate_bps;
82 // Set the send-side bandwidth to the max of the sum of start bitrates and
83 // the current estimate, so that if the user wants to immediately use more
84 // bandwidth, that can be enforced.
85 for (const auto& observer : bitrate_observers_)
86 new_bwe_candidate_bps += observer.second.start_bitrate_;
87 } else {
88 // Add new settings.
89 bitrate_observers_.push_back(BitrateObserverConfiguration(
90 observer, BitrateConfiguration(start_bitrate_bps, min_bitrate_bps,
91 max_bitrate_bps)));
92 bitrate_observers_modified_ = true;
93
94 // TODO(andresp): This is a ugly way to set start bitrate.
95 //
96 // Only change start bitrate if we have exactly one observer. By definition
97 // you can only have one start bitrate, once we have our first estimate we
98 // will adapt from there.
99 if (bitrate_observers_.size() == 1)
100 new_bwe_candidate_bps = start_bitrate_bps;
101 }
102
103 last_bitrate_bps_ = std::max<int>(new_bwe_candidate_bps, last_bitrate_bps_);
104
105 ObserverBitrateMap allocation = AllocateBitrates();
106 *new_observer_bitrate_bps = 0;
107 for (auto& kv : allocation) {
108 kv.first->OnNetworkChanged(kv.second, last_fraction_loss_, last_rtt_);
109 if (kv.first == observer)
110 *new_observer_bitrate_bps = kv.second;
111 }
112 return last_bitrate_bps_;
113 }
114
RemoveBitrateObserver(BitrateObserver * observer)115 void BitrateAllocator::RemoveBitrateObserver(BitrateObserver* observer) {
116 CriticalSectionScoped lock(crit_sect_.get());
117 BitrateObserverConfList::iterator it =
118 FindObserverConfigurationPair(observer);
119 if (it != bitrate_observers_.end()) {
120 bitrate_observers_.erase(it);
121 bitrate_observers_modified_ = true;
122 }
123 }
124
GetMinMaxBitrateSumBps(int * min_bitrate_sum_bps,int * max_bitrate_sum_bps) const125 void BitrateAllocator::GetMinMaxBitrateSumBps(int* min_bitrate_sum_bps,
126 int* max_bitrate_sum_bps) const {
127 *min_bitrate_sum_bps = 0;
128 *max_bitrate_sum_bps = 0;
129
130 CriticalSectionScoped lock(crit_sect_.get());
131 for (const auto& observer : bitrate_observers_) {
132 *min_bitrate_sum_bps += observer.second.min_bitrate_;
133 *max_bitrate_sum_bps += observer.second.max_bitrate_;
134 }
135 }
136
137 BitrateAllocator::BitrateObserverConfList::iterator
FindObserverConfigurationPair(const BitrateObserver * observer)138 BitrateAllocator::FindObserverConfigurationPair(
139 const BitrateObserver* observer) {
140 for (auto it = bitrate_observers_.begin(); it != bitrate_observers_.end();
141 ++it) {
142 if (it->first == observer)
143 return it;
144 }
145 return bitrate_observers_.end();
146 }
147
EnforceMinBitrate(bool enforce_min_bitrate)148 void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) {
149 CriticalSectionScoped lock(crit_sect_.get());
150 enforce_min_bitrate_ = enforce_min_bitrate;
151 }
152
NormalRateAllocation(uint32_t bitrate,uint32_t sum_min_bitrates)153 BitrateAllocator::ObserverBitrateMap BitrateAllocator::NormalRateAllocation(
154 uint32_t bitrate,
155 uint32_t sum_min_bitrates) {
156 uint32_t number_of_observers = bitrate_observers_.size();
157 uint32_t bitrate_per_observer =
158 (bitrate - sum_min_bitrates) / number_of_observers;
159 // Use map to sort list based on max bitrate.
160 ObserverSortingMap list_max_bitrates;
161 for (const auto& observer : bitrate_observers_) {
162 list_max_bitrates.insert(std::pair<uint32_t, ObserverConfiguration>(
163 observer.second.max_bitrate_,
164 ObserverConfiguration(observer.first, observer.second.min_bitrate_)));
165 }
166 ObserverBitrateMap allocation;
167 ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
168 while (max_it != list_max_bitrates.end()) {
169 number_of_observers--;
170 uint32_t observer_allowance =
171 max_it->second.min_bitrate_ + bitrate_per_observer;
172 if (max_it->first < observer_allowance) {
173 // We have more than enough for this observer.
174 // Carry the remainder forward.
175 uint32_t remainder = observer_allowance - max_it->first;
176 if (number_of_observers != 0) {
177 bitrate_per_observer += remainder / number_of_observers;
178 }
179 allocation[max_it->second.observer_] = max_it->first;
180 } else {
181 allocation[max_it->second.observer_] = observer_allowance;
182 }
183 list_max_bitrates.erase(max_it);
184 // Prepare next iteration.
185 max_it = list_max_bitrates.begin();
186 }
187 return allocation;
188 }
189
LowRateAllocation(uint32_t bitrate)190 BitrateAllocator::ObserverBitrateMap BitrateAllocator::LowRateAllocation(
191 uint32_t bitrate) {
192 ObserverBitrateMap allocation;
193 if (enforce_min_bitrate_) {
194 // Min bitrate to all observers.
195 for (const auto& observer : bitrate_observers_)
196 allocation[observer.first] = observer.second.min_bitrate_;
197 } else {
198 // Allocate up to |min_bitrate_| to one observer at a time, until
199 // |bitrate| is depleted.
200 uint32_t remainder = bitrate;
201 for (const auto& observer : bitrate_observers_) {
202 uint32_t allocated_bitrate =
203 std::min(remainder, observer.second.min_bitrate_);
204 allocation[observer.first] = allocated_bitrate;
205 remainder -= allocated_bitrate;
206 }
207 }
208 return allocation;
209 }
210 } // namespace webrtc
211