OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/net/rtcp/rtcp.h" | 5 #include "media/cast/net/rtcp/rtcp.h" |
6 | 6 |
7 #include "media/cast/cast_config.h" | 7 #include "media/cast/cast_config.h" |
8 #include "media/cast/cast_defines.h" | 8 #include "media/cast/cast_defines.h" |
9 #include "media/cast/cast_environment.h" | 9 #include "media/cast/cast_environment.h" |
10 #include "media/cast/net/cast_transport_defines.h" | 10 #include "media/cast/net/cast_transport_defines.h" |
11 #include "media/cast/net/rtcp/rtcp_defines.h" | 11 #include "media/cast/net/rtcp/rtcp_defines.h" |
12 #include "media/cast/net/rtcp/rtcp_sender.h" | 12 #include "media/cast/net/rtcp/rtcp_sender.h" |
13 #include "media/cast/net/rtcp/rtcp_utility.h" | 13 #include "media/cast/net/rtcp/rtcp_utility.h" |
14 | 14 |
15 using base::TimeDelta; | 15 using base::TimeDelta; |
16 | 16 |
17 namespace media { | 17 namespace media { |
18 namespace cast { | 18 namespace cast { |
19 | 19 |
20 static const int32 kMaxRttMs = 10000; // 10 seconds. | 20 static const int32 kStatsHistoryWindowMs = 10000; // 10 seconds. |
21 // Reject packets that are older than 0.5 seconds older than | 21 // Reject packets that are older than 0.5 seconds older than |
22 // the newest packet we've seen so far. This protect internal | 22 // the newest packet we've seen so far. This protect internal |
23 // states from crazy routers. (Based on RRTR) | 23 // states from crazy routers. (Based on RRTR) |
24 static const int32 kOutOfOrderMaxAgeMs = 500; | 24 static const int32 kOutOfOrderMaxAgeMs = 500; |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 // A receiver frame event is identified by frame RTP timestamp, event timestamp | 28 // A receiver frame event is identified by frame RTP timestamp, event timestamp |
29 // and event type. | 29 // and event type. |
30 // A receiver packet event is identified by all of the above plus packet id. | 30 // A receiver packet event is identified by all of the above plus packet id. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
63 : cast_callback_(cast_callback), | 63 : cast_callback_(cast_callback), |
64 rtt_callback_(rtt_callback), | 64 rtt_callback_(rtt_callback), |
65 log_callback_(log_callback), | 65 log_callback_(log_callback), |
66 clock_(clock), | 66 clock_(clock), |
67 rtcp_sender_(new RtcpSender(packet_sender, local_ssrc)), | 67 rtcp_sender_(new RtcpSender(packet_sender, local_ssrc)), |
68 local_ssrc_(local_ssrc), | 68 local_ssrc_(local_ssrc), |
69 remote_ssrc_(remote_ssrc), | 69 remote_ssrc_(remote_ssrc), |
70 last_report_truncated_ntp_(0), | 70 last_report_truncated_ntp_(0), |
71 local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()), | 71 local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()), |
72 lip_sync_rtp_timestamp_(0), | 72 lip_sync_rtp_timestamp_(0), |
73 lip_sync_ntp_timestamp_(0), | 73 lip_sync_ntp_timestamp_(0) { |
74 min_rtt_(TimeDelta::FromMilliseconds(kMaxRttMs)), | |
75 number_of_rtt_in_avg_(0) { | |
76 } | 74 } |
77 | 75 |
78 Rtcp::~Rtcp() {} | 76 Rtcp::~Rtcp() {} |
79 | 77 |
80 bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) { | 78 bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) { |
81 if (length < kMinLengthOfRtcp) { | 79 if (length < kMinLengthOfRtcp) { |
82 LOG(ERROR) << "Invalid RTCP packet received."; | 80 LOG(ERROR) << "Invalid RTCP packet received."; |
83 return false; | 81 return false; |
84 } | 82 } |
85 | 83 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 RtcpReceiverReferenceTimeReport rrtr; | 200 RtcpReceiverReferenceTimeReport rrtr; |
203 | 201 |
204 // Attach our NTP to all RTCP packets; with this information a "smart" sender | 202 // Attach our NTP to all RTCP packets; with this information a "smart" sender |
205 // can make decisions based on how old the RTCP message is. | 203 // can make decisions based on how old the RTCP message is. |
206 ConvertTimeTicksToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction); | 204 ConvertTimeTicksToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction); |
207 SaveLastSentNtpTime(now, rrtr.ntp_seconds, rrtr.ntp_fraction); | 205 SaveLastSentNtpTime(now, rrtr.ntp_seconds, rrtr.ntp_fraction); |
208 | 206 |
209 if (rtp_receiver_statistics) { | 207 if (rtp_receiver_statistics) { |
210 report_block.remote_ssrc = 0; // Not needed to set send side. | 208 report_block.remote_ssrc = 0; // Not needed to set send side. |
211 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender. | 209 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender. |
212 if (rtp_receiver_statistics) { | 210 rtp_receiver_statistics->GetStatistics( |
213 rtp_receiver_statistics->GetStatistics( | 211 &report_block.fraction_lost, &report_block.cumulative_lost, |
214 &report_block.fraction_lost, &report_block.cumulative_lost, | 212 &report_block.extended_high_sequence_number, &report_block.jitter); |
215 &report_block.extended_high_sequence_number, &report_block.jitter); | |
216 } | |
217 | 213 |
218 report_block.last_sr = last_report_truncated_ntp_; | 214 report_block.last_sr = last_report_truncated_ntp_; |
219 if (!time_last_report_received_.is_null()) { | 215 if (!time_last_report_received_.is_null()) { |
220 uint32 delay_seconds = 0; | 216 uint32 delay_seconds = 0; |
221 uint32 delay_fraction = 0; | 217 uint32 delay_fraction = 0; |
222 base::TimeDelta delta = now - time_last_report_received_; | 218 base::TimeDelta delta = now - time_last_report_received_; |
223 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds, | 219 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds, |
224 &delay_fraction); | 220 &delay_fraction); |
225 report_block.delay_since_last_sr = | 221 report_block.delay_since_last_sr = |
226 ConvertToNtpDiff(delay_seconds, delay_fraction); | 222 ConvertToNtpDiff(delay_seconds, delay_fraction); |
(...skipping 29 matching lines...) Expand all Loading... | |
256 | 252 |
257 rtcp_sender_->SendRtcpFromRtpSender(sender_info); | 253 rtcp_sender_->SendRtcpFromRtpSender(sender_info); |
258 } | 254 } |
259 | 255 |
260 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) { | 256 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) { |
261 last_report_truncated_ntp_ = ConvertToNtpDiff(ntp_seconds, ntp_fraction); | 257 last_report_truncated_ntp_ = ConvertToNtpDiff(ntp_seconds, ntp_fraction); |
262 | 258 |
263 const base::TimeTicks now = clock_->NowTicks(); | 259 const base::TimeTicks now = clock_->NowTicks(); |
264 time_last_report_received_ = now; | 260 time_last_report_received_ = now; |
265 | 261 |
266 // TODO(miu): This clock offset calculation does not account for packet | 262 const base::TimeTicks now_according_to_peer = |
267 // transit time over the network. End2EndTest.EvilNetwork confirms that this | 263 ConvertNtpToTimeTicks(ntp_seconds, ntp_fraction) + |
268 // contributes a very significant source of error here. Fix this along with | 264 current_round_trip_time_ / 2; |
269 // the RTT clean-up. | 265 const base::TimeDelta measured_offset = now - now_according_to_peer; |
270 const base::TimeDelta measured_offset = | |
271 now - ConvertNtpToTimeTicks(ntp_seconds, ntp_fraction); | |
272 local_clock_ahead_by_.Update(now, measured_offset); | 266 local_clock_ahead_by_.Update(now, measured_offset); |
273 if (measured_offset < local_clock_ahead_by_.Current()) { | 267 if (measured_offset < local_clock_ahead_by_.Current()) { |
274 // Logically, the minimum offset between the clocks has to be the correct | 268 // Logically, the minimum offset between the clocks has to be the correct |
hubbe
2014/09/04 22:51:27
This logic doesn't apply if you subtract half the
miu
2014/09/05 18:29:40
I think it applies regardless, right? Meaning, th
miu
2014/09/05 20:54:37
Reverted these LOC, as discussed.
| |
275 // one. For example, the time it took to transmit the current report may | 269 // one. For example, the time it took to transmit the current report may |
276 // have been lower than usual, and so some of the error introduced by the | 270 // have been lower than usual, and so some of the error introduced by the |
277 // transmission time can be eliminated. | 271 // transmission time can be eliminated. |
278 local_clock_ahead_by_.Reset(now, measured_offset); | 272 local_clock_ahead_by_.Reset(now, measured_offset); |
279 } | 273 } |
280 VLOG(1) << "Local clock is ahead of the remote clock by: " | 274 VLOG(1) << "Local clock is ahead of the remote clock by: " |
281 << "measured=" << measured_offset.InMicroseconds() << " usec, " | 275 << "measured=" << measured_offset.InMicroseconds() << " usec, " |
282 << "filtered=" << local_clock_ahead_by_.Current().InMicroseconds() | 276 << "filtered=" << local_clock_ahead_by_.Current().InMicroseconds() |
283 << " usec."; | 277 << " usec."; |
284 } | 278 } |
(...skipping 28 matching lines...) Expand all Loading... | |
313 return true; | 307 return true; |
314 } | 308 } |
315 | 309 |
316 void Rtcp::OnReceivedDelaySinceLastReport(uint32 last_report, | 310 void Rtcp::OnReceivedDelaySinceLastReport(uint32 last_report, |
317 uint32 delay_since_last_report) { | 311 uint32 delay_since_last_report) { |
318 RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report); | 312 RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report); |
319 if (it == last_reports_sent_map_.end()) { | 313 if (it == last_reports_sent_map_.end()) { |
320 return; // Feedback on another report. | 314 return; // Feedback on another report. |
321 } | 315 } |
322 | 316 |
323 base::TimeDelta sender_delay = clock_->NowTicks() - it->second; | 317 const base::TimeDelta sender_delay = clock_->NowTicks() - it->second; |
324 UpdateRtt(sender_delay, ConvertFromNtpDiff(delay_since_last_report)); | 318 const base::TimeDelta receiver_delay = |
319 ConvertFromNtpDiff(delay_since_last_report); | |
320 current_round_trip_time_ = sender_delay - receiver_delay; | |
321 // If the round trip time was computed as less than 1 ms, assume clock | |
322 // imprecision by one or both peers caused a bad value to be calculated. | |
323 // While plenty of networks do easily achieve less than 1 ms round trip time, | |
324 // such a level of precision cannot be measured with our approach; and 1 ms is | |
325 // good enough to represent "under 1 ms" for our use cases. | |
326 current_round_trip_time_ = | |
327 std::max(current_round_trip_time_, base::TimeDelta::FromMilliseconds(1)); | |
328 | |
329 if (!rtt_callback_.is_null()) | |
330 rtt_callback_.Run(current_round_trip_time_); | |
325 } | 331 } |
326 | 332 |
327 void Rtcp::OnReceivedCastFeedback(const RtcpCastMessage& cast_message) { | 333 void Rtcp::OnReceivedCastFeedback(const RtcpCastMessage& cast_message) { |
328 if (cast_callback_.is_null()) | 334 if (cast_callback_.is_null()) |
329 return; | 335 return; |
330 cast_callback_.Run(cast_message); | 336 cast_callback_.Run(cast_message); |
331 } | 337 } |
332 | 338 |
333 void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now, | 339 void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now, |
334 uint32 last_ntp_seconds, | 340 uint32 last_ntp_seconds, |
335 uint32 last_ntp_fraction) { | 341 uint32 last_ntp_fraction) { |
336 // Make sure |now| is always greater than the last element in | 342 // Make sure |now| is always greater than the last element in |
337 // |last_reports_sent_queue_|. | 343 // |last_reports_sent_queue_|. |
338 if (!last_reports_sent_queue_.empty()) | 344 if (!last_reports_sent_queue_.empty()) |
339 DCHECK(now >= last_reports_sent_queue_.back().second); | 345 DCHECK(now >= last_reports_sent_queue_.back().second); |
340 | 346 |
341 uint32 last_report = ConvertToNtpDiff(last_ntp_seconds, last_ntp_fraction); | 347 uint32 last_report = ConvertToNtpDiff(last_ntp_seconds, last_ntp_fraction); |
342 last_reports_sent_map_[last_report] = now; | 348 last_reports_sent_map_[last_report] = now; |
343 last_reports_sent_queue_.push(std::make_pair(last_report, now)); | 349 last_reports_sent_queue_.push(std::make_pair(last_report, now)); |
344 | 350 |
345 base::TimeTicks timeout = now - TimeDelta::FromMilliseconds(kMaxRttMs); | 351 const base::TimeTicks timeout = |
352 now - TimeDelta::FromMilliseconds(kStatsHistoryWindowMs); | |
346 | 353 |
347 // Cleanup old statistics older than |timeout|. | 354 // Cleanup old statistics older than |timeout|. |
348 while (!last_reports_sent_queue_.empty()) { | 355 while (!last_reports_sent_queue_.empty()) { |
349 RtcpSendTimePair oldest_report = last_reports_sent_queue_.front(); | 356 RtcpSendTimePair oldest_report = last_reports_sent_queue_.front(); |
350 if (oldest_report.second < timeout) { | 357 if (oldest_report.second < timeout) { |
351 last_reports_sent_map_.erase(oldest_report.first); | 358 last_reports_sent_map_.erase(oldest_report.first); |
352 last_reports_sent_queue_.pop(); | 359 last_reports_sent_queue_.pop(); |
353 } else { | 360 } else { |
354 break; | 361 break; |
355 } | 362 } |
356 } | 363 } |
357 } | 364 } |
358 | 365 |
359 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay, | |
360 const base::TimeDelta& receiver_delay) { | |
361 base::TimeDelta rtt = sender_delay - receiver_delay; | |
362 // TODO(miu): Find out why this must be >= 1 ms, and remove the fudge if it's | |
363 // bogus. | |
364 rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1)); | |
365 rtt_ = rtt; | |
366 min_rtt_ = std::min(min_rtt_, rtt); | |
367 max_rtt_ = std::max(max_rtt_, rtt); | |
368 | |
369 // TODO(miu): Replace "average for all time" with an EWMA, or suitable | |
370 // "average over recent past" mechanism. | |
371 if (number_of_rtt_in_avg_ != 0) { | |
372 // Integer math equivalent of (ac/(ac+1.0))*avg_rtt_ + (1.0/(ac+1.0))*rtt). | |
373 // (TimeDelta only supports math with other TimeDeltas and int64s.) | |
374 avg_rtt_ = (avg_rtt_ * number_of_rtt_in_avg_ + rtt) / | |
375 (number_of_rtt_in_avg_ + 1); | |
376 } else { | |
377 avg_rtt_ = rtt; | |
378 } | |
379 number_of_rtt_in_avg_++; | |
380 | |
381 if (!rtt_callback_.is_null()) | |
382 rtt_callback_.Run(rtt, avg_rtt_, min_rtt_, max_rtt_); | |
383 } | |
384 | |
385 bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt, | |
386 base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const { | |
387 DCHECK(rtt) << "Invalid argument"; | |
388 DCHECK(avg_rtt) << "Invalid argument"; | |
389 DCHECK(min_rtt) << "Invalid argument"; | |
390 DCHECK(max_rtt) << "Invalid argument"; | |
391 | |
392 if (number_of_rtt_in_avg_ == 0) return false; | |
393 | |
394 *rtt = rtt_; | |
395 *avg_rtt = avg_rtt_; | |
396 *min_rtt = min_rtt_; | |
397 *max_rtt = max_rtt_; | |
398 return true; | |
399 } | |
400 | |
401 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) { | 366 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) { |
402 if (log_callback_.is_null()) | 367 if (log_callback_.is_null()) |
403 return; | 368 return; |
404 log_callback_.Run(receiver_log); | 369 log_callback_.Run(receiver_log); |
405 } | 370 } |
406 | 371 |
407 } // namespace cast | 372 } // namespace cast |
408 } // namespace media | 373 } // namespace media |
OLD | NEW |