OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... | |
28 constexpr int kTimestampGroupLengthMs = 5; | 28 constexpr int kTimestampGroupLengthMs = 5; |
29 constexpr int kAbsSendTimeFraction = 18; | 29 constexpr int kAbsSendTimeFraction = 18; |
30 constexpr int kAbsSendTimeInterArrivalUpshift = 8; | 30 constexpr int kAbsSendTimeInterArrivalUpshift = 8; |
31 constexpr int kInterArrivalShift = | 31 constexpr int kInterArrivalShift = |
32 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; | 32 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; |
33 constexpr double kTimestampToMs = | 33 constexpr double kTimestampToMs = |
34 1000.0 / static_cast<double>(1 << kInterArrivalShift); | 34 1000.0 / static_cast<double>(1 << kInterArrivalShift); |
35 // This ssrc is used to fulfill the current API but will be removed | 35 // This ssrc is used to fulfill the current API but will be removed |
36 // after the API has been changed. | 36 // after the API has been changed. |
37 constexpr uint32_t kFixedSsrc = 0; | 37 constexpr uint32_t kFixedSsrc = 0; |
38 constexpr int kRateWindowMs = 250; | |
39 | |
38 } // namespace | 40 } // namespace |
39 | 41 |
40 namespace webrtc { | 42 namespace webrtc { |
43 DelayBasedBwe::RateEstimator::RateEstimator() | |
44 : sum_(0), | |
45 count_(0), | |
46 bitrate_estimate_(300.0f), | |
47 bitrate_estimate_std_(2000.0f) {} | |
48 | |
49 void DelayBasedBwe::RateEstimator::Update(int64_t now_ms, int bytes) { | |
50 UpdateWindow(now_ms, bytes); | |
51 RTC_DCHECK_GE(sum_, 0); | |
52 RTC_DCHECK_GE(count_, 0); | |
53 float bitrate_sample = 8.0f * sum_ / static_cast<float>(kRateWindowMs); | |
54 // Define the sample uncertainty as a function of how far away it is from the | |
55 // current estimate, and how many payloads it based on. | |
terelius
2016/10/21 10:15:52
nit: it is based on
stefan-webrtc
2016/10/24 10:55:14
Done.
| |
56 float sample_uncertainty = | |
terelius
2016/10/21 10:15:52
This essentially means that we make smaller change
stefan-webrtc
2016/10/24 10:55:14
Yes, maybe. I'm worried that the window would have
terelius
2016/10/24 11:20:38
Maybe it is difficult to do what I suggested since
| |
57 std::max(5 * (5 - count_), 1) * (bitrate_estimate_ - bitrate_sample); | |
58 float sample_var = std::max(sample_uncertainty * sample_uncertainty, 1.0f); | |
59 // Update a bayesian estimate of the rate, weighting it lower if the sample | |
60 // uncertainty is large. | |
61 // The bitrate estimate uncertainty is increased with each update to model | |
62 // the possibility that the bitrate can change over time. | |
63 // TODO(holmer): Consider increasing the uncertainty every N milliseconds | |
64 // instead of every update. | |
65 float bitrate_estimate_std = bitrate_estimate_std_ + 25.0f; | |
66 float bitrate_estimate_var = bitrate_estimate_std * bitrate_estimate_std; | |
67 float denom = 1.0f / sample_var + 1.0f / bitrate_estimate_var; | |
68 bitrate_estimate_std_ = sqrt(1.0f / denom); | |
69 bitrate_estimate_ = | |
terelius
2016/10/21 10:15:52
I believe that the reason we are slow to recover f
stefan-webrtc
2016/10/24 10:55:14
Good point. The problem would occur if for instanc
| |
70 (bitrate_estimate_ / bitrate_estimate_var + bitrate_sample / sample_var) * | |
71 bitrate_estimate_std_ * bitrate_estimate_std_; | |
terelius
2016/10/21 10:15:52
This update could alternatively be written as
est
stefan-webrtc
2016/10/24 10:55:14
Do you prefer that?
terelius
2016/10/24 11:20:38
I think I'd prefer
estimate = (sample_var * estima
stefan-webrtc
2016/10/25 11:04:33
Yes, the sums to 1 is a nice thing to show clearly
| |
72 } | |
73 | |
74 void DelayBasedBwe::RateEstimator::UpdateWindow(int64_t now_ms, int bytes) { | |
75 // Reset if time moves backwards. | |
76 if (!payloads_.empty() && payloads_.back().first > now_ms) { | |
77 payloads_.clear(); | |
78 sum_ = 0; | |
79 } | |
80 payloads_.push_back(std::make_pair(now_ms, bytes)); | |
81 sum_ += bytes; | |
82 ++count_; | |
83 while (!payloads_.empty()) { | |
84 auto oldest = payloads_.front(); | |
85 if (oldest.first > now_ms - kRateWindowMs) | |
86 break; | |
87 sum_ -= oldest.second; | |
88 payloads_.pop_front(); | |
89 --count_; | |
90 } | |
91 } | |
92 | |
93 int DelayBasedBwe::RateEstimator::bitrate_estimate() const { | |
94 return bitrate_estimate_ * 1000; | |
terelius
2016/10/21 10:15:52
Why multiply by 1000?
stefan-webrtc
2016/10/24 10:55:14
I wanted the returned value to be bits/s. Should p
terelius
2016/10/24 11:20:38
Oh, right. It would have been bits/ms otherwise.
| |
95 } | |
41 | 96 |
42 DelayBasedBwe::DelayBasedBwe(Clock* clock) | 97 DelayBasedBwe::DelayBasedBwe(Clock* clock) |
43 : clock_(clock), | 98 : clock_(clock), |
44 inter_arrival_(), | 99 inter_arrival_(), |
45 estimator_(), | 100 estimator_(), |
46 detector_(OverUseDetectorOptions()), | 101 detector_(OverUseDetectorOptions()), |
47 receiver_incoming_bitrate_(kBitrateWindowMs, 8000), | 102 receiver_incoming_bitrate_(), |
48 last_update_ms_(-1), | 103 last_update_ms_(-1), |
49 last_seen_packet_ms_(-1), | 104 last_seen_packet_ms_(-1), |
50 uma_recorded_(false) { | 105 uma_recorded_(false) { |
51 network_thread_.DetachFromThread(); | 106 network_thread_.DetachFromThread(); |
52 } | 107 } |
53 | 108 |
54 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( | 109 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( |
55 const std::vector<PacketInfo>& packet_feedback_vector) { | 110 const std::vector<PacketInfo>& packet_feedback_vector) { |
56 RTC_DCHECK(network_thread_.CalledOnValidThread()); | 111 RTC_DCHECK(network_thread_.CalledOnValidThread()); |
57 if (!uma_recorded_) { | 112 if (!uma_recorded_) { |
58 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, | 113 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, |
59 BweNames::kSendSideTransportSeqNum, | 114 BweNames::kSendSideTransportSeqNum, |
60 BweNames::kBweNamesMax); | 115 BweNames::kBweNamesMax); |
61 uma_recorded_ = true; | 116 uma_recorded_ = true; |
62 } | 117 } |
63 Result aggregated_result; | 118 Result aggregated_result; |
64 for (const auto& packet_info : packet_feedback_vector) { | 119 for (const auto& packet_info : packet_feedback_vector) { |
65 Result result = IncomingPacketInfo(packet_info); | 120 Result result = IncomingPacketInfo(packet_info); |
66 if (result.updated) | 121 if (result.updated) |
67 aggregated_result = result; | 122 aggregated_result = result; |
68 } | 123 } |
69 return aggregated_result; | 124 return aggregated_result; |
70 } | 125 } |
71 | 126 |
72 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo( | 127 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo( |
73 const PacketInfo& info) { | 128 const PacketInfo& info) { |
74 int64_t now_ms = clock_->TimeInMilliseconds(); | 129 int64_t now_ms = clock_->TimeInMilliseconds(); |
75 | 130 |
76 receiver_incoming_bitrate_.Update(info.payload_size, info.arrival_time_ms); | 131 receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size); |
77 Result result; | 132 Result result; |
78 // Reset if the stream has timed out. | 133 // Reset if the stream has timed out. |
79 if (last_seen_packet_ms_ == -1 || | 134 if (last_seen_packet_ms_ == -1 || |
80 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { | 135 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { |
81 inter_arrival_.reset( | 136 inter_arrival_.reset( |
82 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, | 137 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, |
83 kTimestampToMs, true)); | 138 kTimestampToMs, true)); |
84 estimator_.reset(new OveruseEstimator(OverUseDetectorOptions())); | 139 estimator_.reset(new OveruseEstimator(OverUseDetectorOptions())); |
85 } | 140 } |
86 last_seen_packet_ms_ = now_ms; | 141 last_seen_packet_ms_ = now_ms; |
(...skipping 19 matching lines...) Expand all Loading... | |
106 info.arrival_time_ms); | 161 info.arrival_time_ms); |
107 detector_.Detect(estimator_->offset(), ts_delta_ms, | 162 detector_.Detect(estimator_->offset(), ts_delta_ms, |
108 estimator_->num_of_deltas(), info.arrival_time_ms); | 163 estimator_->num_of_deltas(), info.arrival_time_ms); |
109 } | 164 } |
110 | 165 |
111 int probing_bps = 0; | 166 int probing_bps = 0; |
112 if (info.probe_cluster_id != PacketInfo::kNotAProbe) { | 167 if (info.probe_cluster_id != PacketInfo::kNotAProbe) { |
113 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info); | 168 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info); |
114 } | 169 } |
115 | 170 |
171 int acked_bitrate_bps = receiver_incoming_bitrate_.bitrate_estimate(); | |
116 // Currently overusing the bandwidth. | 172 // Currently overusing the bandwidth. |
117 if (detector_.State() == kBwOverusing) { | 173 if (detector_.State() == kBwOverusing) { |
118 rtc::Optional<uint32_t> incoming_rate = | 174 if (rate_control_.TimeToReduceFurther(now_ms, acked_bitrate_bps)) { |
119 receiver_incoming_bitrate_.Rate(info.arrival_time_ms); | 175 result.updated = |
120 if (incoming_rate && | 176 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps, |
121 rate_control_.TimeToReduceFurther(now_ms, *incoming_rate)) { | 177 &result.target_bitrate_bps); |
122 result.updated = UpdateEstimate(info.arrival_time_ms, now_ms, | |
123 &result.target_bitrate_bps); | |
124 } | 178 } |
125 } else if (probing_bps > 0) { | 179 } else if (probing_bps > 0) { |
126 // No overuse, but probing measured a bitrate. | 180 // No overuse, but probing measured a bitrate. |
127 rate_control_.SetEstimate(probing_bps, info.arrival_time_ms); | 181 rate_control_.SetEstimate(probing_bps, info.arrival_time_ms); |
128 result.probe = true; | 182 result.probe = true; |
129 result.updated = UpdateEstimate(info.arrival_time_ms, now_ms, | 183 result.updated = |
130 &result.target_bitrate_bps); | 184 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps, |
185 &result.target_bitrate_bps); | |
131 } | 186 } |
132 rtc::Optional<uint32_t> incoming_rate = | |
133 receiver_incoming_bitrate_.Rate(info.arrival_time_ms); | |
134 if (!result.updated && | 187 if (!result.updated && |
135 (last_update_ms_ == -1 || | 188 (last_update_ms_ == -1 || |
136 now_ms - last_update_ms_ > rate_control_.GetFeedbackInterval())) { | 189 now_ms - last_update_ms_ > rate_control_.GetFeedbackInterval())) { |
137 result.updated = UpdateEstimate(info.arrival_time_ms, now_ms, | 190 result.updated = |
138 &result.target_bitrate_bps); | 191 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps, |
192 &result.target_bitrate_bps); | |
139 } | 193 } |
140 if (result.updated) | 194 if (result.updated) |
141 last_update_ms_ = now_ms; | 195 last_update_ms_ = now_ms; |
142 | 196 |
143 return result; | 197 return result; |
144 } | 198 } |
145 | 199 |
146 bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms, | 200 bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms, |
147 int64_t now_ms, | 201 int64_t now_ms, |
202 int acked_bitrate_bps, | |
148 uint32_t* target_bitrate_bps) { | 203 uint32_t* target_bitrate_bps) { |
149 // The first overuse should immediately trigger a new estimate. | 204 if (acked_bitrate_bps <= 0) |
150 // We also have to update the estimate immediately if we are overusing | 205 return false; |
151 // and the target bitrate is too high compared to what we are receiving. | |
152 const RateControlInput input(detector_.State(), | 206 const RateControlInput input(detector_.State(), |
153 receiver_incoming_bitrate_.Rate(arrival_time_ms), | 207 rtc::Optional<uint32_t>(acked_bitrate_bps), |
154 estimator_->var_noise()); | 208 estimator_->var_noise()); |
155 rate_control_.Update(&input, now_ms); | 209 rate_control_.Update(&input, now_ms); |
156 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); | 210 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); |
157 return rate_control_.ValidEstimate(); | 211 return rate_control_.ValidEstimate(); |
158 } | 212 } |
159 | 213 |
160 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { | 214 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { |
161 rate_control_.SetRtt(avg_rtt_ms); | 215 rate_control_.SetRtt(avg_rtt_ms); |
162 } | 216 } |
163 | 217 |
(...skipping 12 matching lines...) Expand all Loading... | |
176 *bitrate_bps = rate_control_.LatestEstimate(); | 230 *bitrate_bps = rate_control_.LatestEstimate(); |
177 return true; | 231 return true; |
178 } | 232 } |
179 | 233 |
180 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { | 234 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { |
181 // Called from both the configuration thread and the network thread. Shouldn't | 235 // Called from both the configuration thread and the network thread. Shouldn't |
182 // be called from the network thread in the future. | 236 // be called from the network thread in the future. |
183 rate_control_.SetMinBitrate(min_bitrate_bps); | 237 rate_control_.SetMinBitrate(min_bitrate_bps); |
184 } | 238 } |
185 } // namespace webrtc | 239 } // namespace webrtc |
OLD | NEW |