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 |
11 #include "webrtc/modules/congestion_controller/probe_bitrate_estimator.h" | 11 #include "webrtc/modules/congestion_controller/probe_bitrate_estimator.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <sstream> |
14 | 15 |
15 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" | 16 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" |
16 #include "webrtc/rtc_base/checks.h" | 17 #include "webrtc/rtc_base/checks.h" |
17 #include "webrtc/rtc_base/logging.h" | 18 #include "webrtc/rtc_base/logging.h" |
| 19 #include "webrtc/rtc_base/timeutils.h" |
18 | 20 |
19 namespace { | 21 namespace { |
20 // The minumum number of probes we need to receive feedback about in percent | 22 // The minumum number of probes we need to receive feedback about in percent |
21 // in order to have a valid estimate. | 23 // in order to have a valid estimate. |
22 constexpr int kMinReceivedProbesPercent = 80; | 24 constexpr int kMinReceivedProbesPercent = 80; |
23 | 25 |
24 // The minumum number of bytes we need to receive feedback about in percent | 26 // The minumum number of bytes we need to receive feedback about in percent |
25 // in order to have a valid estimate. | 27 // in order to have a valid estimate. |
26 constexpr int kMinReceivedBytesPercent = 80; | 28 constexpr int kMinReceivedBytesPercent = 80; |
27 | 29 |
(...skipping 26 matching lines...) Expand all Loading... |
54 : event_log_(event_log) {} | 56 : event_log_(event_log) {} |
55 | 57 |
56 ProbeBitrateEstimator::~ProbeBitrateEstimator() = default; | 58 ProbeBitrateEstimator::~ProbeBitrateEstimator() = default; |
57 | 59 |
58 int ProbeBitrateEstimator::HandleProbeAndEstimateBitrate( | 60 int ProbeBitrateEstimator::HandleProbeAndEstimateBitrate( |
59 const PacketFeedback& packet_feedback) { | 61 const PacketFeedback& packet_feedback) { |
60 int cluster_id = packet_feedback.pacing_info.probe_cluster_id; | 62 int cluster_id = packet_feedback.pacing_info.probe_cluster_id; |
61 RTC_DCHECK_NE(cluster_id, PacedPacketInfo::kNotAProbe); | 63 RTC_DCHECK_NE(cluster_id, PacedPacketInfo::kNotAProbe); |
62 | 64 |
63 EraseOldClusters(packet_feedback.arrival_time_ms - kMaxClusterHistoryMs); | 65 EraseOldClusters(packet_feedback.arrival_time_ms - kMaxClusterHistoryMs); |
| 66 if (start_ == 0) |
| 67 start_ = packet_feedback.send_time_ms; |
| 68 |
| 69 Print("Feedback:%5u id:%3d send:%8ld receive:%8ld size:%4lu", |
| 70 packet_feedback.sequence_number, |
| 71 packet_feedback.pacing_info.probe_cluster_id, |
| 72 packet_feedback.send_time_ms - start_, |
| 73 packet_feedback.arrival_time_ms - start_, packet_feedback.payload_size); |
64 | 74 |
65 int payload_size_bits = packet_feedback.payload_size * 8; | 75 int payload_size_bits = packet_feedback.payload_size * 8; |
66 AggregatedCluster* cluster = &clusters_[cluster_id]; | 76 AggregatedCluster* cluster = &clusters_[cluster_id]; |
67 | 77 |
68 if (packet_feedback.send_time_ms < cluster->first_send_ms) { | 78 if (packet_feedback.send_time_ms < cluster->first_send_ms) { |
69 cluster->first_send_ms = packet_feedback.send_time_ms; | 79 cluster->first_send_ms = packet_feedback.send_time_ms; |
70 } | 80 } |
71 if (packet_feedback.send_time_ms > cluster->last_send_ms) { | 81 if (packet_feedback.send_time_ms > cluster->last_send_ms) { |
72 cluster->last_send_ms = packet_feedback.send_time_ms; | 82 cluster->last_send_ms = packet_feedback.send_time_ms; |
73 cluster->size_last_send = payload_size_bits; | 83 cluster->size_last_send = payload_size_bits; |
(...skipping 17 matching lines...) Expand all Loading... |
91 kMinReceivedBytesPercent / 100; | 101 kMinReceivedBytesPercent / 100; |
92 if (cluster->num_probes < min_probes || cluster->size_total < min_bytes * 8) | 102 if (cluster->num_probes < min_probes || cluster->size_total < min_bytes * 8) |
93 return -1; | 103 return -1; |
94 | 104 |
95 float send_interval_ms = cluster->last_send_ms - cluster->first_send_ms; | 105 float send_interval_ms = cluster->last_send_ms - cluster->first_send_ms; |
96 float receive_interval_ms = | 106 float receive_interval_ms = |
97 cluster->last_receive_ms - cluster->first_receive_ms; | 107 cluster->last_receive_ms - cluster->first_receive_ms; |
98 | 108 |
99 if (send_interval_ms <= 0 || send_interval_ms > kMaxProbeIntervalMs || | 109 if (send_interval_ms <= 0 || send_interval_ms > kMaxProbeIntervalMs || |
100 receive_interval_ms <= 0 || receive_interval_ms > kMaxProbeIntervalMs) { | 110 receive_interval_ms <= 0 || receive_interval_ms > kMaxProbeIntervalMs) { |
| 111 std::stringstream ss1; |
| 112 ss1 << "Probing unsuccessful, invalid send/receive interval" |
| 113 << " [cluster id: " << cluster_id |
| 114 << "] [send interval: " << send_interval_ms << " ms]" |
| 115 << " [receive interval: " << receive_interval_ms << " ms]"; |
101 LOG(LS_INFO) << "Probing unsuccessful, invalid send/receive interval" | 116 LOG(LS_INFO) << "Probing unsuccessful, invalid send/receive interval" |
102 << " [cluster id: " << cluster_id | 117 << " [cluster id: " << cluster_id |
103 << "] [send interval: " << send_interval_ms << " ms]" | 118 << "] [send interval: " << send_interval_ms << " ms]" |
104 << " [receive interval: " << receive_interval_ms << " ms]"; | 119 << " [receive interval: " << receive_interval_ms << " ms]"; |
| 120 Print("%s", ss1.str().c_str()); |
105 if (event_log_) { | 121 if (event_log_) { |
106 event_log_->LogProbeResultFailure(cluster_id, | 122 event_log_->LogProbeResultFailure(cluster_id, |
107 kInvalidSendReceiveInterval); | 123 kInvalidSendReceiveInterval); |
108 } | 124 } |
109 return -1; | 125 return -1; |
110 } | 126 } |
111 // Since the |send_interval_ms| does not include the time it takes to actually | 127 // Since the |send_interval_ms| does not include the time it takes to actually |
112 // send the last packet the size of the last sent packet should not be | 128 // send the last packet the size of the last sent packet should not be |
113 // included when calculating the send bitrate. | 129 // included when calculating the send bitrate. |
114 RTC_DCHECK_GT(cluster->size_total, cluster->size_last_send); | 130 RTC_DCHECK_GT(cluster->size_total, cluster->size_last_send); |
115 float send_size = cluster->size_total - cluster->size_last_send; | 131 float send_size_bits = cluster->size_total - cluster->size_last_send; |
116 float send_bps = send_size / send_interval_ms * 1000; | 132 float send_bps = send_size_bits / send_interval_ms * 1000; |
117 | 133 |
118 // Since the |receive_interval_ms| does not include the time it takes to | 134 // Since the |receive_interval_ms| does not include the time it takes to |
119 // actually receive the first packet the size of the first received packet | 135 // actually receive the first packet the size of the first received packet |
120 // should not be included when calculating the receive bitrate. | 136 // should not be included when calculating the receive bitrate. |
121 RTC_DCHECK_GT(cluster->size_total, cluster->size_first_receive); | 137 RTC_DCHECK_GT(cluster->size_total, cluster->size_first_receive); |
122 float receive_size = cluster->size_total - cluster->size_first_receive; | 138 float receive_size_bits = cluster->size_total - cluster->size_first_receive; |
123 float receive_bps = receive_size / receive_interval_ms * 1000; | 139 float receive_bps = receive_size_bits / receive_interval_ms * 1000; |
124 | 140 |
125 float ratio = receive_bps / send_bps; | 141 float ratio = receive_bps / send_bps; |
126 if (ratio > kMaxValidRatio) { | 142 if (ratio > kMaxValidRatio) { |
| 143 std::stringstream ss2; |
| 144 ss2 << "Probing unsuccessful, receive/send ratio too high" |
| 145 << " [cluster id: " << cluster_id << "] [send: " << send_size_bits / 8 |
| 146 << " bytes / " << send_interval_ms << " ms = " << send_bps / 1000 |
| 147 << " kb/s]" |
| 148 << " [receive: " << receive_size_bits / 8 << " bytes / " |
| 149 << receive_interval_ms << " ms = " << receive_bps / 1000 << " kb/s]" |
| 150 << " [ratio: " << receive_bps / 1000 << " / " << send_bps / 1000 |
| 151 << " = " << ratio << " > kMaxValidRatio (" << kMaxValidRatio << ")]"; |
| 152 Print("%s", ss2.str().c_str()); |
127 LOG(LS_INFO) << "Probing unsuccessful, receive/send ratio too high" | 153 LOG(LS_INFO) << "Probing unsuccessful, receive/send ratio too high" |
128 << " [cluster id: " << cluster_id << "] [send: " << send_size | 154 << " [cluster id: " << cluster_id |
129 << " bytes / " << send_interval_ms | 155 << "] [send: " << send_size_bits / 8 << " bytes / " |
130 << " ms = " << send_bps / 1000 << " kb/s]" | 156 << send_interval_ms << " ms = " << send_bps / 1000 << " kb/s]" |
131 << " [receive: " << receive_size << " bytes / " | 157 << " [receive: " << receive_size_bits / 8 << " bytes / " |
132 << receive_interval_ms << " ms = " << receive_bps / 1000 | 158 << receive_interval_ms << " ms = " << receive_bps / 1000 |
133 << " kb/s]" | 159 << " kb/s]" |
134 << " [ratio: " << receive_bps / 1000 << " / " | 160 << " [ratio: " << receive_bps / 1000 << " / " |
135 << send_bps / 1000 << " = " << ratio << " > kMaxValidRatio (" | 161 << send_bps / 1000 << " = " << ratio << " > kMaxValidRatio (" |
136 << kMaxValidRatio << ")]"; | 162 << kMaxValidRatio << ")]"; |
137 if (event_log_) | 163 if (event_log_) |
138 event_log_->LogProbeResultFailure(cluster_id, kInvalidSendReceiveRatio); | 164 event_log_->LogProbeResultFailure(cluster_id, kInvalidSendReceiveRatio); |
139 return -1; | 165 return -1; |
140 } | 166 } |
| 167 std::stringstream ss3; |
| 168 ss3 << "Probing successful" |
| 169 << " [cluster id: " << cluster_id << "] [send: " << send_size_bits / 8 |
| 170 << " bytes / " << send_interval_ms << " ms = " << send_bps / 1000 |
| 171 << " kb/s]" |
| 172 << " [receive: " << receive_size_bits / 8 << " bytes / " |
| 173 << receive_interval_ms << " ms = " << receive_bps / 1000 << " kb/s]"; |
141 LOG(LS_INFO) << "Probing successful" | 174 LOG(LS_INFO) << "Probing successful" |
142 << " [cluster id: " << cluster_id << "] [send: " << send_size | 175 << " [cluster id: " << cluster_id |
143 << " bytes / " << send_interval_ms << " ms = " << send_bps / 1000 | 176 << "] [send: " << send_size_bits / 8 << " bytes / " |
144 << " kb/s]" | 177 << send_interval_ms << " ms = " << send_bps / 1000 << " kb/s]" |
145 << " [receive: " << receive_size << " bytes / " | 178 << " [receive: " << receive_size_bits / 8 << " bytes / " |
146 << receive_interval_ms << " ms = " << receive_bps / 1000 | 179 << receive_interval_ms << " ms = " << receive_bps / 1000 |
147 << " kb/s]"; | 180 << " kb/s]"; |
148 | 181 |
149 float res = std::min(send_bps, receive_bps); | 182 float res = std::min(send_bps, receive_bps); |
150 // If we're receiving at significantly lower bitrate than we were sending at, | 183 // If we're receiving at significantly lower bitrate than we were sending at, |
151 // it suggests that we've found the true capacity of the link. In this case, | 184 // it suggests that we've found the true capacity of the link. In this case, |
152 // set the target bitrate slightly lower to not immediately overuse. | 185 // set the target bitrate slightly lower to not immediately overuse. |
153 if (receive_bps < kMinRatioForUnsaturatedLink * send_bps) { | 186 if (receive_bps < kMinRatioForUnsaturatedLink * send_bps) { |
154 RTC_DCHECK_GT(send_bps, receive_bps); | 187 RTC_DCHECK_GT(send_bps, receive_bps); |
155 res = kTargetUtilizationFraction * receive_bps; | 188 res = kTargetUtilizationFraction * receive_bps; |
156 } | 189 } |
157 if (event_log_) | |
158 event_log_->LogProbeResultSuccess(cluster_id, res); | |
159 estimated_bitrate_bps_ = rtc::Optional<int>(res); | 190 estimated_bitrate_bps_ = rtc::Optional<int>(res); |
| 191 last_estimate_update_ms_ = rtc::TimeMillis(); |
| 192 cluster_id_ = cluster_id; |
| 193 Print("%s, estimated kbps: %d", ss3.str().c_str(), |
| 194 *estimated_bitrate_bps_ / 1000); |
160 return *estimated_bitrate_bps_; | 195 return *estimated_bitrate_bps_; |
161 } | 196 } |
162 | 197 |
163 rtc::Optional<int> | 198 rtc::Optional<int> ProbeBitrateEstimator::FetchAndResetLastEstimatedBitrateBps( |
164 ProbeBitrateEstimator::FetchAndResetLastEstimatedBitrateBps() { | 199 int64_t timeout) { |
| 200 int64_t now_ms = rtc::TimeMillis(); |
165 rtc::Optional<int> estimated_bitrate_bps = estimated_bitrate_bps_; | 201 rtc::Optional<int> estimated_bitrate_bps = estimated_bitrate_bps_; |
| 202 |
| 203 if (!estimated_bitrate_bps || now_ms < last_estimate_update_ms_ + timeout) |
| 204 return rtc::Optional<int>(); |
| 205 |
| 206 Print("Probe result %d kbps", *estimated_bitrate_bps / 1000); |
| 207 |
| 208 if (event_log_) |
| 209 event_log_->LogProbeResultSuccess(cluster_id_, *estimated_bitrate_bps); |
| 210 |
166 estimated_bitrate_bps_.reset(); | 211 estimated_bitrate_bps_.reset(); |
167 return estimated_bitrate_bps; | 212 return estimated_bitrate_bps; |
168 } | 213 } |
169 | 214 |
170 void ProbeBitrateEstimator::EraseOldClusters(int64_t timestamp_ms) { | 215 void ProbeBitrateEstimator::EraseOldClusters(int64_t timestamp_ms) { |
171 for (auto it = clusters_.begin(); it != clusters_.end();) { | 216 for (auto it = clusters_.begin(); it != clusters_.end();) { |
172 if (it->second.last_receive_ms < timestamp_ms) { | 217 if (it->second.last_receive_ms < timestamp_ms) { |
173 it = clusters_.erase(it); | 218 it = clusters_.erase(it); |
174 } else { | 219 } else { |
175 ++it; | 220 ++it; |
176 } | 221 } |
177 } | 222 } |
178 } | 223 } |
179 } // namespace webrtc | 224 } // namespace webrtc |
OLD | NEW |