blob: f4f085c1b30d3c86902e8676cf857d5d97e59b60 [file] [log] [blame]
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +00001/*
2 * Copyright (c) 2012 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
pbos@webrtc.org2e10b8e2013-07-16 12:54:53 +000012#include "webrtc/modules/bitrate_controller/bitrate_controller_impl.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000013
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +000014#include <algorithm>
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000015#include <utility>
16
pbos@webrtc.org2e10b8e2013-07-16 12:54:53 +000017#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000018
19namespace webrtc {
20
21class RtcpBandwidthObserverImpl : public RtcpBandwidthObserver {
22 public:
23 explicit RtcpBandwidthObserverImpl(BitrateControllerImpl* owner)
24 : owner_(owner) {
25 }
26 virtual ~RtcpBandwidthObserverImpl() {
27 }
28 // Received RTCP REMB or TMMBR.
pbos@webrtc.org4fac8a42013-07-31 15:16:20 +000029 virtual void OnReceivedEstimatedBitrate(const uint32_t bitrate) OVERRIDE {
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000030 owner_->OnReceivedEstimatedBitrate(bitrate);
31 }
32 // Received RTCP receiver block.
33 virtual void OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +000034 const ReportBlockList& report_blocks,
35 uint16_t rtt,
36 int64_t now_ms) OVERRIDE {
37 if (report_blocks.empty())
38 return;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000039
stefan@webrtc.org28a331e2013-09-17 07:49:56 +000040 int fraction_lost_aggregate = 0;
41 int total_number_of_packets = 0;
42
43 // Compute the a weighted average of the fraction loss from all report
44 // blocks.
45 for (ReportBlockList::const_iterator it = report_blocks.begin();
46 it != report_blocks.end(); ++it) {
47 std::map<uint32_t, uint32_t>::iterator seq_num_it =
48 ssrc_to_last_received_extended_high_seq_num_.find(it->sourceSSRC);
49
50 int number_of_packets = 0;
51 if (seq_num_it != ssrc_to_last_received_extended_high_seq_num_.end())
52 number_of_packets = it->extendedHighSeqNum -
53 seq_num_it->second;
54
55 fraction_lost_aggregate += number_of_packets * it->fractionLost;
56 total_number_of_packets += number_of_packets;
57
58 // Update last received for this SSRC.
59 ssrc_to_last_received_extended_high_seq_num_[it->sourceSSRC] =
60 it->extendedHighSeqNum;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000061 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +000062 if (total_number_of_packets == 0)
63 fraction_lost_aggregate = 0;
64 else
65 fraction_lost_aggregate = (fraction_lost_aggregate +
66 total_number_of_packets / 2) / total_number_of_packets;
67 if (fraction_lost_aggregate > 255)
68 return;
69
70 owner_->OnReceivedRtcpReceiverReport(fraction_lost_aggregate, rtt,
71 total_number_of_packets, now_ms);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000072 }
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +000073
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000074 private:
75 std::map<uint32_t, uint32_t> ssrc_to_last_received_extended_high_seq_num_;
76 BitrateControllerImpl* owner_;
77};
78
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +000079class LowRateStrategy {
80 public:
81 LowRateStrategy(
82 SendSideBandwidthEstimation* bandwidth_estimation,
83 BitrateControllerImpl::BitrateObserverConfList* bitrate_observers)
84 : bandwidth_estimation_(bandwidth_estimation),
85 bitrate_observers_(bitrate_observers) {}
86
87 virtual ~LowRateStrategy() {}
88
89 virtual void LowRateAllocation(uint32_t bitrate,
90 uint8_t fraction_loss,
91 uint32_t rtt,
92 uint32_t sum_min_bitrates) = 0;
93
94 protected:
95 SendSideBandwidthEstimation* bandwidth_estimation_;
96 BitrateControllerImpl::BitrateObserverConfList* bitrate_observers_;
97};
98
99class EnforceMinRateStrategy : public LowRateStrategy {
100 public:
101 EnforceMinRateStrategy(
102 SendSideBandwidthEstimation* bandwidth_estimation,
103 BitrateControllerImpl::BitrateObserverConfList* bitrate_observers)
104 : LowRateStrategy(bandwidth_estimation, bitrate_observers) {}
105
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +0000106 void LowRateAllocation(uint32_t bitrate,
107 uint8_t fraction_loss,
108 uint32_t rtt,
109 uint32_t sum_min_bitrates) {
110 // Min bitrate to all observers.
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000111 BitrateControllerImpl::BitrateObserverConfList::iterator it;
112 for (it = bitrate_observers_->begin(); it != bitrate_observers_->end();
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +0000113 ++it) {
114 it->first->OnNetworkChanged(it->second->min_bitrate_, fraction_loss,
115 rtt);
116 }
117 // Set sum of min to current send bitrate.
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000118 bandwidth_estimation_->SetSendBitrate(sum_min_bitrates);
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +0000119 }
120};
121
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000122class NoEnforceMinRateStrategy : public LowRateStrategy {
123 public:
124 NoEnforceMinRateStrategy(
125 SendSideBandwidthEstimation* bandwidth_estimation,
126 BitrateControllerImpl::BitrateObserverConfList* bitrate_observers)
127 : LowRateStrategy(bandwidth_estimation, bitrate_observers) {}
128
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +0000129 void LowRateAllocation(uint32_t bitrate,
130 uint8_t fraction_loss,
131 uint32_t rtt,
132 uint32_t sum_min_bitrates) {
133 // Allocate up to |min_bitrate_| to one observer at a time, until
134 // |bitrate| is depleted.
135 uint32_t remainder = bitrate;
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000136 BitrateControllerImpl::BitrateObserverConfList::iterator it;
137 for (it = bitrate_observers_->begin(); it != bitrate_observers_->end();
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +0000138 ++it) {
139 uint32_t allocation = std::min(remainder, it->second->min_bitrate_);
140 it->first->OnNetworkChanged(allocation, fraction_loss, rtt);
141 remainder -= allocation;
142 }
143 // Set |bitrate| to current send bitrate.
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000144 bandwidth_estimation_->SetSendBitrate(bitrate);
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +0000145 }
146};
147
148BitrateController* BitrateController::CreateBitrateController(
149 bool enforce_min_bitrate) {
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000150 return new BitrateControllerImpl(enforce_min_bitrate);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000151}
152
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000153BitrateControllerImpl::BitrateControllerImpl(bool enforce_min_bitrate)
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000154 : critsect_(CriticalSectionWrapper::CreateCriticalSection()) {
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000155 if (enforce_min_bitrate) {
156 low_rate_strategy_.reset(new EnforceMinRateStrategy(
157 &bandwidth_estimation_, &bitrate_observers_));
158 } else {
159 low_rate_strategy_.reset(new NoEnforceMinRateStrategy(
160 &bandwidth_estimation_, &bitrate_observers_));
161 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000162}
163
164BitrateControllerImpl::~BitrateControllerImpl() {
stefan@webrtc.org1281dc02012-08-13 16:13:09 +0000165 BitrateObserverConfList::iterator it =
pwestin@webrtc.orge9727cd2012-05-03 11:32:25 +0000166 bitrate_observers_.begin();
167 while (it != bitrate_observers_.end()) {
168 delete it->second;
169 bitrate_observers_.erase(it);
170 it = bitrate_observers_.begin();
171 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000172 delete critsect_;
173}
174
175RtcpBandwidthObserver* BitrateControllerImpl::CreateRtcpBandwidthObserver() {
176 return new RtcpBandwidthObserverImpl(this);
177}
178
stefan@webrtc.org1281dc02012-08-13 16:13:09 +0000179BitrateControllerImpl::BitrateObserverConfList::iterator
180BitrateControllerImpl::FindObserverConfigurationPair(const BitrateObserver*
181 observer) {
182 BitrateObserverConfList::iterator it = bitrate_observers_.begin();
183 for (; it != bitrate_observers_.end(); ++it) {
184 if (it->first == observer) {
185 return it;
186 }
187 }
188 return bitrate_observers_.end();
189}
190
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000191void BitrateControllerImpl::SetBitrateObserver(
192 BitrateObserver* observer,
193 const uint32_t start_bitrate,
194 const uint32_t min_bitrate,
195 const uint32_t max_bitrate) {
196 CriticalSectionScoped cs(critsect_);
197
stefan@webrtc.org1281dc02012-08-13 16:13:09 +0000198 BitrateObserverConfList::iterator it = FindObserverConfigurationPair(
199 observer);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000200
201 if (it != bitrate_observers_.end()) {
202 // Update current configuration.
203 it->second->start_bitrate_ = start_bitrate;
204 it->second->min_bitrate_ = min_bitrate;
205 it->second->max_bitrate_ = max_bitrate;
206 } else {
207 // Add new settings.
stefan@webrtc.org1281dc02012-08-13 16:13:09 +0000208 bitrate_observers_.push_back(BitrateObserverConfiguration(observer,
209 new BitrateConfiguration(start_bitrate, min_bitrate, max_bitrate)));
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000210 }
211 uint32_t sum_start_bitrate = 0;
212 uint32_t sum_min_bitrate = 0;
213 uint32_t sum_max_bitrate = 0;
214
215 // Summarize all configurations.
216 for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
217 sum_start_bitrate += it->second->start_bitrate_;
218 sum_min_bitrate += it->second->min_bitrate_;
219 sum_max_bitrate += it->second->max_bitrate_;
220 }
221 // Only change start bitrate if we have exactly one observer. By definition
222 // you can only have one start bitrate, once we have our first estimate we
223 // will adapt from there.
224 if (bitrate_observers_.size() == 1) {
225 bandwidth_estimation_.SetSendBitrate(sum_start_bitrate);
226 }
227 bandwidth_estimation_.SetMinMaxBitrate(sum_min_bitrate,
228 sum_max_bitrate);
229}
230
231void BitrateControllerImpl::RemoveBitrateObserver(BitrateObserver* observer) {
232 CriticalSectionScoped cs(critsect_);
stefan@webrtc.org1281dc02012-08-13 16:13:09 +0000233 BitrateObserverConfList::iterator it = FindObserverConfigurationPair(
234 observer);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000235 if (it != bitrate_observers_.end()) {
236 delete it->second;
237 bitrate_observers_.erase(it);
238 }
239}
240
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000241void BitrateControllerImpl::EnforceMinBitrate(bool enforce_min_bitrate) {
242 CriticalSectionScoped cs(critsect_);
243 if (enforce_min_bitrate) {
244 low_rate_strategy_.reset(new EnforceMinRateStrategy(
245 &bandwidth_estimation_, &bitrate_observers_));
246 } else {
247 low_rate_strategy_.reset(new NoEnforceMinRateStrategy(
248 &bandwidth_estimation_, &bitrate_observers_));
249 }
250}
251
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000252void BitrateControllerImpl::SetBweMinBitrate(uint32_t min_bitrate) {
253 CriticalSectionScoped cs(critsect_);
254 bandwidth_estimation_.SetMinBitrate(min_bitrate);
255}
256
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000257void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) {
258 uint32_t new_bitrate = 0;
259 uint8_t fraction_lost = 0;
260 uint16_t rtt = 0;
261 CriticalSectionScoped cs(critsect_);
262 if (bandwidth_estimation_.UpdateBandwidthEstimate(bitrate,
263 &new_bitrate,
264 &fraction_lost,
265 &rtt)) {
266 OnNetworkChanged(new_bitrate, fraction_lost, rtt);
267 }
268}
269
270void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
271 const uint8_t fraction_loss,
272 const uint32_t rtt,
273 const int number_of_packets,
274 const uint32_t now_ms) {
275 uint32_t new_bitrate = 0;
276 uint8_t loss = fraction_loss;
277 CriticalSectionScoped cs(critsect_);
278 if (bandwidth_estimation_.UpdatePacketLoss(number_of_packets, rtt, now_ms,
279 &loss, &new_bitrate)) {
280 OnNetworkChanged(new_bitrate, loss, rtt);
281 }
282}
283
284// We have the lock here.
285void BitrateControllerImpl::OnNetworkChanged(const uint32_t bitrate,
286 const uint8_t fraction_loss,
287 const uint32_t rtt) {
288 // Sanity check.
289 uint32_t number_of_observers = bitrate_observers_.size();
290 if (number_of_observers == 0) {
291 return;
292 }
293 uint32_t sum_min_bitrates = 0;
stefan@webrtc.org1281dc02012-08-13 16:13:09 +0000294 BitrateObserverConfList::iterator it;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000295 for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
296 sum_min_bitrates += it->second->min_bitrate_;
297 }
298 if (bitrate <= sum_min_bitrates) {
henrik.lundin@webrtc.orgb56d0e32013-10-24 09:24:06 +0000299 return low_rate_strategy_->LowRateAllocation(bitrate, fraction_loss, rtt,
300 sum_min_bitrates);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000301 }
302 uint32_t bitrate_per_observer = (bitrate - sum_min_bitrates) /
303 number_of_observers;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000304 // Use map to sort list based on max bitrate.
305 ObserverSortingMap list_max_bitrates;
306 for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
307 list_max_bitrates.insert(std::pair<uint32_t, ObserverConfiguration*>(
308 it->second->max_bitrate_,
309 new ObserverConfiguration(it->first, it->second->min_bitrate_)));
310 }
311 ObserverSortingMap::iterator max_it = list_max_bitrates.begin();
312 while (max_it != list_max_bitrates.end()) {
313 number_of_observers--;
314 uint32_t observer_allowance = max_it->second->min_bitrate_ +
315 bitrate_per_observer;
316 if (max_it->first < observer_allowance) {
317 // We have more than enough for this observer.
318 // Carry the remainder forward.
319 uint32_t remainder = observer_allowance - max_it->first;
320 if (number_of_observers != 0) {
321 bitrate_per_observer += remainder / number_of_observers;
322 }
323 max_it->second->observer_->OnNetworkChanged(max_it->first, fraction_loss,
324 rtt);
325 } else {
326 max_it->second->observer_->OnNetworkChanged(observer_allowance,
327 fraction_loss, rtt);
328 }
329 delete max_it->second;
330 list_max_bitrates.erase(max_it);
331 // Prepare next iteration.
332 max_it = list_max_bitrates.begin();
333 }
334}
pwestin@webrtc.orga2cd7322012-04-23 08:32:47 +0000335
336bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
337 return bandwidth_estimation_.AvailableBandwidth(bandwidth);
338}
henrik.lundin@webrtc.org29dd0de2013-10-21 14:00:01 +0000339
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000340} // namespace webrtc