1 /*
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 #include "modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
12
13
14 #include <cstdint>
15 #include <utility>
16
17 #include "absl/types/optional.h"
18 #include "modules/remote_bitrate_estimator/aimd_rate_control.h"
19 #include "modules/remote_bitrate_estimator/include/bwe_defines.h"
20 #include "modules/remote_bitrate_estimator/inter_arrival.h"
21 #include "modules/remote_bitrate_estimator/overuse_detector.h"
22 #include "modules/remote_bitrate_estimator/overuse_estimator.h"
23 #include "rtc_base/checks.h"
24 #include "rtc_base/logging.h"
25 #include "system_wrappers/include/clock.h"
26 #include "system_wrappers/include/metrics.h"
27
28 namespace webrtc {
29 namespace {
OptionalRateFromOptionalBps(absl::optional<int> bitrate_bps)30 absl::optional<DataRate> OptionalRateFromOptionalBps(
31 absl::optional<int> bitrate_bps) {
32 if (bitrate_bps) {
33 return DataRate::BitsPerSec(*bitrate_bps);
34 } else {
35 return absl::nullopt;
36 }
37 }
38 } // namespace
39
40 enum { kTimestampGroupLengthMs = 5 };
41 static const double kTimestampToMs = 1.0 / 90.0;
42
43 struct RemoteBitrateEstimatorSingleStream::Detector {
Detectorwebrtc::RemoteBitrateEstimatorSingleStream::Detector44 explicit Detector(int64_t last_packet_time_ms,
45 const OverUseDetectorOptions& options,
46 bool enable_burst_grouping,
47 const FieldTrialsView* key_value_config)
48 : last_packet_time_ms(last_packet_time_ms),
49 inter_arrival(90 * kTimestampGroupLengthMs,
50 kTimestampToMs,
51 enable_burst_grouping),
52 estimator(options),
53 detector(key_value_config) {}
54 int64_t last_packet_time_ms;
55 InterArrival inter_arrival;
56 OveruseEstimator estimator;
57 OveruseDetector detector;
58 };
59
RemoteBitrateEstimatorSingleStream(RemoteBitrateObserver * observer,Clock * clock)60 RemoteBitrateEstimatorSingleStream::RemoteBitrateEstimatorSingleStream(
61 RemoteBitrateObserver* observer,
62 Clock* clock)
63 : clock_(clock),
64 incoming_bitrate_(kBitrateWindowMs, 8000),
65 last_valid_incoming_bitrate_(0),
66 remote_rate_(&field_trials_),
67 observer_(observer),
68 last_process_time_(-1),
69 process_interval_ms_(kProcessIntervalMs),
70 uma_recorded_(false) {
71 RTC_LOG(LS_INFO) << "RemoteBitrateEstimatorSingleStream: Instantiating.";
72 }
73
~RemoteBitrateEstimatorSingleStream()74 RemoteBitrateEstimatorSingleStream::~RemoteBitrateEstimatorSingleStream() {
75 while (!overuse_detectors_.empty()) {
76 SsrcOveruseEstimatorMap::iterator it = overuse_detectors_.begin();
77 delete it->second;
78 overuse_detectors_.erase(it);
79 }
80 }
81
IncomingPacket(int64_t arrival_time_ms,size_t payload_size,const RTPHeader & header)82 void RemoteBitrateEstimatorSingleStream::IncomingPacket(
83 int64_t arrival_time_ms,
84 size_t payload_size,
85 const RTPHeader& header) {
86 if (!uma_recorded_) {
87 BweNames type = BweNames::kReceiverTOffset;
88 if (!header.extension.hasTransmissionTimeOffset)
89 type = BweNames::kReceiverNoExtension;
90 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, type, BweNames::kBweNamesMax);
91 uma_recorded_ = true;
92 }
93 uint32_t ssrc = header.ssrc;
94 uint32_t rtp_timestamp =
95 header.timestamp + header.extension.transmissionTimeOffset;
96 int64_t now_ms = clock_->TimeInMilliseconds();
97 MutexLock lock(&mutex_);
98 SsrcOveruseEstimatorMap::iterator it = overuse_detectors_.find(ssrc);
99 if (it == overuse_detectors_.end()) {
100 // This is a new SSRC. Adding to map.
101 // TODO(holmer): If the channel changes SSRC the old SSRC will still be
102 // around in this map until the channel is deleted. This is OK since the
103 // callback will no longer be called for the old SSRC. This will be
104 // automatically cleaned up when we have one RemoteBitrateEstimator per REMB
105 // group.
106 std::pair<SsrcOveruseEstimatorMap::iterator, bool> insert_result =
107 overuse_detectors_.insert(
108 std::make_pair(ssrc, new Detector(now_ms, OverUseDetectorOptions(),
109 true, &field_trials_)));
110 it = insert_result.first;
111 }
112 Detector* estimator = it->second;
113 estimator->last_packet_time_ms = now_ms;
114
115 // Check if incoming bitrate estimate is valid, and if it needs to be reset.
116 absl::optional<uint32_t> incoming_bitrate = incoming_bitrate_.Rate(now_ms);
117 if (incoming_bitrate) {
118 last_valid_incoming_bitrate_ = *incoming_bitrate;
119 } else if (last_valid_incoming_bitrate_ > 0) {
120 // Incoming bitrate had a previous valid value, but now not enough data
121 // point are left within the current window. Reset incoming bitrate
122 // estimator so that the window size will only contain new data points.
123 incoming_bitrate_.Reset();
124 last_valid_incoming_bitrate_ = 0;
125 }
126 incoming_bitrate_.Update(payload_size, now_ms);
127
128 const BandwidthUsage prior_state = estimator->detector.State();
129 uint32_t timestamp_delta = 0;
130 int64_t time_delta = 0;
131 int size_delta = 0;
132 if (estimator->inter_arrival.ComputeDeltas(
133 rtp_timestamp, arrival_time_ms, now_ms, payload_size,
134 ×tamp_delta, &time_delta, &size_delta)) {
135 double timestamp_delta_ms = timestamp_delta * kTimestampToMs;
136 estimator->estimator.Update(time_delta, timestamp_delta_ms, size_delta,
137 estimator->detector.State(), now_ms);
138 estimator->detector.Detect(estimator->estimator.offset(),
139 timestamp_delta_ms,
140 estimator->estimator.num_of_deltas(), now_ms);
141 }
142 if (estimator->detector.State() == BandwidthUsage::kBwOverusing) {
143 absl::optional<uint32_t> incoming_bitrate_bps =
144 incoming_bitrate_.Rate(now_ms);
145 if (incoming_bitrate_bps &&
146 (prior_state != BandwidthUsage::kBwOverusing ||
147 remote_rate_.TimeToReduceFurther(
148 Timestamp::Millis(now_ms),
149 DataRate::BitsPerSec(*incoming_bitrate_bps)))) {
150 // The first overuse should immediately trigger a new estimate.
151 // We also have to update the estimate immediately if we are overusing
152 // and the target bitrate is too high compared to what we are receiving.
153 UpdateEstimate(now_ms);
154 }
155 }
156 }
157
Process()158 TimeDelta RemoteBitrateEstimatorSingleStream::Process() {
159 MutexLock lock(&mutex_);
160 int64_t now_ms = clock_->TimeInMilliseconds();
161 int64_t next_process_time_ms = last_process_time_ + process_interval_ms_;
162 if (last_process_time_ == -1 || now_ms >= next_process_time_ms) {
163 UpdateEstimate(now_ms);
164 last_process_time_ = now_ms;
165 return TimeDelta::Millis(process_interval_ms_);
166 }
167
168 return TimeDelta::Millis(next_process_time_ms - now_ms);
169 }
170
UpdateEstimate(int64_t now_ms)171 void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t now_ms) {
172 BandwidthUsage bw_state = BandwidthUsage::kBwNormal;
173 SsrcOveruseEstimatorMap::iterator it = overuse_detectors_.begin();
174 while (it != overuse_detectors_.end()) {
175 const int64_t time_of_last_received_packet =
176 it->second->last_packet_time_ms;
177 if (time_of_last_received_packet >= 0 &&
178 now_ms - time_of_last_received_packet > kStreamTimeOutMs) {
179 // This over-use detector hasn't received packets for `kStreamTimeOutMs`
180 // milliseconds and is considered stale.
181 delete it->second;
182 overuse_detectors_.erase(it++);
183 } else {
184 // Make sure that we trigger an over-use if any of the over-use detectors
185 // is detecting over-use.
186 if (it->second->detector.State() > bw_state) {
187 bw_state = it->second->detector.State();
188 }
189 ++it;
190 }
191 }
192 // We can't update the estimate if we don't have any active streams.
193 if (overuse_detectors_.empty()) {
194 return;
195 }
196
197 const RateControlInput input(
198 bw_state, OptionalRateFromOptionalBps(incoming_bitrate_.Rate(now_ms)));
199 uint32_t target_bitrate =
200 remote_rate_.Update(&input, Timestamp::Millis(now_ms)).bps<uint32_t>();
201 if (remote_rate_.ValidEstimate()) {
202 process_interval_ms_ = remote_rate_.GetFeedbackInterval().ms();
203 RTC_DCHECK_GT(process_interval_ms_, 0);
204 std::vector<uint32_t> ssrcs;
205 GetSsrcs(&ssrcs);
206 if (observer_)
207 observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate);
208 }
209 }
210
OnRttUpdate(int64_t avg_rtt_ms,int64_t max_rtt_ms)211 void RemoteBitrateEstimatorSingleStream::OnRttUpdate(int64_t avg_rtt_ms,
212 int64_t max_rtt_ms) {
213 MutexLock lock(&mutex_);
214 remote_rate_.SetRtt(TimeDelta::Millis(avg_rtt_ms));
215 }
216
RemoveStream(unsigned int ssrc)217 void RemoteBitrateEstimatorSingleStream::RemoveStream(unsigned int ssrc) {
218 MutexLock lock(&mutex_);
219 SsrcOveruseEstimatorMap::iterator it = overuse_detectors_.find(ssrc);
220 if (it != overuse_detectors_.end()) {
221 delete it->second;
222 overuse_detectors_.erase(it);
223 }
224 }
225
LatestEstimate() const226 DataRate RemoteBitrateEstimatorSingleStream::LatestEstimate() const {
227 MutexLock lock(&mutex_);
228 if (!remote_rate_.ValidEstimate() || overuse_detectors_.empty()) {
229 return DataRate::Zero();
230 }
231 return remote_rate_.LatestEstimate();
232 }
233
GetSsrcs(std::vector<uint32_t> * ssrcs) const234 void RemoteBitrateEstimatorSingleStream::GetSsrcs(
235 std::vector<uint32_t>* ssrcs) const {
236 RTC_DCHECK(ssrcs);
237 ssrcs->resize(overuse_detectors_.size());
238 int i = 0;
239 for (SsrcOveruseEstimatorMap::const_iterator it = overuse_detectors_.begin();
240 it != overuse_detectors_.end(); ++it, ++i) {
241 (*ssrcs)[i] = it->first;
242 }
243 }
244
245 } // namespace webrtc
246