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

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: Remove RTT accessors in FrameSender (not needed post-refactor). 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/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
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
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
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
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
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