Chromium Code Reviews| 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 |