blob: 34b8242ed760dcc96e52bb7d870a926c0d472885 [file] [log] [blame]
philipel863a8262016-06-17 09:21:34 -07001/*
2 * Copyright (c) 2016 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#include "webrtc/modules/congestion_controller/delay_based_bwe.h"
12
13#include <math.h>
14
15#include <algorithm>
16
17#include "webrtc/base/checks.h"
18#include "webrtc/base/constructormagic.h"
19#include "webrtc/base/logging.h"
20#include "webrtc/base/thread_annotations.h"
Irfan Sheriffb2540bb2016-09-12 12:28:54 -070021#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
philipel863a8262016-06-17 09:21:34 -070022#include "webrtc/modules/pacing/paced_sender.h"
23#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
stefan64636dd2016-08-03 00:29:03 -070024#include "webrtc/system_wrappers/include/metrics.h"
philipel863a8262016-06-17 09:21:34 -070025#include "webrtc/typedefs.h"
26
27namespace {
philipel7522a282016-08-16 10:59:36 +020028constexpr int kTimestampGroupLengthMs = 5;
29constexpr int kAbsSendTimeFraction = 18;
30constexpr int kAbsSendTimeInterArrivalUpshift = 8;
31constexpr int kInterArrivalShift =
32 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
33constexpr double kTimestampToMs =
philipel863a8262016-06-17 09:21:34 -070034 1000.0 / static_cast<double>(1 << kInterArrivalShift);
philipel7522a282016-08-16 10:59:36 +020035// This ssrc is used to fulfill the current API but will be removed
36// after the API has been changed.
37constexpr uint32_t kFixedSsrc = 0;
philipel863a8262016-06-17 09:21:34 -070038} // namespace
39
40namespace webrtc {
41
Stefan Holmer280de9e2016-09-30 10:06:51 +020042DelayBasedBwe::DelayBasedBwe(Clock* clock)
stefan5e12d362016-07-11 01:44:02 -070043 : clock_(clock),
philipel863a8262016-06-17 09:21:34 -070044 inter_arrival_(),
45 estimator_(),
46 detector_(OverUseDetectorOptions()),
47 incoming_bitrate_(kBitrateWindowMs, 8000),
philipel863a8262016-06-17 09:21:34 -070048 last_update_ms_(-1),
philipel7522a282016-08-16 10:59:36 +020049 last_seen_packet_ms_(-1),
stefan64636dd2016-08-03 00:29:03 -070050 uma_recorded_(false) {
philipel863a8262016-06-17 09:21:34 -070051 network_thread_.DetachFromThread();
52}
53
Stefan Holmer280de9e2016-09-30 10:06:51 +020054DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
philipel863a8262016-06-17 09:21:34 -070055 const std::vector<PacketInfo>& packet_feedback_vector) {
56 RTC_DCHECK(network_thread_.CalledOnValidThread());
stefan64636dd2016-08-03 00:29:03 -070057 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -070058 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
59 BweNames::kSendSideTransportSeqNum,
60 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -070061 uma_recorded_ = true;
62 }
Stefan Holmer280de9e2016-09-30 10:06:51 +020063 Result aggregated_result;
philipel863a8262016-06-17 09:21:34 -070064 for (const auto& packet_info : packet_feedback_vector) {
Stefan Holmer280de9e2016-09-30 10:06:51 +020065 Result result = IncomingPacketInfo(packet_info);
66 if (result.updated)
67 aggregated_result = result;
philipel863a8262016-06-17 09:21:34 -070068 }
Stefan Holmer280de9e2016-09-30 10:06:51 +020069 return aggregated_result;
philipel863a8262016-06-17 09:21:34 -070070}
71
Stefan Holmer280de9e2016-09-30 10:06:51 +020072DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo(
73 const PacketInfo& info) {
stefan5e12d362016-07-11 01:44:02 -070074 int64_t now_ms = clock_->TimeInMilliseconds();
philipel863a8262016-06-17 09:21:34 -070075
philipel7522a282016-08-16 10:59:36 +020076 incoming_bitrate_.Update(info.payload_size, info.arrival_time_ms);
Stefan Holmer280de9e2016-09-30 10:06:51 +020077 Result result;
78 // Reset if the stream has timed out.
79 if (last_seen_packet_ms_ == -1 ||
80 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
81 inter_arrival_.reset(
82 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
83 kTimestampToMs, true));
84 estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
85 }
86 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -070087
Stefan Holmer280de9e2016-09-30 10:06:51 +020088 uint32_t send_time_24bits =
89 static_cast<uint32_t>(
90 ((static_cast<uint64_t>(info.send_time_ms) << kAbsSendTimeFraction) +
91 500) /
92 1000) &
93 0x00FFFFFF;
94 // Shift up send time to use the full 32 bits that inter_arrival works with,
95 // so wrapping works properly.
96 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -070097
Stefan Holmer280de9e2016-09-30 10:06:51 +020098 uint32_t ts_delta = 0;
99 int64_t t_delta = 0;
100 int size_delta = 0;
101 if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms,
102 info.payload_size, &ts_delta, &t_delta,
103 &size_delta)) {
104 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
105 estimator_->Update(t_delta, ts_delta_ms, size_delta, detector_.State(),
106 info.arrival_time_ms);
107 detector_.Detect(estimator_->offset(), ts_delta_ms,
108 estimator_->num_of_deltas(), info.arrival_time_ms);
stefan5ec85fb2016-09-29 04:19:38 -0700109 }
110
Stefan Holmer280de9e2016-09-30 10:06:51 +0200111 int probing_bps = 0;
112 if (info.probe_cluster_id != PacketInfo::kNotAProbe) {
113 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info);
114 }
115
116 // Currently overusing the bandwidth.
117 if (detector_.State() == kBwOverusing) {
118 rtc::Optional<uint32_t> incoming_rate =
119 incoming_bitrate_.Rate(info.arrival_time_ms);
120 if (incoming_rate &&
121 remote_rate_.TimeToReduceFurther(now_ms, *incoming_rate)) {
122 result.updated = UpdateEstimate(info.arrival_time_ms, now_ms,
123 &result.target_bitrate_bps);
124 }
125 } else if (probing_bps > 0) {
126 // No overuse, but probing measured a bitrate.
127 remote_rate_.SetEstimate(probing_bps, info.arrival_time_ms);
128 result.probe = true;
129 result.updated = UpdateEstimate(info.arrival_time_ms, now_ms,
130 &result.target_bitrate_bps);
131 }
132 rtc::Optional<uint32_t> incoming_rate =
133 incoming_bitrate_.Rate(info.arrival_time_ms);
134 if (!result.updated &&
135 (last_update_ms_ == -1 ||
136 now_ms - last_update_ms_ > remote_rate_.GetFeedbackInterval())) {
137 result.updated = UpdateEstimate(info.arrival_time_ms, now_ms,
138 &result.target_bitrate_bps);
139 }
140 if (result.updated)
stefan5ec85fb2016-09-29 04:19:38 -0700141 last_update_ms_ = now_ms;
Stefan Holmer280de9e2016-09-30 10:06:51 +0200142
143 return result;
philipel863a8262016-06-17 09:21:34 -0700144}
145
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700146bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms,
147 int64_t now_ms,
148 uint32_t* target_bitrate_bps) {
149 // The first overuse should immediately trigger a new estimate.
150 // We also have to update the estimate immediately if we are overusing
151 // and the target bitrate is too high compared to what we are receiving.
152 const RateControlInput input(detector_.State(),
153 incoming_bitrate_.Rate(arrival_time_ms),
154 estimator_->var_noise());
155 remote_rate_.Update(&input, now_ms);
156 *target_bitrate_bps = remote_rate_.UpdateBandwidthEstimate(now_ms);
157 return remote_rate_.ValidEstimate();
158}
159
philipel863a8262016-06-17 09:21:34 -0700160void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
philipel863a8262016-06-17 09:21:34 -0700161 remote_rate_.SetRtt(avg_rtt_ms);
162}
163
philipel863a8262016-06-17 09:21:34 -0700164bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
165 uint32_t* bitrate_bps) const {
166 // Currently accessed from both the process thread (see
167 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
168 // Call::GetStats()). Should in the future only be accessed from a single
169 // thread.
170 RTC_DCHECK(ssrcs);
171 RTC_DCHECK(bitrate_bps);
philipel7522a282016-08-16 10:59:36 +0200172 if (!remote_rate_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700173 return false;
philipel7522a282016-08-16 10:59:36 +0200174
175 *ssrcs = {kFixedSsrc};
176 *bitrate_bps = remote_rate_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700177 return true;
178}
179
180void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
181 // Called from both the configuration thread and the network thread. Shouldn't
182 // be called from the network thread in the future.
philipel863a8262016-06-17 09:21:34 -0700183 remote_rate_.SetMinBitrate(min_bitrate_bps);
184}
185} // namespace webrtc