OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 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/transport_feedback_adapter.h" | 11 #include "webrtc/modules/congestion_controller/transport_feedback_adapter.h" |
12 | 12 |
| 13 #include <algorithm> |
| 14 |
13 #include "webrtc/modules/congestion_controller/delay_based_bwe.h" | 15 #include "webrtc/modules/congestion_controller/delay_based_bwe.h" |
14 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" | 16 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
15 #include "webrtc/rtc_base/checks.h" | 17 #include "webrtc/rtc_base/checks.h" |
16 #include "webrtc/rtc_base/logging.h" | 18 #include "webrtc/rtc_base/logging.h" |
17 #include "webrtc/rtc_base/mod_ops.h" | 19 #include "webrtc/rtc_base/mod_ops.h" |
18 #include "webrtc/system_wrappers/include/field_trial.h" | 20 #include "webrtc/system_wrappers/include/field_trial.h" |
19 | 21 |
20 namespace webrtc { | 22 namespace webrtc { |
21 | 23 |
22 const int64_t kNoTimestamp = -1; | 24 const int64_t kNoTimestamp = -1; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 void TransportFeedbackAdapter::SetNetworkIds(uint16_t local_id, | 98 void TransportFeedbackAdapter::SetNetworkIds(uint16_t local_id, |
97 uint16_t remote_id) { | 99 uint16_t remote_id) { |
98 rtc::CritScope cs(&lock_); | 100 rtc::CritScope cs(&lock_); |
99 local_net_id_ = local_id; | 101 local_net_id_ = local_id; |
100 remote_net_id_ = remote_id; | 102 remote_net_id_ = remote_id; |
101 } | 103 } |
102 | 104 |
103 std::vector<PacketFeedback> TransportFeedbackAdapter::GetPacketFeedbackVector( | 105 std::vector<PacketFeedback> TransportFeedbackAdapter::GetPacketFeedbackVector( |
104 const rtcp::TransportFeedback& feedback) { | 106 const rtcp::TransportFeedback& feedback) { |
105 int64_t timestamp_us = feedback.GetBaseTimeUs(); | 107 int64_t timestamp_us = feedback.GetBaseTimeUs(); |
| 108 int64_t now_ms = clock_->TimeInMilliseconds(); |
106 // Add timestamp deltas to a local time base selected on first packet arrival. | 109 // Add timestamp deltas to a local time base selected on first packet arrival. |
107 // This won't be the true time base, but makes it easier to manually inspect | 110 // This won't be the true time base, but makes it easier to manually inspect |
108 // time stamps. | 111 // time stamps. |
109 if (last_timestamp_us_ == kNoTimestamp) { | 112 if (last_timestamp_us_ == kNoTimestamp) { |
110 current_offset_ms_ = clock_->TimeInMilliseconds(); | 113 current_offset_ms_ = now_ms; |
111 } else { | 114 } else { |
112 int64_t delta = timestamp_us - last_timestamp_us_; | 115 int64_t delta = timestamp_us - last_timestamp_us_; |
113 | 116 |
114 // Detect and compensate for wrap-arounds in base time. | 117 // Detect and compensate for wrap-arounds in base time. |
115 if (std::abs(delta - kBaseTimestampRangeSizeUs) < std::abs(delta)) { | 118 if (std::abs(delta - kBaseTimestampRangeSizeUs) < std::abs(delta)) { |
116 delta -= kBaseTimestampRangeSizeUs; // Wrap backwards. | 119 delta -= kBaseTimestampRangeSizeUs; // Wrap backwards. |
117 } else if (std::abs(delta + kBaseTimestampRangeSizeUs) < std::abs(delta)) { | 120 } else if (std::abs(delta + kBaseTimestampRangeSizeUs) < std::abs(delta)) { |
118 delta += kBaseTimestampRangeSizeUs; // Wrap forwards. | 121 delta += kBaseTimestampRangeSizeUs; // Wrap forwards. |
119 } | 122 } |
120 | 123 |
121 current_offset_ms_ += delta / 1000; | 124 current_offset_ms_ += delta / 1000; |
122 } | 125 } |
123 last_timestamp_us_ = timestamp_us; | 126 last_timestamp_us_ = timestamp_us; |
124 | 127 |
125 std::vector<PacketFeedback> packet_feedback_vector; | 128 std::vector<PacketFeedback> packet_feedback_vector; |
126 if (feedback.GetPacketStatusCount() == 0) { | 129 if (feedback.GetPacketStatusCount() == 0) { |
127 LOG(LS_INFO) << "Empty transport feedback packet received."; | 130 LOG(LS_INFO) << "Empty transport feedback packet received."; |
128 return packet_feedback_vector; | 131 return packet_feedback_vector; |
129 } | 132 } |
130 packet_feedback_vector.reserve(feedback.GetPacketStatusCount()); | 133 packet_feedback_vector.reserve(feedback.GetPacketStatusCount()); |
131 | 134 int64_t feedback_rtt = -1; |
132 { | 135 { |
133 rtc::CritScope cs(&lock_); | 136 rtc::CritScope cs(&lock_); |
134 size_t failed_lookups = 0; | 137 size_t failed_lookups = 0; |
135 int64_t offset_us = 0; | 138 int64_t offset_us = 0; |
136 int64_t timestamp_ms = 0; | 139 int64_t timestamp_ms = 0; |
137 uint16_t seq_num = feedback.GetBaseSequence(); | 140 uint16_t seq_num = feedback.GetBaseSequence(); |
138 for (const auto& packet : feedback.GetReceivedPackets()) { | 141 for (const auto& packet : feedback.GetReceivedPackets()) { |
139 // Insert into the vector those unreceived packets which precede this | 142 // Insert into the vector those unreceived packets which precede this |
140 // iteration's received packet. | 143 // iteration's received packet. |
141 for (; seq_num != packet.sequence_number(); ++seq_num) { | 144 for (; seq_num != packet.sequence_number(); ++seq_num) { |
142 PacketFeedback packet_feedback(PacketFeedback::kNotReceived, seq_num); | 145 PacketFeedback packet_feedback(PacketFeedback::kNotReceived, seq_num); |
143 // Note: Element not removed from history because it might be reported | 146 // Note: Element not removed from history because it might be reported |
144 // as received by another feedback. | 147 // as received by another feedback. |
145 if (!send_time_history_.GetFeedback(&packet_feedback, false)) | 148 if (!send_time_history_.GetFeedback(&packet_feedback, false)) |
146 ++failed_lookups; | 149 ++failed_lookups; |
147 if (packet_feedback.local_net_id == local_net_id_ && | 150 if (packet_feedback.local_net_id == local_net_id_ && |
148 packet_feedback.remote_net_id == remote_net_id_) { | 151 packet_feedback.remote_net_id == remote_net_id_) { |
149 packet_feedback_vector.push_back(packet_feedback); | 152 packet_feedback_vector.push_back(packet_feedback); |
150 } | 153 } |
151 } | 154 } |
152 | 155 |
153 // Handle this iteration's received packet. | 156 // Handle this iteration's received packet. |
154 offset_us += packet.delta_us(); | 157 offset_us += packet.delta_us(); |
155 timestamp_ms = current_offset_ms_ + (offset_us / 1000); | 158 timestamp_ms = current_offset_ms_ + (offset_us / 1000); |
156 PacketFeedback packet_feedback(timestamp_ms, packet.sequence_number()); | 159 PacketFeedback packet_feedback(timestamp_ms, packet.sequence_number()); |
157 if (!send_time_history_.GetFeedback(&packet_feedback, true)) | 160 if (!send_time_history_.GetFeedback(&packet_feedback, true)) |
158 ++failed_lookups; | 161 ++failed_lookups; |
159 if (packet_feedback.local_net_id == local_net_id_ && | 162 if (packet_feedback.local_net_id == local_net_id_ && |
160 packet_feedback.remote_net_id == remote_net_id_) { | 163 packet_feedback.remote_net_id == remote_net_id_) { |
| 164 if (packet_feedback.send_time_ms >= 0) { |
| 165 int64_t rtt = now_ms - packet_feedback.send_time_ms; |
| 166 // max() is used to account for feedback being delayed by the |
| 167 // receiver. |
| 168 feedback_rtt = std::max(rtt, feedback_rtt); |
| 169 } |
161 packet_feedback_vector.push_back(packet_feedback); | 170 packet_feedback_vector.push_back(packet_feedback); |
162 } | 171 } |
163 | 172 |
164 ++seq_num; | 173 ++seq_num; |
165 } | 174 } |
166 | 175 |
167 if (failed_lookups > 0) { | 176 if (failed_lookups > 0) { |
168 LOG(LS_WARNING) << "Failed to lookup send time for " << failed_lookups | 177 LOG(LS_WARNING) << "Failed to lookup send time for " << failed_lookups |
169 << " packet" << (failed_lookups > 1 ? "s" : "") | 178 << " packet" << (failed_lookups > 1 ? "s" : "") |
170 << ". Send time history too small?"; | 179 << ". Send time history too small?"; |
171 } | 180 } |
| 181 if (feedback_rtt > -1) { |
| 182 feedback_rtts_.push_back(feedback_rtt); |
| 183 const size_t kFeedbackRttWindow = 32; |
| 184 if (feedback_rtts_.size() > kFeedbackRttWindow) |
| 185 feedback_rtts_.pop_front(); |
| 186 min_feedback_rtt_.emplace( |
| 187 *std::min_element(feedback_rtts_.begin(), feedback_rtts_.end())); |
| 188 } |
172 } | 189 } |
173 return packet_feedback_vector; | 190 return packet_feedback_vector; |
174 } | 191 } |
175 | 192 |
176 void TransportFeedbackAdapter::OnTransportFeedback( | 193 void TransportFeedbackAdapter::OnTransportFeedback( |
177 const rtcp::TransportFeedback& feedback) { | 194 const rtcp::TransportFeedback& feedback) { |
178 last_packet_feedback_vector_ = GetPacketFeedbackVector(feedback); | 195 last_packet_feedback_vector_ = GetPacketFeedbackVector(feedback); |
179 { | 196 { |
180 rtc::CritScope cs(&observers_lock_); | 197 rtc::CritScope cs(&observers_lock_); |
181 for (auto observer : observers_) { | 198 for (auto observer : observers_) { |
182 observer->OnPacketFeedbackVector(last_packet_feedback_vector_); | 199 observer->OnPacketFeedbackVector(last_packet_feedback_vector_); |
183 } | 200 } |
184 } | 201 } |
185 } | 202 } |
186 | 203 |
187 std::vector<PacketFeedback> | 204 std::vector<PacketFeedback> |
188 TransportFeedbackAdapter::GetTransportFeedbackVector() const { | 205 TransportFeedbackAdapter::GetTransportFeedbackVector() const { |
189 return last_packet_feedback_vector_; | 206 return last_packet_feedback_vector_; |
190 } | 207 } |
| 208 |
| 209 rtc::Optional<int64_t> TransportFeedbackAdapter::GetMinFeedbackLoopRtt() const { |
| 210 rtc::CritScope cs(&lock_); |
| 211 return min_feedback_rtt_; |
| 212 } |
| 213 |
| 214 size_t TransportFeedbackAdapter::GetOutstandingBytes() const { |
| 215 rtc::CritScope cs(&lock_); |
| 216 return send_time_history_.GetOutstandingBytes(local_net_id_, remote_net_id_); |
| 217 } |
191 } // namespace webrtc | 218 } // namespace webrtc |
OLD | NEW |