blob: 4a045d9d89fb25856291b229e15b57c9b74fa683 [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
andresp@webrtc.org16b75c22014-03-21 14:00:51 +000021class BitrateControllerImpl::RtcpBandwidthObserverImpl
22 : public RtcpBandwidthObserver {
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000023 public:
24 explicit RtcpBandwidthObserverImpl(BitrateControllerImpl* owner)
25 : owner_(owner) {
26 }
27 virtual ~RtcpBandwidthObserverImpl() {
28 }
29 // Received RTCP REMB or TMMBR.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000030 void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000031 owner_->OnReceivedEstimatedBitrate(bitrate);
32 }
33 // Received RTCP receiver block.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000034 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
35 int64_t rtt,
36 int64_t now_ms) override {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +000037 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.org29dd0de2013-10-21 14:00:01 +000079BitrateController* BitrateController::CreateBitrateController(
andresp@webrtc.org44caf012014-03-26 21:00:21 +000080 Clock* clock,
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000081 BitrateObserver* observer) {
82 return new BitrateControllerImpl(clock, observer);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000083}
84
sprang@webrtc.org9b791972014-12-18 11:53:59 +000085BitrateControllerImpl::BitrateControllerImpl(Clock* clock,
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000086 BitrateObserver* observer)
andresp@webrtc.org44caf012014-03-26 21:00:21 +000087 : clock_(clock),
stefan@webrtc.org792f1a12015-03-04 12:24:26 +000088 observer_(observer),
andresp@webrtc.org44caf012014-03-26 21:00:21 +000089 last_bitrate_update_ms_(clock_->TimeInMilliseconds()),
solenberg@webrtc.org4e656022014-03-26 14:32:47 +000090 bandwidth_estimation_(),
andresp@webrtc.org44caf012014-03-26 21:00:21 +000091 reserved_bitrate_bps_(0),
92 last_bitrate_bps_(0),
solenberg@webrtc.org4e656022014-03-26 14:32:47 +000093 last_fraction_loss_(0),
andresp@webrtc.org44caf012014-03-26 21:00:21 +000094 last_rtt_ms_(0),
sprang@webrtc.org8bd2f402015-03-16 14:11:21 +000095 last_reserved_bitrate_bps_(0) {
Stefan Holmere5904162015-03-26 11:11:06 +010096 // This calls the observer_, which means that the observer provided by the
97 // user must be ready to accept a bitrate update when it constructs the
98 // controller. We do this to avoid having to keep synchronized initial values
99 // in both the controller and the allocator.
100 MaybeTriggerOnNetworkChanged();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000101}
102
103RtcpBandwidthObserver* BitrateControllerImpl::CreateRtcpBandwidthObserver() {
104 return new RtcpBandwidthObserverImpl(this);
105}
106
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000107void BitrateControllerImpl::SetStartBitrate(int start_bitrate_bps) {
Stefan Holmere5904162015-03-26 11:11:06 +0100108 {
sprang867fb522015-08-03 04:38:41 -0700109 rtc::CritScope cs(&critsect_);
Stefan Holmere5904162015-03-26 11:11:06 +0100110 bandwidth_estimation_.SetSendBitrate(start_bitrate_bps);
111 }
112 MaybeTriggerOnNetworkChanged();
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000113}
114
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000115void BitrateControllerImpl::SetMinMaxBitrate(int min_bitrate_bps,
116 int max_bitrate_bps) {
Stefan Holmere5904162015-03-26 11:11:06 +0100117 {
sprang867fb522015-08-03 04:38:41 -0700118 rtc::CritScope cs(&critsect_);
Stefan Holmere5904162015-03-26 11:11:06 +0100119 bandwidth_estimation_.SetMinMaxBitrate(min_bitrate_bps, max_bitrate_bps);
120 }
121 MaybeTriggerOnNetworkChanged();
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000122}
123
solenberg@webrtc.org4e656022014-03-26 14:32:47 +0000124void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000125 {
sprang867fb522015-08-03 04:38:41 -0700126 rtc::CritScope cs(&critsect_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000127 reserved_bitrate_bps_ = reserved_bitrate_bps;
128 }
solenberg@webrtc.org4e656022014-03-26 14:32:47 +0000129 MaybeTriggerOnNetworkChanged();
130}
131
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000132void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000133 {
sprang867fb522015-08-03 04:38:41 -0700134 rtc::CritScope cs(&critsect_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000135 bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
sprang@webrtc.org9b791972014-12-18 11:53:59 +0000136 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000137 MaybeTriggerOnNetworkChanged();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000138}
139
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +0000140int64_t BitrateControllerImpl::TimeUntilNextProcess() {
141 const int64_t kBitrateControllerUpdateIntervalMs = 25;
sprang867fb522015-08-03 04:38:41 -0700142 rtc::CritScope cs(&critsect_);
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +0000143 int64_t time_since_update_ms =
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000144 clock_->TimeInMilliseconds() - last_bitrate_update_ms_;
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +0000145 return std::max<int64_t>(
146 kBitrateControllerUpdateIntervalMs - time_since_update_ms, 0);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000147}
148
149int32_t BitrateControllerImpl::Process() {
150 if (TimeUntilNextProcess() > 0)
151 return 0;
152 {
sprang867fb522015-08-03 04:38:41 -0700153 rtc::CritScope cs(&critsect_);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000154 bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds());
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000155 }
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000156 MaybeTriggerOnNetworkChanged();
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000157 last_bitrate_update_ms_ = clock_->TimeInMilliseconds();
158 return 0;
159}
160
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000161void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000162 uint8_t fraction_loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000163 int64_t rtt,
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000164 int number_of_packets,
165 int64_t now_ms) {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000166 {
sprang867fb522015-08-03 04:38:41 -0700167 rtc::CritScope cs(&critsect_);
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000168 bandwidth_estimation_.UpdateReceiverBlock(fraction_loss, rtt,
169 number_of_packets, now_ms);
170 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000171 MaybeTriggerOnNetworkChanged();
172}
173
174void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() {
175 uint32_t bitrate;
176 uint8_t fraction_loss;
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000177 int64_t rtt;
Stefan Holmere5904162015-03-26 11:11:06 +0100178 if (GetNetworkParameters(&bitrate, &fraction_loss, &rtt))
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000179 observer_->OnNetworkChanged(bitrate, fraction_loss, rtt);
andresp@webrtc.org16b75c22014-03-21 14:00:51 +0000180}
181
Stefan Holmere5904162015-03-26 11:11:06 +0100182bool BitrateControllerImpl::GetNetworkParameters(uint32_t* bitrate,
183 uint8_t* fraction_loss,
184 int64_t* rtt) {
sprang867fb522015-08-03 04:38:41 -0700185 rtc::CritScope cs(&critsect_);
Stefan Holmere5904162015-03-26 11:11:06 +0100186 int current_bitrate;
187 bandwidth_estimation_.CurrentEstimate(&current_bitrate, fraction_loss, rtt);
188 *bitrate = current_bitrate;
189 *bitrate -= std::min(*bitrate, reserved_bitrate_bps_);
190 *bitrate =
191 std::max<uint32_t>(*bitrate, bandwidth_estimation_.GetMinBitrate());
192
193 bool new_bitrate = false;
194 if (*bitrate != last_bitrate_bps_ || *fraction_loss != last_fraction_loss_ ||
195 *rtt != last_rtt_ms_ ||
196 last_reserved_bitrate_bps_ != reserved_bitrate_bps_) {
197 last_bitrate_bps_ = *bitrate;
198 last_fraction_loss_ = *fraction_loss;
199 last_rtt_ms_ = *rtt;
200 last_reserved_bitrate_bps_ = reserved_bitrate_bps_;
201 new_bitrate = true;
202 }
203 return new_bitrate;
204}
205
pwestin@webrtc.orga2cd7322012-04-23 08:32:47 +0000206bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const {
sprang867fb522015-08-03 04:38:41 -0700207 rtc::CritScope cs(&critsect_);
Stefan Holmere5904162015-03-26 11:11:06 +0100208 int bitrate;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000209 uint8_t fraction_loss;
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000210 int64_t rtt;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000211 bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
Stefan Holmere5904162015-03-26 11:11:06 +0100212 if (bitrate > 0) {
213 bitrate = bitrate - std::min<int>(bitrate, reserved_bitrate_bps_);
214 bitrate = std::max(bitrate, bandwidth_estimation_.GetMinBitrate());
215 *bandwidth = bitrate;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000216 return true;
217 }
218 return false;
pwestin@webrtc.orga2cd7322012-04-23 08:32:47 +0000219}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000220} // namespace webrtc