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