Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: webrtc/call/bitrate_allocator.cc

Issue 2035383002: Implementing auto pausing of video streams. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Removed comment. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/call/bitrate_allocator.h ('k') | webrtc/call/bitrate_allocator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 * 9 *
10 */ 10 */
11 11
12 #include "webrtc/call/bitrate_allocator.h" 12 #include "webrtc/call/bitrate_allocator.h"
13 13
14 #include <algorithm> 14 #include <algorithm>
15 #include <utility> 15 #include <utility>
16 16
17 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
18 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" 18 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
19 19
20 namespace webrtc { 20 namespace webrtc {
21 21
22 // Allow packets to be transmitted in up to 2 times max video bitrate if the 22 // Allow packets to be transmitted in up to 2 times max video bitrate if the
23 // bandwidth estimate allows it. 23 // bandwidth estimate allows it.
24 const int kTransmissionMaxBitrateMultiplier = 2; 24 const int kTransmissionMaxBitrateMultiplier = 2;
25 const int kDefaultBitrateBps = 300000; 25 const int kDefaultBitrateBps = 300000;
26 26
27 // Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
28 const double kToggleFactor = 0.1;
29 const uint32_t kMinToggleBitrateBps = 20000;
30
27 BitrateAllocator::BitrateAllocator() 31 BitrateAllocator::BitrateAllocator()
28 : bitrate_observer_configs_(), 32 : bitrate_observer_configs_(),
29 enforce_min_bitrate_(true),
30 last_bitrate_bps_(kDefaultBitrateBps), 33 last_bitrate_bps_(kDefaultBitrateBps),
31 last_non_zero_bitrate_bps_(kDefaultBitrateBps), 34 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
32 last_fraction_loss_(0), 35 last_fraction_loss_(0),
33 last_rtt_(0) {} 36 last_rtt_(0) {}
34 37
35 uint32_t BitrateAllocator::OnNetworkChanged(uint32_t bitrate, 38 uint32_t BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
36 uint8_t fraction_loss, 39 uint8_t fraction_loss,
37 int64_t rtt) { 40 int64_t rtt) {
38 rtc::CritScope lock(&crit_sect_); 41 rtc::CritScope lock(&crit_sect_);
39 last_bitrate_bps_ = bitrate; 42 last_bitrate_bps_ = target_bitrate_bps;
40 last_non_zero_bitrate_bps_ = 43 last_non_zero_bitrate_bps_ =
41 bitrate > 0 ? bitrate : last_non_zero_bitrate_bps_; 44 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
42 last_fraction_loss_ = fraction_loss; 45 last_fraction_loss_ = fraction_loss;
43 last_rtt_ = rtt; 46 last_rtt_ = rtt;
44 47
45 uint32_t allocated_bitrate_bps = 0; 48 uint32_t allocated_bitrate_bps = 0;
46 ObserverAllocation allocation = AllocateBitrates(bitrate); 49 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
47 for (const auto& kv : allocation) { 50 for (const auto& kv : allocation) {
48 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); 51 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
49 allocated_bitrate_bps += kv.second; 52 allocated_bitrate_bps += kv.second;
50 } 53 }
54 last_allocation_ = allocation;
51 return allocated_bitrate_bps; 55 return allocated_bitrate_bps;
52 } 56 }
53 57
54 int BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, 58 int BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
55 uint32_t min_bitrate_bps, 59 uint32_t min_bitrate_bps,
56 uint32_t max_bitrate_bps, 60 uint32_t max_bitrate_bps,
57 bool enforce_min_bitrate) { 61 bool enforce_min_bitrate) {
58 rtc::CritScope lock(&crit_sect_); 62 rtc::CritScope lock(&crit_sect_);
59 // TODO(mflodman): Enforce this per observer.
60 EnforceMinBitrate(enforce_min_bitrate);
61
62 auto it = FindObserverConfig(observer); 63 auto it = FindObserverConfig(observer);
63 64
64 // Allow the max bitrate to be exceeded for FEC and retransmissions. 65 // Update settings if the observer already exists, create a new one otherwise.
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;
69 if (it != bitrate_observer_configs_.end()) { 66 if (it != bitrate_observer_configs_.end()) {
70 // Update current configuration.
71 it->min_bitrate_bps = min_bitrate_bps; 67 it->min_bitrate_bps = min_bitrate_bps;
72 it->max_bitrate_bps = max_bitrate_bps; 68 it->max_bitrate_bps = max_bitrate_bps;
69 it->enforce_min_bitrate = enforce_min_bitrate;
73 } else { 70 } else {
74 // Add new settings.
75 bitrate_observer_configs_.push_back(ObserverConfig( 71 bitrate_observer_configs_.push_back(ObserverConfig(
76 observer, min_bitrate_bps, max_bitrate_bps, enforce_min_bitrate)); 72 observer, min_bitrate_bps, max_bitrate_bps, enforce_min_bitrate));
77 } 73 }
78 74
79 int new_observer_bitrate_bps = 0; 75 ObserverAllocation allocation;
80 if (last_bitrate_bps_ > 0) { // We have a bitrate to allocate. 76 if (last_bitrate_bps_ > 0) {
81 ObserverAllocation allocation = AllocateBitrates(last_bitrate_bps_); 77 // Calculate a new allocation and update all observers.
82 for (auto& kv : allocation) { 78 allocation = AllocateBitrates(last_bitrate_bps_);
83 // Update all observers with the new allocation. 79 for (const auto& kv : allocation)
84 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); 80 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 { 81 } else {
89 // Currently, an encoder is not allowed to produce frames. 82 // Currently, an encoder is not allowed to produce frames.
90 // But we still have to return the initial config bitrate + let the 83 // But we still have to return the initial config bitrate + let the
91 // observer know that it can not produce frames. 84 // observer know that it can not produce frames.
92 ObserverAllocation allocation = 85 allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
93 AllocateBitrates(last_non_zero_bitrate_bps_);
94 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_); 86 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_);
95 new_observer_bitrate_bps = allocation[observer];
96 } 87 }
97 return new_observer_bitrate_bps; 88 last_allocation_ = allocation;
89 return allocation[observer];
98 } 90 }
99 91
100 void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) { 92 void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
101 rtc::CritScope lock(&crit_sect_); 93 rtc::CritScope lock(&crit_sect_);
102 auto it = FindObserverConfig(observer); 94 auto it = FindObserverConfig(observer);
103 if (it != bitrate_observer_configs_.end()) { 95 if (it != bitrate_observer_configs_.end()) {
104 bitrate_observer_configs_.erase(it); 96 bitrate_observer_configs_.erase(it);
105 } 97 }
106 } 98 }
107 99
108 void BitrateAllocator::EnforceMinBitrate(bool enforce_min_bitrate) {
109 enforce_min_bitrate_ = enforce_min_bitrate;
110 }
111
112 BitrateAllocator::ObserverConfigList::iterator 100 BitrateAllocator::ObserverConfigList::iterator
113 BitrateAllocator::FindObserverConfig( 101 BitrateAllocator::FindObserverConfig(
114 const BitrateAllocatorObserver* observer) { 102 const BitrateAllocatorObserver* observer) {
115 for (auto it = bitrate_observer_configs_.begin(); 103 for (auto it = bitrate_observer_configs_.begin();
116 it != bitrate_observer_configs_.end(); ++it) { 104 it != bitrate_observer_configs_.end(); ++it) {
117 if (it->observer == observer) 105 if (it->observer == observer)
118 return it; 106 return it;
119 } 107 }
120 return bitrate_observer_configs_.end(); 108 return bitrate_observer_configs_.end();
121 } 109 }
122 110
123 BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates( 111 BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
124 uint32_t bitrate) { 112 uint32_t bitrate) {
125 if (bitrate_observer_configs_.empty()) 113 if (bitrate_observer_configs_.empty())
126 return ObserverAllocation(); 114 return ObserverAllocation();
127 115
128 if (bitrate == 0) 116 if (bitrate == 0)
129 return ZeroRateAllocation(); 117 return ZeroRateAllocation();
130 118
131 uint32_t sum_min_bitrates = 0; 119 uint32_t sum_min_bitrates = 0;
132 for (const auto& observer_config : bitrate_observer_configs_) 120 uint32_t sum_max_bitrates = 0;
121 for (const auto& observer_config : bitrate_observer_configs_) {
133 sum_min_bitrates += observer_config.min_bitrate_bps; 122 sum_min_bitrates += observer_config.min_bitrate_bps;
134 if (bitrate <= sum_min_bitrates) 123 sum_max_bitrates += observer_config.max_bitrate_bps;
124 }
125
126 // Not enough for all observers to get an allocation, allocate according to:
127 // enforced min bitrate -> allocated bitrate previous round -> restart paused
128 // streams.
129 if (!EnoughBitrateForAllObservers(bitrate, sum_min_bitrates))
135 return LowRateAllocation(bitrate); 130 return LowRateAllocation(bitrate);
136 131
137 return NormalRateAllocation(bitrate, sum_min_bitrates); 132 // All observers will get their min bitrate plus an even share of the rest.
138 } 133 if (bitrate <= sum_max_bitrates)
134 return NormalRateAllocation(bitrate, sum_min_bitrates);
139 135
140 BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation( 136 // All observers will get up to kTransmissionMaxBitrateMultiplier x max.
141 uint32_t bitrate, 137 return MaxRateAllocation(bitrate, sum_max_bitrates);
142 uint32_t sum_min_bitrates) {
143 uint32_t num_remaining_observers =
144 static_cast<uint32_t>(bitrate_observer_configs_.size());
145 RTC_DCHECK_GT(num_remaining_observers, 0u);
146
147 uint32_t bitrate_per_observer =
148 (bitrate - sum_min_bitrates) / num_remaining_observers;
149 // Use map to sort list based on max bitrate.
150 ObserverSortingMap list_max_bitrates;
151 for (const auto& config : bitrate_observer_configs_) {
152 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
153 config.max_bitrate_bps, &config));
154 }
155
156 ObserverAllocation allocation;
157 ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
158 while (max_it != list_max_bitrates.end()) {
159 num_remaining_observers--;
160 uint32_t observer_allowance =
161 max_it->second->min_bitrate_bps + bitrate_per_observer;
162 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;
166 if (num_remaining_observers != 0)
167 bitrate_per_observer += remainder / num_remaining_observers;
168 allocation[max_it->second->observer] = max_it->first;
169 } else {
170 allocation[max_it->second->observer] = observer_allowance;
171 }
172 list_max_bitrates.erase(max_it);
173 // Prepare next iteration.
174 max_it = list_max_bitrates.begin();
175 }
176 return allocation;
177 } 138 }
178 139
179 BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() { 140 BitrateAllocator::ObserverAllocation BitrateAllocator::ZeroRateAllocation() {
180 ObserverAllocation allocation; 141 ObserverAllocation allocation;
181 // Zero bitrate to all observers.
182 for (const auto& observer_config : bitrate_observer_configs_) 142 for (const auto& observer_config : bitrate_observer_configs_)
183 allocation[observer_config.observer] = 0; 143 allocation[observer_config.observer] = 0;
184 return allocation; 144 return allocation;
185 } 145 }
186 146
187 BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation( 147 BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
188 uint32_t bitrate) { 148 uint32_t bitrate) {
189 ObserverAllocation allocation; 149 ObserverAllocation allocation;
190 if (enforce_min_bitrate_) { 150
191 // Min bitrate to all observers. 151 // Start by allocating bitrate to observers enforcing a min bitrate, hence
192 for (const auto& observer_config : bitrate_observer_configs_) 152 // remaining_bitrate might turn negative.
193 allocation[observer_config.observer] = observer_config.min_bitrate_bps; 153 int64_t remaining_bitrate = bitrate;
194 } else { 154 for (const auto& observer_config : bitrate_observer_configs_) {
195 // Allocate up to |min_bitrate_bps| to one observer at a time, until 155 int32_t allocated_bitrate = 0;
196 // |bitrate| is depleted. 156 if (observer_config.enforce_min_bitrate)
197 uint32_t remainder = bitrate; 157 allocated_bitrate = observer_config.min_bitrate_bps;
158
159 allocation[observer_config.observer] = allocated_bitrate;
160 remaining_bitrate -= allocated_bitrate;
161 }
162
163 // Allocate bitrate to all previously active streams.
164 if (remaining_bitrate > 0) {
198 for (const auto& observer_config : bitrate_observer_configs_) { 165 for (const auto& observer_config : bitrate_observer_configs_) {
199 uint32_t allocated_bitrate = 166 if (observer_config.enforce_min_bitrate ||
200 std::min(remainder, observer_config.min_bitrate_bps); 167 LastAllocatedBitrate(observer_config) == 0)
201 allocation[observer_config.observer] = allocated_bitrate; 168 continue;
202 remainder -= allocated_bitrate; 169
170 if (remaining_bitrate >= observer_config.min_bitrate_bps) {
171 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
172 remaining_bitrate -= observer_config.min_bitrate_bps;
173 }
203 } 174 }
204 } 175 }
176
177 // Allocate bitrate to previously paused streams.
178 if (remaining_bitrate > 0) {
179 for (const auto& observer_config : bitrate_observer_configs_) {
180 if (LastAllocatedBitrate(observer_config) != 0)
181 continue;
182
183 // Add a hysteresis to avoid toggling.
184 uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
185 if (remaining_bitrate >= required_bitrate) {
186 allocation[observer_config.observer] = required_bitrate;
187 remaining_bitrate -= required_bitrate;
188 }
189 }
190 }
191
192 // Split a possible remainder evenly on all streams with an allocation.
193 if (remaining_bitrate > 0)
194 DistributeBitrateEvenly(remaining_bitrate, false, 1, &allocation);
195
196 RTC_DCHECK_EQ(allocation.size(), bitrate_observer_configs_.size());
205 return allocation; 197 return allocation;
206 } 198 }
199
200 BitrateAllocator::ObserverAllocation BitrateAllocator::NormalRateAllocation(
201 uint32_t bitrate,
202 uint32_t sum_min_bitrates) {
203
204 ObserverAllocation allocation;
205 for (const auto& observer_config : bitrate_observer_configs_)
206 allocation[observer_config.observer] = observer_config.min_bitrate_bps;
207
208 bitrate -= sum_min_bitrates;
209 if (bitrate > 0)
210 DistributeBitrateEvenly(bitrate, true, 1, &allocation);
211
212 return allocation;
213 }
214
215 BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
216 uint32_t bitrate, uint32_t sum_max_bitrates) {
217 ObserverAllocation allocation;
218
219 for (const auto& observer_config : bitrate_observer_configs_) {
220 allocation[observer_config.observer] = observer_config.max_bitrate_bps;
221 bitrate -= observer_config.max_bitrate_bps;
222 }
223 DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
224 &allocation);
225 return allocation;
226 }
227
228 uint32_t BitrateAllocator::LastAllocatedBitrate(
229 const ObserverConfig& observer_config) {
230
231 const auto& it = last_allocation_.find(observer_config.observer);
232 if (it != last_allocation_.end())
233 return it->second;
234
235 // Return the configured minimum bitrate for newly added observers, to avoid
236 // requiring an extra high bitrate for the observer to get an allocated
237 // bitrate.
238 return observer_config.min_bitrate_bps;
239 }
240
241 uint32_t BitrateAllocator::MinBitrateWithHysteresis(
242 const ObserverConfig& observer_config) {
243 uint32_t min_bitrate = observer_config.min_bitrate_bps;
244 if (LastAllocatedBitrate(observer_config) == 0) {
245 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
246 kMinToggleBitrateBps);
247 }
248 return min_bitrate;
249 }
250
251 void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
252 bool include_zero_allocations,
253 int max_multiplier,
254 ObserverAllocation* allocation) {
255 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
256
257 ObserverSortingMap list_max_bitrates;
258 for (const auto& observer_config : bitrate_observer_configs_) {
259 if (include_zero_allocations ||
260 allocation->at(observer_config.observer) != 0) {
261 list_max_bitrates.insert(std::pair<uint32_t, const ObserverConfig*>(
262 observer_config.max_bitrate_bps, &observer_config));
263 }
264 }
265 auto it = list_max_bitrates.begin();
266 while (it != list_max_bitrates.end()) {
267 RTC_DCHECK_GT(bitrate, 0u);
268 uint32_t extra_allocation =
269 bitrate / static_cast<uint32_t>(list_max_bitrates.size());
270 uint32_t total_allocation =
271 extra_allocation + allocation->at(it->second->observer);
272 bitrate -= extra_allocation;
273 if (total_allocation > max_multiplier * it->first) {
274 // There is more than we can fit for this observer, carry over to the
275 // remaining observers.
276 bitrate += total_allocation - max_multiplier * it->first;
277 total_allocation = max_multiplier * it->first;
278 }
279 // Finally, update the allocation for this observer.
280 allocation->at(it->second->observer) = total_allocation;
281 it = list_max_bitrates.erase(it);
282 }
283 }
284
285 bool BitrateAllocator::EnoughBitrateForAllObservers(uint32_t bitrate,
286 uint32_t sum_min_bitrates) {
287 if (bitrate < sum_min_bitrates)
288 return false;
289
290 uint32_t extra_bitrate_per_observer = (bitrate - sum_min_bitrates) /
291 static_cast<uint32_t>(bitrate_observer_configs_.size());
292 for (const auto& observer_config : bitrate_observer_configs_) {
293 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
294 MinBitrateWithHysteresis(observer_config))
295 return false;
296 }
297 return true;
298 }
207 } // namespace webrtc 299 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/call/bitrate_allocator.h ('k') | webrtc/call/bitrate_allocator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698