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

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

Issue 2117493002: Auto pause video streams based on encoder target bitrate. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase Created 4 years, 5 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/base/logging.h"
18 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.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"
19 22
20 namespace webrtc { 23 namespace webrtc {
21 24
22 // Allow packets to be transmitted in up to 2 times max video bitrate if the 25 // Allow packets to be transmitted in up to 2 times max video bitrate if the
23 // bandwidth estimate allows it. 26 // bandwidth estimate allows it.
24 const int kTransmissionMaxBitrateMultiplier = 2; 27 const int kTransmissionMaxBitrateMultiplier = 2;
25 const int kDefaultBitrateBps = 300000; 28 const int kDefaultBitrateBps = 300000;
26 29
27 // Require a bitrate increase of max(10%, 20kbps) to resume paused streams. 30 // Require a bitrate increase of max(10%, 20kbps) to resume paused streams.
28 const double kToggleFactor = 0.1; 31 const double kToggleFactor = 0.1;
29 const uint32_t kMinToggleBitrateBps = 20000; 32 const uint32_t kMinToggleBitrateBps = 20000;
30 33
34 const int64_t kBweLogIntervalMs = 5000;
35
36 namespace {
37
38 double MediaRatio(uint32_t allocated_bitrate, uint32_t protection_bitrate) {
39 RTC_DCHECK_GT(allocated_bitrate, 0u);
40 if (protection_bitrate == 0)
41 return 1.0;
42
43 uint32_t media_bitrate = allocated_bitrate - protection_bitrate;
44 return media_bitrate / static_cast<double>(allocated_bitrate);
45 }
46 } // namespace
47
31 BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer) 48 BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
32 : limit_observer_(limit_observer), 49 : limit_observer_(limit_observer),
33 bitrate_observer_configs_(), 50 bitrate_observer_configs_(),
34 last_bitrate_bps_(kDefaultBitrateBps), 51 last_bitrate_bps_(kDefaultBitrateBps),
35 last_non_zero_bitrate_bps_(kDefaultBitrateBps), 52 last_non_zero_bitrate_bps_(kDefaultBitrateBps),
36 last_fraction_loss_(0), 53 last_fraction_loss_(0),
37 last_rtt_(0) {} 54 last_rtt_(0),
55 num_pause_events_(0),
56 clock_(Clock::GetRealTimeClock()),
57 last_bwe_log_time_(0) {}
58
59 BitrateAllocator::~BitrateAllocator() {
60 RTC_LOGGED_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
61 num_pause_events_);
62 }
38 63
39 void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps, 64 void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
40 uint8_t fraction_loss, 65 uint8_t fraction_loss,
41 int64_t rtt) { 66 int64_t rtt) {
42 rtc::CritScope lock(&crit_sect_); 67 rtc::CritScope lock(&crit_sect_);
43 last_bitrate_bps_ = target_bitrate_bps; 68 last_bitrate_bps_ = target_bitrate_bps;
44 last_non_zero_bitrate_bps_ = 69 last_non_zero_bitrate_bps_ =
45 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_; 70 target_bitrate_bps > 0 ? target_bitrate_bps : last_non_zero_bitrate_bps_;
46 last_fraction_loss_ = fraction_loss; 71 last_fraction_loss_ = fraction_loss;
47 last_rtt_ = rtt; 72 last_rtt_ = rtt;
48 73
74 // Periodically log the incoming BWE.
75 int64_t now = clock_->TimeInMilliseconds();
76 if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
77 LOG(LS_INFO) << "Current BWE " << target_bitrate_bps;
78 last_bwe_log_time_ = now;
79 }
80
49 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps); 81 ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
50 for (const auto& kv : allocation) { 82
51 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); 83 for (auto& config : bitrate_observer_configs_) {
84 uint32_t allocated_bitrate = allocation[config.observer];
85 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
86 allocated_bitrate, last_fraction_loss_, last_rtt_);
87
88 if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
89 if (target_bitrate_bps > 0)
90 ++num_pause_events_;
91 // The protection bitrate is an estimate based on the ratio between media
92 // and protection used before this observer was muted.
93 uint32_t predicted_protection_bps =
94 (1.0 - config.media_ratio) * config.min_bitrate_bps;
95 LOG(LS_INFO) << "Pausing observer " << config.observer
96 << " with configured min bitrate " << config.min_bitrate_bps
97 << " and current estimate of " << target_bitrate_bps
98 << " and protection bitrate " << predicted_protection_bps;
99 } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
100 if (target_bitrate_bps > 0)
101 ++num_pause_events_;
102 LOG(LS_INFO) << "Resuming observer " << config.observer
103 << ", configured min bitrate " << config.min_bitrate_bps
104 << ", current allocation " << allocated_bitrate
105 << " and protection bitrate " << protection_bitrate;
106 }
107
108 // Only update the media ratio if the observer got an allocation.
109 if (allocated_bitrate > 0)
110 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
111 config.allocated_bitrate_bps = allocated_bitrate;
52 } 112 }
53 last_allocation_ = allocation;
54 } 113 }
55 114
56 void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer, 115 void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
57 uint32_t min_bitrate_bps, 116 uint32_t min_bitrate_bps,
58 uint32_t max_bitrate_bps, 117 uint32_t max_bitrate_bps,
59 uint32_t pad_up_bitrate_bps, 118 uint32_t pad_up_bitrate_bps,
60 bool enforce_min_bitrate) { 119 bool enforce_min_bitrate) {
61 rtc::CritScope lock(&crit_sect_); 120 rtc::CritScope lock(&crit_sect_);
62 auto it = FindObserverConfig(observer); 121 auto it = FindObserverConfig(observer);
63 122
64 // Update settings if the observer already exists, create a new one otherwise. 123 // Update settings if the observer already exists, create a new one otherwise.
65 if (it != bitrate_observer_configs_.end()) { 124 if (it != bitrate_observer_configs_.end()) {
66 it->min_bitrate_bps = min_bitrate_bps; 125 it->min_bitrate_bps = min_bitrate_bps;
67 it->max_bitrate_bps = max_bitrate_bps; 126 it->max_bitrate_bps = max_bitrate_bps;
68 it->pad_up_bitrate_bps = pad_up_bitrate_bps; 127 it->pad_up_bitrate_bps = pad_up_bitrate_bps;
69 it->enforce_min_bitrate = enforce_min_bitrate; 128 it->enforce_min_bitrate = enforce_min_bitrate;
70 } else { 129 } else {
71 bitrate_observer_configs_.push_back( 130 bitrate_observer_configs_.push_back(
72 ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps, 131 ObserverConfig(observer, min_bitrate_bps, max_bitrate_bps,
73 pad_up_bitrate_bps, enforce_min_bitrate)); 132 pad_up_bitrate_bps, enforce_min_bitrate));
74 } 133 }
75 134
76 ObserverAllocation allocation; 135 ObserverAllocation allocation;
77 if (last_bitrate_bps_ > 0) { 136 if (last_bitrate_bps_ > 0) {
78 // Calculate a new allocation and update all observers. 137 // Calculate a new allocation and update all observers.
79 allocation = AllocateBitrates(last_bitrate_bps_); 138 allocation = AllocateBitrates(last_bitrate_bps_);
80 for (const auto& kv : allocation) 139 for (auto& config : bitrate_observer_configs_) {
81 kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_); 140 uint32_t allocated_bitrate = allocation[config.observer];
141 uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
142 allocated_bitrate, last_fraction_loss_, last_rtt_);
143 config.allocated_bitrate_bps = allocated_bitrate;
144 if (allocated_bitrate > 0)
145 config.media_ratio = MediaRatio(allocated_bitrate, protection_bitrate);
146 }
82 } else { 147 } else {
83 // Currently, an encoder is not allowed to produce frames. 148 // Currently, an encoder is not allowed to produce frames.
84 // But we still have to return the initial config bitrate + let the 149 // But we still have to return the initial config bitrate + let the
85 // observer know that it can not produce frames. 150 // observer know that it can not produce frames.
86 allocation = AllocateBitrates(last_non_zero_bitrate_bps_); 151 allocation = AllocateBitrates(last_non_zero_bitrate_bps_);
87 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_); 152 observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_);
88 } 153 }
89 UpdateAllocationLimits(); 154 UpdateAllocationLimits();
90
91 last_allocation_ = allocation;
92 } 155 }
93 156
94 void BitrateAllocator::UpdateAllocationLimits() { 157 void BitrateAllocator::UpdateAllocationLimits() {
95 uint32_t total_requested_padding_bitrate = 0; 158 uint32_t total_requested_padding_bitrate = 0;
96 uint32_t total_requested_min_bitrate = 0; 159 uint32_t total_requested_min_bitrate = 0;
97 160
98 { 161 {
99 rtc::CritScope lock(&crit_sect_); 162 rtc::CritScope lock(&crit_sect_);
100 for (const auto& config : bitrate_observer_configs_) { 163 for (const auto& config : bitrate_observer_configs_) {
101 if (config.enforce_min_bitrate) { 164 if (config.enforce_min_bitrate) {
(...skipping 13 matching lines...) Expand all
115 auto it = FindObserverConfig(observer); 178 auto it = FindObserverConfig(observer);
116 if (it != bitrate_observer_configs_.end()) { 179 if (it != bitrate_observer_configs_.end()) {
117 bitrate_observer_configs_.erase(it); 180 bitrate_observer_configs_.erase(it);
118 } 181 }
119 } 182 }
120 UpdateAllocationLimits(); 183 UpdateAllocationLimits();
121 } 184 }
122 185
123 int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) { 186 int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
124 rtc::CritScope lock(&crit_sect_); 187 rtc::CritScope lock(&crit_sect_);
125 const auto& it = last_allocation_.find(observer); 188 const auto& it = FindObserverConfig(observer);
126 if (it != last_allocation_.end()) 189 if (it == bitrate_observer_configs_.end()) {
127 return it->second; 190 // This observer hasn't been added yet, just give it its fair share.
128 191 return last_non_zero_bitrate_bps_ /
129 // This is a new observer that has not yet been started. Assume that if it is 192 static_cast<int>((bitrate_observer_configs_.size() + 1));
130 // added, all observers would split the available bitrate evenly. 193 } else if (it->allocated_bitrate_bps == -1) {
131 return last_non_zero_bitrate_bps_ / 194 // This observer hasn't received an allocation yet, so do the same.
132 static_cast<int>((bitrate_observer_configs_.size() + 1)); 195 return last_non_zero_bitrate_bps_ /
196 static_cast<int>(bitrate_observer_configs_.size());
197 } else {
198 // This observer already has an allocation.
199 return it->allocated_bitrate_bps;
200 }
133 } 201 }
134 202
135 BitrateAllocator::ObserverConfigList::iterator 203 BitrateAllocator::ObserverConfigs::iterator
136 BitrateAllocator::FindObserverConfig( 204 BitrateAllocator::FindObserverConfig(
137 const BitrateAllocatorObserver* observer) { 205 const BitrateAllocatorObserver* observer) {
138 for (auto it = bitrate_observer_configs_.begin(); 206 for (auto it = bitrate_observer_configs_.begin();
139 it != bitrate_observer_configs_.end(); ++it) { 207 it != bitrate_observer_configs_.end(); ++it) {
140 if (it->observer == observer) 208 if (it->observer == observer)
141 return it; 209 return it;
142 } 210 }
143 return bitrate_observer_configs_.end(); 211 return bitrate_observer_configs_.end();
144 } 212 }
145 213
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 remaining_bitrate -= allocated_bitrate; 263 remaining_bitrate -= allocated_bitrate;
196 } 264 }
197 265
198 // Allocate bitrate to all previously active streams. 266 // Allocate bitrate to all previously active streams.
199 if (remaining_bitrate > 0) { 267 if (remaining_bitrate > 0) {
200 for (const auto& observer_config : bitrate_observer_configs_) { 268 for (const auto& observer_config : bitrate_observer_configs_) {
201 if (observer_config.enforce_min_bitrate || 269 if (observer_config.enforce_min_bitrate ||
202 LastAllocatedBitrate(observer_config) == 0) 270 LastAllocatedBitrate(observer_config) == 0)
203 continue; 271 continue;
204 272
205 if (remaining_bitrate >= observer_config.min_bitrate_bps) { 273 uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
206 allocation[observer_config.observer] = observer_config.min_bitrate_bps; 274 if (remaining_bitrate >= required_bitrate) {
207 remaining_bitrate -= observer_config.min_bitrate_bps; 275 allocation[observer_config.observer] = required_bitrate;
276 remaining_bitrate -= required_bitrate;
208 } 277 }
209 } 278 }
210 } 279 }
211 280
212 // Allocate bitrate to previously paused streams. 281 // Allocate bitrate to previously paused streams.
213 if (remaining_bitrate > 0) { 282 if (remaining_bitrate > 0) {
214 for (const auto& observer_config : bitrate_observer_configs_) { 283 for (const auto& observer_config : bitrate_observer_configs_) {
215 if (LastAllocatedBitrate(observer_config) != 0) 284 if (LastAllocatedBitrate(observer_config) != 0)
216 continue; 285 continue;
217 286
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 bitrate -= observer_config.max_bitrate_bps; 325 bitrate -= observer_config.max_bitrate_bps;
257 } 326 }
258 DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier, 327 DistributeBitrateEvenly(bitrate, true, kTransmissionMaxBitrateMultiplier,
259 &allocation); 328 &allocation);
260 return allocation; 329 return allocation;
261 } 330 }
262 331
263 uint32_t BitrateAllocator::LastAllocatedBitrate( 332 uint32_t BitrateAllocator::LastAllocatedBitrate(
264 const ObserverConfig& observer_config) { 333 const ObserverConfig& observer_config) {
265 334
266 const auto& it = last_allocation_.find(observer_config.observer);
267 if (it != last_allocation_.end())
268 return it->second;
269
270 // Return the configured minimum bitrate for newly added observers, to avoid 335 // Return the configured minimum bitrate for newly added observers, to avoid
271 // requiring an extra high bitrate for the observer to get an allocated 336 // requiring an extra high bitrate for the observer to get an allocated
272 // bitrate. 337 // bitrate.
273 return observer_config.min_bitrate_bps; 338 return observer_config.allocated_bitrate_bps == -1 ?
339 observer_config.min_bitrate_bps : observer_config.allocated_bitrate_bps;
274 } 340 }
275 341
276 uint32_t BitrateAllocator::MinBitrateWithHysteresis( 342 uint32_t BitrateAllocator::MinBitrateWithHysteresis(
277 const ObserverConfig& observer_config) { 343 const ObserverConfig& observer_config) {
278 uint32_t min_bitrate = observer_config.min_bitrate_bps; 344 uint32_t min_bitrate = observer_config.min_bitrate_bps;
279 if (LastAllocatedBitrate(observer_config) == 0) { 345 if (LastAllocatedBitrate(observer_config) == 0) {
280 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate), 346 min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
281 kMinToggleBitrateBps); 347 kMinToggleBitrateBps);
282 } 348 }
349 // Account for protection bitrate used by this observer in the previous
350 // allocation.
351 // Note: the ratio will only be updated when the stream is active, meaning a
352 // paused stream won't get any ratio updates. This might lead to waiting a bit
353 // longer than necessary if the network condition improves, but this is to
354 // avoid too much toggling.
355 if (observer_config.media_ratio > 0.0 && observer_config.media_ratio < 1.0)
356 min_bitrate += min_bitrate * (1.0 - observer_config.media_ratio);
357
283 return min_bitrate; 358 return min_bitrate;
284 } 359 }
285 360
286 void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate, 361 void BitrateAllocator::DistributeBitrateEvenly(uint32_t bitrate,
287 bool include_zero_allocations, 362 bool include_zero_allocations,
288 int max_multiplier, 363 int max_multiplier,
289 ObserverAllocation* allocation) { 364 ObserverAllocation* allocation) {
290 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size()); 365 RTC_DCHECK_EQ(allocation->size(), bitrate_observer_configs_.size());
291 366
292 ObserverSortingMap list_max_bitrates; 367 ObserverSortingMap list_max_bitrates;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 uint32_t extra_bitrate_per_observer = (bitrate - sum_min_bitrates) / 400 uint32_t extra_bitrate_per_observer = (bitrate - sum_min_bitrates) /
326 static_cast<uint32_t>(bitrate_observer_configs_.size()); 401 static_cast<uint32_t>(bitrate_observer_configs_.size());
327 for (const auto& observer_config : bitrate_observer_configs_) { 402 for (const auto& observer_config : bitrate_observer_configs_) {
328 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer < 403 if (observer_config.min_bitrate_bps + extra_bitrate_per_observer <
329 MinBitrateWithHysteresis(observer_config)) 404 MinBitrateWithHysteresis(observer_config))
330 return false; 405 return false;
331 } 406 }
332 return true; 407 return true;
333 } 408 }
334 } // namespace webrtc 409 } // 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