blob: 2905e6c8dd31567daecd832d60d27c91716ebabb [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/bitrate_controller/send_side_bandwidth_estimation.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000012
jbauchf91e6d02016-01-24 23:05:21 -080013#include <algorithm>
Piotr Tworek5e4833c2017-12-12 12:09:31 +010014#include <cstdio>
Stefan Holmer9c79ed92017-03-31 15:53:27 +020015#include <limits>
16#include <string>
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000017
Karl Wiberg918f50c2018-07-05 11:40:33 +020018#include "absl/memory/memory.h"
Danil Chapovalov83bbe912019-08-07 12:24:53 +020019#include "api/rtc_event_log/rtc_event_log.h"
Yves Gerey988cc082018-10-23 12:03:01 +020020#include "logging/rtc_event_log/events/rtc_event.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020021#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
23#include "rtc_base/checks.h"
24#include "rtc_base/logging.h"
25#include "system_wrappers/include/field_trial.h"
26#include "system_wrappers/include/metrics.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000027
28namespace webrtc {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000029namespace {
Sebastian Jansson7c1744d2018-10-08 11:00:50 +020030constexpr TimeDelta kBweIncreaseInterval = TimeDelta::Millis<1000>();
31constexpr TimeDelta kBweDecreaseInterval = TimeDelta::Millis<300>();
32constexpr TimeDelta kStartPhase = TimeDelta::Millis<2000>();
33constexpr TimeDelta kBweConverganceTime = TimeDelta::Millis<20000>();
34constexpr int kLimitNumPackets = 20;
35constexpr DataRate kDefaultMaxBitrate = DataRate::BitsPerSec<1000000000>();
36constexpr TimeDelta kLowBitrateLogPeriod = TimeDelta::Millis<10000>();
37constexpr TimeDelta kRtcEventLogPeriod = TimeDelta::Millis<5000>();
Stefan Holmer52200d02016-09-20 14:14:23 +020038// Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals.
Sebastian Jansson7c1744d2018-10-08 11:00:50 +020039constexpr TimeDelta kMaxRtcpFeedbackInterval = TimeDelta::Millis<5000>();
40constexpr int kFeedbackTimeoutIntervals = 3;
41constexpr TimeDelta kTimeoutInterval = TimeDelta::Millis<1000>();
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000042
Sebastian Jansson7c1744d2018-10-08 11:00:50 +020043constexpr float kDefaultLowLossThreshold = 0.02f;
44constexpr float kDefaultHighLossThreshold = 0.1f;
45constexpr DataRate kDefaultBitrateThreshold = DataRate::Zero();
Stefan Holmer9c79ed92017-03-31 15:53:27 +020046
stefan@webrtc.org474e36e2015-01-19 15:44:47 +000047struct UmaRampUpMetric {
48 const char* metric_name;
49 int bitrate_kbps;
50};
51
52const UmaRampUpMetric kUmaRampupMetrics[] = {
53 {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500},
54 {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000},
55 {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}};
56const size_t kNumUmaRampupMetrics =
57 sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]);
58
Stefan Holmer9c79ed92017-03-31 15:53:27 +020059const char kBweLosExperiment[] = "WebRTC-BweLossExperiment";
60
61bool BweLossExperimentIsEnabled() {
62 std::string experiment_string =
63 webrtc::field_trial::FindFullName(kBweLosExperiment);
64 // The experiment is enabled iff the field trial string begins with "Enabled".
65 return experiment_string.find("Enabled") == 0;
66}
67
68bool ReadBweLossExperimentParameters(float* low_loss_threshold,
69 float* high_loss_threshold,
70 uint32_t* bitrate_threshold_kbps) {
71 RTC_DCHECK(low_loss_threshold);
72 RTC_DCHECK(high_loss_threshold);
73 RTC_DCHECK(bitrate_threshold_kbps);
74 std::string experiment_string =
75 webrtc::field_trial::FindFullName(kBweLosExperiment);
76 int parsed_values =
77 sscanf(experiment_string.c_str(), "Enabled-%f,%f,%u", low_loss_threshold,
78 high_loss_threshold, bitrate_threshold_kbps);
79 if (parsed_values == 3) {
80 RTC_CHECK_GT(*low_loss_threshold, 0.0f)
81 << "Loss threshold must be greater than 0.";
82 RTC_CHECK_LE(*low_loss_threshold, 1.0f)
83 << "Loss threshold must be less than or equal to 1.";
84 RTC_CHECK_GT(*high_loss_threshold, 0.0f)
85 << "Loss threshold must be greater than 0.";
86 RTC_CHECK_LE(*high_loss_threshold, 1.0f)
87 << "Loss threshold must be less than or equal to 1.";
88 RTC_CHECK_LE(*low_loss_threshold, *high_loss_threshold)
89 << "The low loss threshold must be less than or equal to the high loss "
90 "threshold.";
91 RTC_CHECK_GE(*bitrate_threshold_kbps, 0)
92 << "Bitrate threshold can't be negative.";
93 RTC_CHECK_LT(*bitrate_threshold_kbps,
94 std::numeric_limits<int>::max() / 1000)
95 << "Bitrate must be smaller enough to avoid overflows.";
96 return true;
97 }
Mirko Bonadei675513b2017-11-09 11:09:25 +010098 RTC_LOG(LS_WARNING) << "Failed to parse parameters for BweLossExperiment "
99 "experiment from field trial string. Using default.";
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200100 *low_loss_threshold = kDefaultLowLossThreshold;
101 *high_loss_threshold = kDefaultHighLossThreshold;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200102 *bitrate_threshold_kbps = kDefaultBitrateThreshold.kbps();
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200103 return false;
104}
jbauchf91e6d02016-01-24 23:05:21 -0800105} // namespace
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000106
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100107LinkCapacityTracker::LinkCapacityTracker()
108 : tracking_rate("rate", TimeDelta::seconds(10)) {
109 ParseFieldTrial({&tracking_rate},
110 field_trial::FindFullName("WebRTC-Bwe-LinkCapacity"));
111}
112
113LinkCapacityTracker::~LinkCapacityTracker() {}
114
Florent Castelli1067d312019-09-04 14:58:32 +0200115void LinkCapacityTracker::OnOveruse(DataRate delay_based_bitrate,
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100116 Timestamp at_time) {
117 capacity_estimate_bps_ =
Florent Castelli1067d312019-09-04 14:58:32 +0200118 std::min(capacity_estimate_bps_, delay_based_bitrate.bps<double>());
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100119 last_link_capacity_update_ = at_time;
120}
121
122void LinkCapacityTracker::OnStartingRate(DataRate start_rate) {
123 if (last_link_capacity_update_.IsInfinite())
124 capacity_estimate_bps_ = start_rate.bps<double>();
125}
126
127void LinkCapacityTracker::OnRateUpdate(DataRate acknowledged,
128 Timestamp at_time) {
129 if (acknowledged.bps() > capacity_estimate_bps_) {
130 TimeDelta delta = at_time - last_link_capacity_update_;
131 double alpha = delta.IsFinite() ? exp(-(delta / tracking_rate.Get())) : 0;
132 capacity_estimate_bps_ = alpha * capacity_estimate_bps_ +
133 (1 - alpha) * acknowledged.bps<double>();
134 }
135 last_link_capacity_update_ = at_time;
136}
137
138void LinkCapacityTracker::OnRttBackoff(DataRate backoff_rate,
139 Timestamp at_time) {
140 capacity_estimate_bps_ =
141 std::min(capacity_estimate_bps_, backoff_rate.bps<double>());
142 last_link_capacity_update_ = at_time;
143}
144
145DataRate LinkCapacityTracker::estimate() const {
146 return DataRate::bps(capacity_estimate_bps_);
147}
148
Sebastian Jansson24643482018-11-14 14:19:45 +0100149RttBasedBackoff::RttBasedBackoff()
150 : rtt_limit_("limit", TimeDelta::PlusInfinity()),
151 drop_fraction_("fraction", 0.5),
152 drop_interval_("interval", TimeDelta::ms(300)),
153 persist_on_route_change_("persist"),
Christoffer Rodbro5f6abcf2019-02-08 11:00:10 +0100154 safe_timeout_("safe_timeout", true),
Christoffer Rodbro8ea02382019-02-28 15:15:35 +0100155 bandwidth_floor_("floor", DataRate::kbps(5)),
Sebastian Jansson24643482018-11-14 14:19:45 +0100156 // By initializing this to plus infinity, we make sure that we never
157 // trigger rtt backoff unless packet feedback is enabled.
158 last_propagation_rtt_update_(Timestamp::PlusInfinity()),
Christoffer Rodbro5f6abcf2019-02-08 11:00:10 +0100159 last_propagation_rtt_(TimeDelta::Zero()),
160 last_packet_sent_(Timestamp::MinusInfinity()) {
Christoffer Rodbro8ea02382019-02-28 15:15:35 +0100161 ParseFieldTrial(
162 {&rtt_limit_, &drop_fraction_, &drop_interval_, &persist_on_route_change_,
163 &safe_timeout_, &bandwidth_floor_},
164 field_trial::FindFullName("WebRTC-Bwe-MaxRttLimit"));
Sebastian Jansson2e068e82018-10-08 12:49:53 +0200165}
Sebastian Jansson24643482018-11-14 14:19:45 +0100166
167void RttBasedBackoff::OnRouteChange() {
168 if (!persist_on_route_change_) {
169 last_propagation_rtt_update_ = Timestamp::PlusInfinity();
170 last_propagation_rtt_ = TimeDelta::Zero();
171 }
172}
173
174void RttBasedBackoff::UpdatePropagationRtt(Timestamp at_time,
175 TimeDelta propagation_rtt) {
176 last_propagation_rtt_update_ = at_time;
177 last_propagation_rtt_ = propagation_rtt;
178}
179
Christoffer Rodbro5f6abcf2019-02-08 11:00:10 +0100180TimeDelta RttBasedBackoff::CorrectedRtt(Timestamp at_time) const {
Sebastian Jansson24643482018-11-14 14:19:45 +0100181 TimeDelta time_since_rtt = at_time - last_propagation_rtt_update_;
Christoffer Rodbro5f6abcf2019-02-08 11:00:10 +0100182 TimeDelta timeout_correction = time_since_rtt;
183 if (safe_timeout_) {
184 // Avoid timeout when no packets are being sent.
185 TimeDelta time_since_packet_sent = at_time - last_packet_sent_;
186 timeout_correction =
187 std::max(time_since_rtt - time_since_packet_sent, TimeDelta::Zero());
188 }
189 return timeout_correction + last_propagation_rtt_;
Sebastian Jansson24643482018-11-14 14:19:45 +0100190}
191
192RttBasedBackoff::~RttBasedBackoff() = default;
Sebastian Jansson2e068e82018-10-08 12:49:53 +0200193
ivoc14d5dbe2016-07-04 07:06:55 -0700194SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
Sebastian Jansson24643482018-11-14 14:19:45 +0100195 : lost_packets_since_last_loss_update_(0),
pbosb7edb882015-10-22 08:52:20 -0700196 expected_packets_since_last_loss_update_(0),
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200197 current_bitrate_(DataRate::Zero()),
198 min_bitrate_configured_(
199 DataRate::bps(congestion_controller::GetMinBitrateBps())),
200 max_bitrate_configured_(kDefaultMaxBitrate),
201 last_low_bitrate_log_(Timestamp::MinusInfinity()),
pbosb7edb882015-10-22 08:52:20 -0700202 has_decreased_since_last_fraction_loss_(false),
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200203 last_loss_feedback_(Timestamp::MinusInfinity()),
204 last_loss_packet_report_(Timestamp::MinusInfinity()),
205 last_timeout_(Timestamp::MinusInfinity()),
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000206 last_fraction_loss_(0),
stefan3821ff82016-09-04 05:07:26 -0700207 last_logged_fraction_loss_(0),
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200208 last_round_trip_time_(TimeDelta::Zero()),
209 bwe_incoming_(DataRate::Zero()),
210 delay_based_bitrate_(DataRate::Zero()),
211 time_last_decrease_(Timestamp::MinusInfinity()),
212 first_report_time_(Timestamp::MinusInfinity()),
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000213 initially_lost_packets_(0),
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200214 bitrate_at_2_seconds_(DataRate::Zero()),
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000215 uma_update_state_(kNoUpdate),
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100216 uma_rtt_state_(kNoUpdate),
terelius006d93d2015-11-05 12:02:15 -0800217 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
stefan3821ff82016-09-04 05:07:26 -0700218 event_log_(event_log),
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200219 last_rtc_event_log_(Timestamp::MinusInfinity()),
sprangc1b57a12017-02-28 08:50:47 -0800220 in_timeout_experiment_(
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200221 webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")),
222 low_loss_threshold_(kDefaultLowLossThreshold),
223 high_loss_threshold_(kDefaultHighLossThreshold),
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200224 bitrate_threshold_(kDefaultBitrateThreshold) {
ivoc14d5dbe2016-07-04 07:06:55 -0700225 RTC_DCHECK(event_log);
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200226 if (BweLossExperimentIsEnabled()) {
227 uint32_t bitrate_threshold_kbps;
228 if (ReadBweLossExperimentParameters(&low_loss_threshold_,
229 &high_loss_threshold_,
230 &bitrate_threshold_kbps)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100231 RTC_LOG(LS_INFO) << "Enabled BweLossExperiment with parameters "
232 << low_loss_threshold_ << ", " << high_loss_threshold_
233 << ", " << bitrate_threshold_kbps;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200234 bitrate_threshold_ = DataRate::kbps(bitrate_threshold_kbps);
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200235 }
236 }
ivoc14d5dbe2016-07-04 07:06:55 -0700237}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000238
andresp@webrtc.org16b75c22014-03-21 14:00:51 +0000239SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000240
Sebastian Jansson24643482018-11-14 14:19:45 +0100241void SendSideBandwidthEstimation::OnRouteChange() {
242 lost_packets_since_last_loss_update_ = 0;
243 expected_packets_since_last_loss_update_ = 0;
244 current_bitrate_ = DataRate::Zero();
245 min_bitrate_configured_ =
246 DataRate::bps(congestion_controller::GetMinBitrateBps());
247 max_bitrate_configured_ = kDefaultMaxBitrate;
248 last_low_bitrate_log_ = Timestamp::MinusInfinity();
249 has_decreased_since_last_fraction_loss_ = false;
250 last_loss_feedback_ = Timestamp::MinusInfinity();
251 last_loss_packet_report_ = Timestamp::MinusInfinity();
252 last_timeout_ = Timestamp::MinusInfinity();
253 last_fraction_loss_ = 0;
254 last_logged_fraction_loss_ = 0;
255 last_round_trip_time_ = TimeDelta::Zero();
256 bwe_incoming_ = DataRate::Zero();
257 delay_based_bitrate_ = DataRate::Zero();
258 time_last_decrease_ = Timestamp::MinusInfinity();
259 first_report_time_ = Timestamp::MinusInfinity();
260 initially_lost_packets_ = 0;
261 bitrate_at_2_seconds_ = DataRate::Zero();
262 uma_update_state_ = kNoUpdate;
263 uma_rtt_state_ = kNoUpdate;
264 last_rtc_event_log_ = Timestamp::MinusInfinity();
265
266 rtt_backoff_.OnRouteChange();
267}
268
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200269void SendSideBandwidthEstimation::SetBitrates(
270 absl::optional<DataRate> send_bitrate,
271 DataRate min_bitrate,
272 DataRate max_bitrate,
273 Timestamp at_time) {
philipel1b965312017-04-18 06:55:32 -0700274 SetMinMaxBitrate(min_bitrate, max_bitrate);
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100275 if (send_bitrate) {
276 link_capacity_.OnStartingRate(*send_bitrate);
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200277 SetSendBitrate(*send_bitrate, at_time);
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100278 }
philipelc6957c72016-04-28 15:52:49 +0200279}
280
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200281void SendSideBandwidthEstimation::SetSendBitrate(DataRate bitrate,
282 Timestamp at_time) {
Sebastian Jansson5a000162019-04-12 11:21:32 +0200283 RTC_DCHECK_GT(bitrate, DataRate::Zero());
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200284 // Reset to avoid being capped by the estimate.
285 delay_based_bitrate_ = DataRate::Zero();
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100286 if (loss_based_bandwidth_estimation_.Enabled()) {
287 loss_based_bandwidth_estimation_.MaybeReset(bitrate);
288 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200289 CapBitrateToThresholds(at_time, bitrate);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000290 // Clear last sent bitrate history so the new value can be used directly
291 // and not capped.
292 min_bitrate_history_.clear();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000293}
294
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200295void SendSideBandwidthEstimation::SetMinMaxBitrate(DataRate min_bitrate,
296 DataRate max_bitrate) {
michaeltf082c2a2016-11-07 04:17:14 -0800297 min_bitrate_configured_ =
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200298 std::max(min_bitrate, congestion_controller::GetMinBitrate());
299 if (max_bitrate > DataRate::Zero() && max_bitrate.IsFinite()) {
300 max_bitrate_configured_ = std::max(min_bitrate_configured_, max_bitrate);
Stefan Holmere5904162015-03-26 11:11:06 +0100301 } else {
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200302 max_bitrate_configured_ = kDefaultMaxBitrate;
Stefan Holmere5904162015-03-26 11:11:06 +0100303 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000304}
305
Stefan Holmere5904162015-03-26 11:11:06 +0100306int SendSideBandwidthEstimation::GetMinBitrate() const {
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200307 return min_bitrate_configured_.bps<int>();
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000308}
309
Stefan Holmere5904162015-03-26 11:11:06 +0100310void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000311 uint8_t* loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000312 int64_t* rtt) const {
Sebastian Janssond98cbd82019-04-01 17:36:22 +0200313 *bitrate = std::max<int32_t>(current_bitrate_.bps<int>(), GetMinBitrate());
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000314 *loss = last_fraction_loss_;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200315 *rtt = last_round_trip_time_.ms<int64_t>();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000316}
317
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100318DataRate SendSideBandwidthEstimation::GetEstimatedLinkCapacity() const {
319 return link_capacity_.estimate();
320}
321
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200322void SendSideBandwidthEstimation::UpdateReceiverEstimate(Timestamp at_time,
323 DataRate bandwidth) {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000324 bwe_incoming_ = bandwidth;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200325 CapBitrateToThresholds(at_time, current_bitrate_);
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000326}
327
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200328void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(Timestamp at_time,
329 DataRate bitrate) {
Florent Castelli1067d312019-09-04 14:58:32 +0200330 if (bitrate < delay_based_bitrate_) {
331 link_capacity_.OnOveruse(bitrate, at_time);
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100332 }
Florent Castelli1067d312019-09-04 14:58:32 +0200333
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200334 delay_based_bitrate_ = bitrate;
335 CapBitrateToThresholds(at_time, current_bitrate_);
stefan32f81542016-01-20 07:13:58 -0800336}
337
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100338void SendSideBandwidthEstimation::SetAcknowledgedRate(
339 absl::optional<DataRate> acknowledged_rate,
340 Timestamp at_time) {
341 acknowledged_rate_ = acknowledged_rate;
342 if (acknowledged_rate && loss_based_bandwidth_estimation_.Enabled()) {
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100343 loss_based_bandwidth_estimation_.UpdateAcknowledgedBitrate(
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100344 *acknowledged_rate, at_time);
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100345 }
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100346}
347
348void SendSideBandwidthEstimation::IncomingPacketFeedbackVector(
349 const TransportPacketsFeedback& report) {
350 if (loss_based_bandwidth_estimation_.Enabled()) {
351 loss_based_bandwidth_estimation_.UpdateLossStatistics(
352 report.packet_feedbacks, report.feedback_time);
353 }
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100354}
355
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000356void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200357 TimeDelta rtt,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000358 int number_of_packets,
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200359 Timestamp at_time) {
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100360 const int kRoundingConstant = 128;
361 int packets_lost = (static_cast<int>(fraction_loss) * number_of_packets +
362 kRoundingConstant) >>
363 8;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200364 UpdatePacketsLost(packets_lost, number_of_packets, at_time);
365 UpdateRtt(rtt, at_time);
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100366}
367
368void SendSideBandwidthEstimation::UpdatePacketsLost(int packets_lost,
369 int number_of_packets,
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200370 Timestamp at_time) {
371 last_loss_feedback_ = at_time;
372 if (first_report_time_.IsInfinite())
373 first_report_time_ = at_time;
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000374
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000375 // Check sequence number diff and weight loss report
376 if (number_of_packets > 0) {
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000377 // Accumulate reports.
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100378 lost_packets_since_last_loss_update_ += packets_lost;
pbosb7edb882015-10-22 08:52:20 -0700379 expected_packets_since_last_loss_update_ += number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000380
pbosb7edb882015-10-22 08:52:20 -0700381 // Don't generate a loss rate until it can be based on enough packets.
382 if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000383 return;
pbosb7edb882015-10-22 08:52:20 -0700384
385 has_decreased_since_last_fraction_loss_ = false;
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100386 int64_t lost_q8 = lost_packets_since_last_loss_update_ << 8;
387 int64_t expected = expected_packets_since_last_loss_update_;
388 last_fraction_loss_ = std::min<int>(lost_q8 / expected, 255);
pbosb7edb882015-10-22 08:52:20 -0700389
390 // Reset accumulators.
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100391
392 lost_packets_since_last_loss_update_ = 0;
pbosb7edb882015-10-22 08:52:20 -0700393 expected_packets_since_last_loss_update_ = 0;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200394 last_loss_packet_report_ = at_time;
395 UpdateEstimate(at_time);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000396 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200397 UpdateUmaStatsPacketsLost(at_time, packets_lost);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000398}
399
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200400void SendSideBandwidthEstimation::UpdateUmaStatsPacketsLost(Timestamp at_time,
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100401 int packets_lost) {
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200402 DataRate bitrate_kbps = DataRate::kbps((current_bitrate_.bps() + 500) / 1000);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000403 for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
404 if (!rampup_uma_stats_updated_[i] &&
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200405 bitrate_kbps.kbps() >= kUmaRampupMetrics[i].bitrate_kbps) {
asapersson1d02d3e2016-09-09 22:40:25 -0700406 RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200407 (at_time - first_report_time_).ms());
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000408 rampup_uma_stats_updated_[i] = true;
409 }
410 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200411 if (IsInStartPhase(at_time)) {
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100412 initially_lost_packets_ += packets_lost;
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000413 } else if (uma_update_state_ == kNoUpdate) {
414 uma_update_state_ = kFirstDone;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200415 bitrate_at_2_seconds_ = bitrate_kbps;
asapersson1d02d3e2016-09-09 22:40:25 -0700416 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
417 initially_lost_packets_, 0, 100, 50);
asapersson1d02d3e2016-09-09 22:40:25 -0700418 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200419 bitrate_at_2_seconds_.kbps(), 0, 2000, 50);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000420 } else if (uma_update_state_ == kFirstDone &&
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200421 at_time - first_report_time_ >= kBweConverganceTime) {
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000422 uma_update_state_ = kDone;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200423 int bitrate_diff_kbps = std::max(
424 bitrate_at_2_seconds_.kbps<int>() - bitrate_kbps.kbps<int>(), 0);
asapersson1d02d3e2016-09-09 22:40:25 -0700425 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
426 0, 2000, 50);
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000427 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000428}
429
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200430void SendSideBandwidthEstimation::UpdateRtt(TimeDelta rtt, Timestamp at_time) {
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100431 // Update RTT if we were able to compute an RTT based on this RTCP.
432 // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200433 if (rtt > TimeDelta::Zero())
434 last_round_trip_time_ = rtt;
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100435
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200436 if (!IsInStartPhase(at_time) && uma_rtt_state_ == kNoUpdate) {
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100437 uma_rtt_state_ = kDone;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200438 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", rtt.ms<int>(), 0, 2000, 50);
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100439 }
440}
441
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200442void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
443 DataRate new_bitrate = current_bitrate_;
Christoffer Rodbro5f6abcf2019-02-08 11:00:10 +0100444 if (rtt_backoff_.CorrectedRtt(at_time) > rtt_backoff_.rtt_limit_) {
Christoffer Rodbro8ea02382019-02-28 15:15:35 +0100445 if (at_time - time_last_decrease_ >= rtt_backoff_.drop_interval_ &&
446 current_bitrate_ > rtt_backoff_.bandwidth_floor_) {
Sebastian Jansson2e068e82018-10-08 12:49:53 +0200447 time_last_decrease_ = at_time;
Christoffer Rodbro8ea02382019-02-28 15:15:35 +0100448 new_bitrate = std::max(current_bitrate_ * rtt_backoff_.drop_fraction_,
449 rtt_backoff_.bandwidth_floor_.Get());
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100450 link_capacity_.OnRttBackoff(new_bitrate, at_time);
Sebastian Jansson2e068e82018-10-08 12:49:53 +0200451 }
452 CapBitrateToThresholds(at_time, new_bitrate);
453 return;
454 }
455
stefanfa156692016-01-21 08:55:03 -0800456 // We trust the REMB and/or delay-based estimate during the first 2 seconds if
457 // we haven't had any packet loss reported, to allow startup bitrate probing.
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200458 if (last_fraction_loss_ == 0 && IsInStartPhase(at_time)) {
philipel1b965312017-04-18 06:55:32 -0700459 new_bitrate = std::max(bwe_incoming_, new_bitrate);
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200460 new_bitrate = std::max(delay_based_bitrate_, new_bitrate);
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100461 if (loss_based_bandwidth_estimation_.Enabled()) {
462 loss_based_bandwidth_estimation_.SetInitialBitrate(new_bitrate);
463 }
philipel1b965312017-04-18 06:55:32 -0700464
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200465 if (new_bitrate != current_bitrate_) {
stefanfa156692016-01-21 08:55:03 -0800466 min_bitrate_history_.clear();
Christoffer Rodbro982639c2019-01-18 15:34:59 +0100467 if (loss_based_bandwidth_estimation_.Enabled()) {
468 min_bitrate_history_.push_back(std::make_pair(at_time, new_bitrate));
469 } else {
470 min_bitrate_history_.push_back(
471 std::make_pair(at_time, current_bitrate_));
472 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200473 CapBitrateToThresholds(at_time, new_bitrate);
stefanfa156692016-01-21 08:55:03 -0800474 return;
475 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000476 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200477 UpdateMinHistory(at_time);
478 if (last_loss_packet_report_.IsInfinite()) {
Stefan Holmer52200d02016-09-20 14:14:23 +0200479 // No feedback received.
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200480 CapBitrateToThresholds(at_time, current_bitrate_);
Stefan Holmer52200d02016-09-20 14:14:23 +0200481 return;
482 }
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100483
484 if (loss_based_bandwidth_estimation_.Enabled()) {
485 loss_based_bandwidth_estimation_.Update(
486 at_time, min_bitrate_history_.front().second, last_round_trip_time_);
487 new_bitrate = MaybeRampupOrBackoff(new_bitrate, at_time);
488 CapBitrateToThresholds(at_time, new_bitrate);
489 return;
490 }
491
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200492 TimeDelta time_since_loss_packet_report = at_time - last_loss_packet_report_;
493 TimeDelta time_since_loss_feedback = at_time - last_loss_feedback_;
494 if (time_since_loss_packet_report < 1.2 * kMaxRtcpFeedbackInterval) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200495 // We only care about loss above a given bitrate threshold.
496 float loss = last_fraction_loss_ / 256.0f;
497 // We only make decisions based on loss when the bitrate is above a
498 // threshold. This is a crude way of handling loss which is uncorrelated
499 // to congestion.
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200500 if (current_bitrate_ < bitrate_threshold_ || loss <= low_loss_threshold_) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000501 // Loss < 2%: Increase rate by 8% of the min bitrate in the last
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200502 // kBweIncreaseInterval.
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000503 // Note that by remembering the bitrate over the last second one can
504 // rampup up one second faster than if only allowed to start ramping
505 // at 8% per second rate now. E.g.:
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100506 // If sending a constant 100kbps it can rampup immediately to 108kbps
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000507 // whenever a receiver report is received with lower packet loss.
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200508 // If instead one would do: current_bitrate_ *= 1.08^(delta time),
philipel1b965312017-04-18 06:55:32 -0700509 // it would take over one second since the lower packet loss to achieve
Stefan Holmer52200d02016-09-20 14:14:23 +0200510 // 108kbps.
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200511 new_bitrate =
512 DataRate::bps(min_bitrate_history_.front().second.bps() * 1.08 + 0.5);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000513
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000514 // Add 1 kbps extra, just to make sure that we do not get stuck
515 // (gives a little extra increase at low rates, negligible at higher
516 // rates).
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200517 new_bitrate += DataRate::bps(1000);
518 } else if (current_bitrate_ > bitrate_threshold_) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200519 if (loss <= high_loss_threshold_) {
520 // Loss between 2% - 10%: Do nothing.
521 } else {
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200522 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseInterval
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200523 // + rtt.
524 if (!has_decreased_since_last_fraction_loss_ &&
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200525 (at_time - time_last_decrease_) >=
526 (kBweDecreaseInterval + last_round_trip_time_)) {
527 time_last_decrease_ = at_time;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000528
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200529 // Reduce rate:
530 // newRate = rate * (1 - 0.5*lossRate);
531 // where packetLoss = 256*lossRate;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200532 new_bitrate =
533 DataRate::bps((current_bitrate_.bps() *
534 static_cast<double>(512 - last_fraction_loss_)) /
535 512.0);
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200536 has_decreased_since_last_fraction_loss_ = true;
537 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000538 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000539 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200540 } else if (time_since_loss_feedback >
541 kFeedbackTimeoutIntervals * kMaxRtcpFeedbackInterval &&
542 (last_timeout_.IsInfinite() ||
543 at_time - last_timeout_ > kTimeoutInterval)) {
Stefan Holmer52200d02016-09-20 14:14:23 +0200544 if (in_timeout_experiment_) {
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200545 RTC_LOG(LS_WARNING) << "Feedback timed out ("
546 << ToString(time_since_loss_feedback)
547 << "), reducing bitrate.";
548 new_bitrate = new_bitrate * 0.8;
Stefan Holmer52200d02016-09-20 14:14:23 +0200549 // Reset accumulators since we've already acted on missing feedback and
550 // shouldn't to act again on these old lost packets.
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100551 lost_packets_since_last_loss_update_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200552 expected_packets_since_last_loss_update_ = 0;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200553 last_timeout_ = at_time;
Stefan Holmer52200d02016-09-20 14:14:23 +0200554 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000555 }
philipel1b965312017-04-18 06:55:32 -0700556
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200557 CapBitrateToThresholds(at_time, new_bitrate);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000558}
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000559
Sebastian Jansson2e068e82018-10-08 12:49:53 +0200560void SendSideBandwidthEstimation::UpdatePropagationRtt(
561 Timestamp at_time,
562 TimeDelta propagation_rtt) {
Sebastian Jansson24643482018-11-14 14:19:45 +0100563 rtt_backoff_.UpdatePropagationRtt(at_time, propagation_rtt);
Sebastian Jansson2e068e82018-10-08 12:49:53 +0200564}
565
Christoffer Rodbro5f6abcf2019-02-08 11:00:10 +0100566void SendSideBandwidthEstimation::OnSentPacket(const SentPacket& sent_packet) {
567 // Only feedback-triggering packets will be reported here.
568 rtt_backoff_.last_packet_sent_ = sent_packet.send_time;
569}
570
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200571bool SendSideBandwidthEstimation::IsInStartPhase(Timestamp at_time) const {
572 return first_report_time_.IsInfinite() ||
573 at_time - first_report_time_ < kStartPhase;
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000574}
575
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200576void SendSideBandwidthEstimation::UpdateMinHistory(Timestamp at_time) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000577 // Remove old data points from history.
578 // Since history precision is in ms, add one so it is able to increase
579 // bitrate if it is off by as little as 0.5ms.
580 while (!min_bitrate_history_.empty() &&
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200581 at_time - min_bitrate_history_.front().first + TimeDelta::ms(1) >
582 kBweIncreaseInterval) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000583 min_bitrate_history_.pop_front();
584 }
585
586 // Typical minimum sliding-window algorithm: Pop values higher than current
587 // bitrate before pushing it.
588 while (!min_bitrate_history_.empty() &&
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200589 current_bitrate_ <= min_bitrate_history_.back().second) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000590 min_bitrate_history_.pop_back();
591 }
592
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200593 min_bitrate_history_.push_back(std::make_pair(at_time, current_bitrate_));
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000594}
595
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100596DataRate SendSideBandwidthEstimation::MaybeRampupOrBackoff(DataRate new_bitrate,
597 Timestamp at_time) {
598 // TODO(crodbro): reuse this code in UpdateEstimate instead of current
599 // inlining of very similar functionality.
600 const TimeDelta time_since_loss_packet_report =
601 at_time - last_loss_packet_report_;
602 const TimeDelta time_since_loss_feedback = at_time - last_loss_feedback_;
603 if (time_since_loss_packet_report < 1.2 * kMaxRtcpFeedbackInterval) {
604 new_bitrate = min_bitrate_history_.front().second * 1.08;
605 new_bitrate += DataRate::bps(1000);
606 } else if (time_since_loss_feedback >
607 kFeedbackTimeoutIntervals * kMaxRtcpFeedbackInterval &&
608 (last_timeout_.IsInfinite() ||
609 at_time - last_timeout_ > kTimeoutInterval)) {
610 if (in_timeout_experiment_) {
611 RTC_LOG(LS_WARNING) << "Feedback timed out ("
612 << ToString(time_since_loss_feedback)
613 << "), reducing bitrate.";
614 new_bitrate = new_bitrate * 0.8;
615 // Reset accumulators since we've already acted on missing feedback and
616 // shouldn't to act again on these old lost packets.
617 lost_packets_since_last_loss_update_ = 0;
618 expected_packets_since_last_loss_update_ = 0;
619 last_timeout_ = at_time;
620 }
621 }
622 return new_bitrate;
623}
624
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200625void SendSideBandwidthEstimation::CapBitrateToThresholds(Timestamp at_time,
626 DataRate bitrate) {
627 if (bwe_incoming_ > DataRate::Zero() && bitrate > bwe_incoming_) {
628 bitrate = bwe_incoming_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000629 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200630 if (delay_based_bitrate_ > DataRate::Zero() &&
631 bitrate > delay_based_bitrate_) {
632 bitrate = delay_based_bitrate_;
stefan32f81542016-01-20 07:13:58 -0800633 }
Christoffer Rodbro3a837482018-11-19 15:30:23 +0100634 if (loss_based_bandwidth_estimation_.Enabled() &&
635 loss_based_bandwidth_estimation_.GetEstimate() > DataRate::Zero()) {
636 bitrate = std::min(bitrate, loss_based_bandwidth_estimation_.GetEstimate());
637 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200638 if (bitrate > max_bitrate_configured_) {
639 bitrate = max_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000640 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200641 if (bitrate < min_bitrate_configured_) {
642 if (last_low_bitrate_log_.IsInfinite() ||
643 at_time - last_low_bitrate_log_ > kLowBitrateLogPeriod) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100644 RTC_LOG(LS_WARNING) << "Estimated available bandwidth "
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200645 << ToString(bitrate)
646 << " is below configured min bitrate "
647 << ToString(min_bitrate_configured_) << ".";
648 last_low_bitrate_log_ = at_time;
stefanb6b0b922015-09-04 03:04:56 -0700649 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200650 bitrate = min_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000651 }
philipel1b965312017-04-18 06:55:32 -0700652
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200653 if (bitrate != current_bitrate_ ||
philipel1b965312017-04-18 06:55:32 -0700654 last_fraction_loss_ != last_logged_fraction_loss_ ||
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200655 at_time - last_rtc_event_log_ > kRtcEventLogPeriod) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200656 event_log_->Log(absl::make_unique<RtcEventBweUpdateLossBased>(
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200657 bitrate.bps(), last_fraction_loss_,
Elad Alon4a87e1c2017-10-03 16:11:34 +0200658 expected_packets_since_last_loss_update_));
philipel1b965312017-04-18 06:55:32 -0700659 last_logged_fraction_loss_ = last_fraction_loss_;
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200660 last_rtc_event_log_ = at_time;
philipel1b965312017-04-18 06:55:32 -0700661 }
Sebastian Jansson7c1744d2018-10-08 11:00:50 +0200662 current_bitrate_ = bitrate;
Sebastian Jansson57f3ad02018-11-23 14:49:18 +0100663
664 if (acknowledged_rate_) {
665 link_capacity_.OnRateUpdate(std::min(current_bitrate_, *acknowledged_rate_),
666 at_time);
667 }
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000668}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000669} // namespace webrtc