Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: media/cast/net/rtcp/rtcp.cc

Issue 532373003: [Cast] RTT clean-up to the max! (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/cast/net/rtcp/rtcp.h ('k') | media/cast/net/rtcp/rtcp_defines.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/cast/net/rtcp/rtcp.h ('k') | media/cast/net/rtcp/rtcp_defines.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698