| 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 |