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

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

Issue 280993002: [Cast] Repair receiver playout time calculations and frame skip logic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed hubbe's comments. Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/rtcp/rtcp.h" 5 #include "media/cast/rtcp/rtcp.h"
6 6
7 #include "base/big_endian.h" 7 #include "base/big_endian.h"
8 #include "base/rand_util.h" 8 #include "base/rand_util.h"
9 #include "media/cast/cast_config.h" 9 #include "media/cast/cast_config.h"
10 #include "media/cast/cast_defines.h" 10 #include "media/cast/cast_defines.h"
11 #include "media/cast/cast_environment.h" 11 #include "media/cast/cast_environment.h"
12 #include "media/cast/rtcp/rtcp_defines.h" 12 #include "media/cast/rtcp/rtcp_defines.h"
13 #include "media/cast/rtcp/rtcp_receiver.h" 13 #include "media/cast/rtcp/rtcp_receiver.h"
14 #include "media/cast/rtcp/rtcp_sender.h" 14 #include "media/cast/rtcp/rtcp_sender.h"
15 #include "media/cast/rtcp/rtcp_utility.h" 15 #include "media/cast/rtcp/rtcp_utility.h"
16 #include "media/cast/transport/cast_transport_defines.h" 16 #include "media/cast/transport/cast_transport_defines.h"
17 17
18 namespace media { 18 namespace media {
19 namespace cast { 19 namespace cast {
20 20
21 static const int kMaxRttMs = 10000; // 10 seconds. 21 static const int kMaxRttMs = 10000; // 10 seconds.
22 static const uint16 kMaxDelay = 2000; 22 static const int kMaxDelay = 2000;
23
24 // Time limit for received RTCP messages when we stop using it for lip-sync.
25 static const int64 kMaxDiffSinceReceivedRtcpMs = 100000; // 100 seconds.
26 23
27 class LocalRtcpRttFeedback : public RtcpRttFeedback { 24 class LocalRtcpRttFeedback : public RtcpRttFeedback {
28 public: 25 public:
29 explicit LocalRtcpRttFeedback(Rtcp* rtcp) : rtcp_(rtcp) {} 26 explicit LocalRtcpRttFeedback(Rtcp* rtcp) : rtcp_(rtcp) {}
30 27
31 virtual void OnReceivedDelaySinceLastReport( 28 virtual void OnReceivedDelaySinceLastReport(
32 uint32 receivers_ssrc, uint32 last_report, 29 uint32 receivers_ssrc, uint32 last_report,
33 uint32 delay_since_last_report) OVERRIDE { 30 uint32 delay_since_last_report) OVERRIDE {
34 rtcp_->OnReceivedDelaySinceLastReport(receivers_ssrc, last_report, 31 rtcp_->OnReceivedDelaySinceLastReport(receivers_ssrc, last_report,
35 delay_since_last_report); 32 delay_since_last_report);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 rtcp_interval_(rtcp_interval), 120 rtcp_interval_(rtcp_interval),
124 rtcp_mode_(rtcp_mode), 121 rtcp_mode_(rtcp_mode),
125 local_ssrc_(local_ssrc), 122 local_ssrc_(local_ssrc),
126 remote_ssrc_(remote_ssrc), 123 remote_ssrc_(remote_ssrc),
127 c_name_(c_name), 124 c_name_(c_name),
128 rtp_receiver_statistics_(rtp_receiver_statistics), 125 rtp_receiver_statistics_(rtp_receiver_statistics),
129 rtt_feedback_(new LocalRtcpRttFeedback(this)), 126 rtt_feedback_(new LocalRtcpRttFeedback(this)),
130 receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)), 127 receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)),
131 rtcp_sender_(new RtcpSender(cast_environment, paced_packet_sender, 128 rtcp_sender_(new RtcpSender(cast_environment, paced_packet_sender,
132 local_ssrc, c_name)), 129 local_ssrc, c_name)),
133 last_report_received_(0), 130 last_report_ntp_time_(0),
134 last_received_rtp_timestamp_(0), 131 lip_sync_rtp_timestamp_(0),
135 last_received_ntp_seconds_(0),
136 last_received_ntp_fraction_(0),
137 min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)), 132 min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)),
138 number_of_rtt_in_avg_(0), 133 number_of_rtt_in_avg_(0),
139 is_audio_(is_audio) { 134 is_audio_(is_audio) {
140 rtcp_receiver_.reset(new RtcpReceiver(cast_environment, sender_feedback, 135 rtcp_receiver_.reset(new RtcpReceiver(cast_environment, sender_feedback,
141 receiver_feedback_.get(), 136 receiver_feedback_.get(),
142 rtt_feedback_.get(), local_ssrc)); 137 rtt_feedback_.get(), local_ssrc));
143 rtcp_receiver_->SetRemoteSSRC(remote_ssrc); 138 rtcp_receiver_->SetRemoteSSRC(remote_ssrc);
144 } 139 }
145 140
146 Rtcp::~Rtcp() {} 141 Rtcp::~Rtcp() {}
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 packet_type_flags |= transport::kRtcpRr; 207 packet_type_flags |= transport::kRtcpRr;
213 208
214 report_block.remote_ssrc = 0; // Not needed to set send side. 209 report_block.remote_ssrc = 0; // Not needed to set send side.
215 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender. 210 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender.
216 if (rtp_receiver_statistics_) { 211 if (rtp_receiver_statistics_) {
217 rtp_receiver_statistics_->GetStatistics( 212 rtp_receiver_statistics_->GetStatistics(
218 &report_block.fraction_lost, &report_block.cumulative_lost, 213 &report_block.fraction_lost, &report_block.cumulative_lost,
219 &report_block.extended_high_sequence_number, &report_block.jitter); 214 &report_block.extended_high_sequence_number, &report_block.jitter);
220 } 215 }
221 216
222 report_block.last_sr = last_report_received_; 217 report_block.last_sr = GetTruncatedLastNtpReportTime();
223 if (!time_last_report_received_.is_null()) { 218 if (!time_last_report_received_.is_null()) {
224 uint32 delay_seconds = 0; 219 uint32 delay_seconds = 0;
225 uint32 delay_fraction = 0; 220 uint32 delay_fraction = 0;
226 base::TimeDelta delta = now - time_last_report_received_; 221 base::TimeDelta delta = now - time_last_report_received_;
227 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds, 222 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
228 &delay_fraction); 223 &delay_fraction);
229 report_block.delay_since_last_sr = 224 report_block.delay_since_last_sr =
230 ConvertToNtpDiff(delay_seconds, delay_fraction); 225 ConvertToNtpDiff(delay_seconds, delay_fraction);
231 } else { 226 } else {
232 report_block.delay_since_last_sr = 0; 227 report_block.delay_since_last_sr = 0;
(...skipping 17 matching lines...) Expand all
250 245
251 if (sender_log_message.size()) { 246 if (sender_log_message.size()) {
252 packet_type_flags |= transport::kRtcpSenderLog; 247 packet_type_flags |= transport::kRtcpSenderLog;
253 } 248 }
254 249
255 SaveLastSentNtpTime(now, sender_info.ntp_seconds, sender_info.ntp_fraction); 250 SaveLastSentNtpTime(now, sender_info.ntp_seconds, sender_info.ntp_fraction);
256 251
257 transport::RtcpDlrrReportBlock dlrr; 252 transport::RtcpDlrrReportBlock dlrr;
258 if (!time_last_report_received_.is_null()) { 253 if (!time_last_report_received_.is_null()) {
259 packet_type_flags |= transport::kRtcpDlrr; 254 packet_type_flags |= transport::kRtcpDlrr;
260 dlrr.last_rr = last_report_received_; 255 dlrr.last_rr = GetTruncatedLastNtpReportTime();
261 uint32 delay_seconds = 0; 256 uint32 delay_seconds = 0;
262 uint32 delay_fraction = 0; 257 uint32 delay_fraction = 0;
263 base::TimeDelta delta = now - time_last_report_received_; 258 base::TimeDelta delta = now - time_last_report_received_;
264 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds, 259 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
265 &delay_fraction); 260 &delay_fraction);
266 261
267 dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction); 262 dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction);
268 } 263 }
269 264
270 transport_sender_->SendRtcpFromRtpSender( 265 transport_sender_->SendRtcpFromRtpSender(
271 packet_type_flags, sender_info, dlrr, sender_log_message, local_ssrc_, 266 packet_type_flags, sender_info, dlrr, sender_log_message, local_ssrc_,
272 c_name_); 267 c_name_);
273 UpdateNextTimeToSendRtcp(); 268 UpdateNextTimeToSendRtcp();
274 } 269 }
275 270
276 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) { 271 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
277 last_report_received_ = (ntp_seconds << 16) + (ntp_fraction >> 16); 272 time_last_report_received_ = cast_environment_->Clock()->NowTicks();
278 273 last_report_ntp_time_ =
279 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 274 (static_cast<uint64>(ntp_seconds) << 32) | ntp_fraction;
280 time_last_report_received_ = now;
281 } 275 }
282 276
283 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, uint32 ntp_seconds, 277 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, uint32 ntp_seconds,
284 uint32 ntp_fraction) { 278 uint32 ntp_fraction) {
285 last_received_rtp_timestamp_ = rtp_timestamp; 279 lip_sync_rtp_timestamp_ = rtp_timestamp;
286 last_received_ntp_seconds_ = ntp_seconds; 280 lip_sync_capture_time_ = ToApproximateLocalTime(ntp_seconds, ntp_fraction);
287 last_received_ntp_fraction_ = ntp_fraction;
288 } 281 }
289 282
290 void Rtcp::OnReceivedSendReportRequest() { 283 void Rtcp::OnReceivedSendReportRequest() {
291 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 284 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
292 285
293 // Trigger a new RTCP report at next timer. 286 // Trigger a new RTCP report at next timer.
294 next_time_to_send_rtcp_ = now; 287 next_time_to_send_rtcp_ = now;
295 } 288 }
296 289
297 bool Rtcp::RtpTimestampInSenderTime(int frequency, uint32 rtp_timestamp, 290 base::TimeTicks Rtcp::ToApproximateLocalTime(uint32 remote_ntp_seconds,
298 base::TimeTicks* rtp_timestamp_in_ticks) 291 uint32 remote_ntp_fraction) const {
299 const { 292 // Determine the clock difference between the local clock and the remote
300 if (last_received_ntp_seconds_ == 0) 293 // clock. |last_report_ntp_time_| is assumed to be an accurate timestamp from
301 return false; 294 // the remote clock that was snapshotted "just before" the
295 // |time_last_report_received_| was snapshotted from the local clock.
296 //
297 // TODO(miu): This does not account for packet transmit latency across the
298 // network, which may or may not be siginifcant for our use cases.
299 if (time_last_report_received_.is_null())
300 return base::TimeTicks();
301 const base::TimeDelta local_clock_ahead_by = time_last_report_received_ -
302 ConvertNtpToTimeTicks(static_cast<uint32>(last_report_ntp_time_ >> 32),
303 static_cast<uint32>(last_report_ntp_time_));
304 return ConvertNtpToTimeTicks(remote_ntp_seconds, remote_ntp_fraction) +
305 local_clock_ahead_by;
306 }
302 307
303 int wrap = CheckForWrapAround(rtp_timestamp, last_received_rtp_timestamp_); 308 base::TimeTicks Rtcp::ToApproximateCaptureTime(uint32 rtp_timestamp,
304 int64 rtp_timestamp_int64 = rtp_timestamp; 309 int rtp_timebase) const {
305 int64 last_received_rtp_timestamp_int64 = last_received_rtp_timestamp_; 310 // If the lip sync info has not been received yet, no conversion is possible.
311 if (lip_sync_capture_time_.is_null()) {
312 DVLOG(2) << "Requested capture time mapping before first lip sync update.";
313 return base::TimeTicks();
314 } else {
315 // Sanity-check: Getting regular lip sync updates?
316 DCHECK((cast_environment_->Clock()->NowTicks() - lip_sync_capture_time_) <
317 base::TimeDelta::FromMinutes(1));
318 }
306 319
307 if (wrap == 1) { 320 const int32 rtp_since_lip_sync =
308 rtp_timestamp_int64 += (1LL << 32); 321 static_cast<int32>(rtp_timestamp - lip_sync_rtp_timestamp_);
309 } else if (wrap == -1) { 322 const base::TimeDelta time_since_lip_sync =
310 last_received_rtp_timestamp_int64 += (1LL << 32); 323 rtp_since_lip_sync * base::TimeDelta::FromSeconds(1) / rtp_timebase;
311 } 324 return lip_sync_capture_time_ + time_since_lip_sync;
312 // Time since the last RTCP message.
313 // Note that this can be negative since we can compare a rtp timestamp from
314 // a frame older than the last received RTCP message.
315 int64 rtp_timestamp_diff =
316 rtp_timestamp_int64 - last_received_rtp_timestamp_int64;
317
318 int frequency_khz = frequency / 1000;
319 int64 rtp_time_diff_ms = rtp_timestamp_diff / frequency_khz;
320
321 // Sanity check.
322 if (std::abs(rtp_time_diff_ms) > kMaxDiffSinceReceivedRtcpMs)
323 return false;
324
325 *rtp_timestamp_in_ticks = ConvertNtpToTimeTicks(last_received_ntp_seconds_,
326 last_received_ntp_fraction_) +
327 base::TimeDelta::FromMilliseconds(rtp_time_diff_ms);
328 return true;
329 } 325 }
330 326
331 void Rtcp::SetCastReceiverEventHistorySize(size_t size) { 327 void Rtcp::SetCastReceiverEventHistorySize(size_t size) {
332 rtcp_receiver_->SetCastReceiverEventHistorySize(size); 328 rtcp_receiver_->SetCastReceiverEventHistorySize(size);
333 } 329 }
334 330
335 void Rtcp::SetTargetDelay(base::TimeDelta target_delay) { 331 void Rtcp::SetTargetDelay(base::TimeDelta target_delay) {
332 DCHECK(target_delay.InMilliseconds() < kMaxDelay);
336 target_delay_ms_ = static_cast<uint16>(target_delay.InMilliseconds()); 333 target_delay_ms_ = static_cast<uint16>(target_delay.InMilliseconds());
337 DCHECK(target_delay_ms_ < kMaxDelay);
338 } 334 }
339 335
340 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc, 336 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
341 uint32 last_report, 337 uint32 last_report,
342 uint32 delay_since_last_report) { 338 uint32 delay_since_last_report) {
343 RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report); 339 RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report);
344 if (it == last_reports_sent_map_.end()) { 340 if (it == last_reports_sent_map_.end()) {
345 return; // Feedback on another report. 341 return; // Feedback on another report.
346 } 342 }
347 343
(...skipping 21 matching lines...) Expand all
369 RtcpSendTimePair oldest_report = last_reports_sent_queue_.front(); 365 RtcpSendTimePair oldest_report = last_reports_sent_queue_.front();
370 if (oldest_report.second < timeout) { 366 if (oldest_report.second < timeout) {
371 last_reports_sent_map_.erase(oldest_report.first); 367 last_reports_sent_map_.erase(oldest_report.first);
372 last_reports_sent_queue_.pop(); 368 last_reports_sent_queue_.pop();
373 } else { 369 } else {
374 break; 370 break;
375 } 371 }
376 } 372 }
377 } 373 }
378 374
375 uint32 Rtcp::GetTruncatedLastNtpReportTime() const {
376 return static_cast<uint32>(last_report_ntp_time_ >> 16);
377 }
378
379 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay, 379 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay,
380 const base::TimeDelta& receiver_delay) { 380 const base::TimeDelta& receiver_delay) {
381 base::TimeDelta rtt = sender_delay - receiver_delay; 381 base::TimeDelta rtt = sender_delay - receiver_delay;
382 // TODO(miu): Find out why this is capped at 1 ms, and remove the cap if it's
383 // bogus.
382 rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1)); 384 rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1));
383 rtt_ = rtt; 385 rtt_ = rtt;
384 min_rtt_ = std::min(min_rtt_, rtt); 386 min_rtt_ = std::min(min_rtt_, rtt);
385 max_rtt_ = std::max(max_rtt_, rtt); 387 max_rtt_ = std::max(max_rtt_, rtt);
386 388
389 // TODO(miu): Replace "average for all time" with an EWMA, or suitable
390 // "average over recent past" mechanism.
387 if (number_of_rtt_in_avg_ != 0) { 391 if (number_of_rtt_in_avg_ != 0) {
388 float ac = static_cast<float>(number_of_rtt_in_avg_); 392 const double ac = static_cast<double>(number_of_rtt_in_avg_);
389 avg_rtt_ms_ = ((ac / (ac + 1.0)) * avg_rtt_ms_) + 393 avg_rtt_ms_ = ((ac / (ac + 1.0)) * avg_rtt_ms_) +
390 ((1.0 / (ac + 1.0)) * rtt.InMilliseconds()); 394 ((1.0 / (ac + 1.0)) * rtt.InMillisecondsF());
391 } else { 395 } else {
392 avg_rtt_ms_ = rtt.InMilliseconds(); 396 avg_rtt_ms_ = rtt.InMillisecondsF();
393 } 397 }
394 number_of_rtt_in_avg_++; 398 number_of_rtt_in_avg_++;
395 } 399 }
396 400
397 bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt, 401 bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
398 base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const { 402 base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const {
399 DCHECK(rtt) << "Invalid argument"; 403 DCHECK(rtt) << "Invalid argument";
400 DCHECK(avg_rtt) << "Invalid argument"; 404 DCHECK(avg_rtt) << "Invalid argument";
401 DCHECK(min_rtt) << "Invalid argument"; 405 DCHECK(min_rtt) << "Invalid argument";
402 DCHECK(max_rtt) << "Invalid argument"; 406 DCHECK(max_rtt) << "Invalid argument";
403 407
404 if (number_of_rtt_in_avg_ == 0) return false; 408 if (number_of_rtt_in_avg_ == 0) return false;
405 409
406 *rtt = rtt_; 410 *rtt = rtt_;
407 *avg_rtt = base::TimeDelta::FromMilliseconds(avg_rtt_ms_); 411 *avg_rtt = base::TimeDelta::FromMillisecondsD(avg_rtt_ms_);
408 *min_rtt = min_rtt_; 412 *min_rtt = min_rtt_;
409 *max_rtt = max_rtt_; 413 *max_rtt = max_rtt_;
410 return true; 414 return true;
411 } 415 }
412 416
413 int Rtcp::CheckForWrapAround(uint32 new_timestamp, uint32 old_timestamp) const {
414 if (new_timestamp < old_timestamp) {
415 // This difference should be less than -2^31 if we have had a wrap around
416 // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
417 // cast to a int32_t, it should be positive.
418 if (static_cast<int32>(new_timestamp - old_timestamp) > 0) {
419 return 1; // Forward wrap around.
420 }
421 } else if (static_cast<int32>(old_timestamp - new_timestamp) > 0) {
422 // This difference should be less than -2^31 if we have had a backward wrap
423 // around. Since it is cast to a int32, it should be positive.
424 return -1;
425 }
426 return 0;
427 }
428
429 void Rtcp::UpdateNextTimeToSendRtcp() { 417 void Rtcp::UpdateNextTimeToSendRtcp() {
430 int random = base::RandInt(0, 999); 418 int random = base::RandInt(0, 999);
431 base::TimeDelta time_to_next = 419 base::TimeDelta time_to_next =
432 (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000); 420 (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000);
433 421
434 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 422 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
435 next_time_to_send_rtcp_ = now + time_to_next; 423 next_time_to_send_rtcp_ = now + time_to_next;
436 } 424 }
437 425
438 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) { 426 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) {
(...skipping 28 matching lines...) Expand all
467 VLOG(2) << "Received log message via RTCP that we did not expect: " 455 VLOG(2) << "Received log message via RTCP that we did not expect: "
468 << static_cast<int>(event_it->type); 456 << static_cast<int>(event_it->type);
469 break; 457 break;
470 } 458 }
471 } 459 }
472 } 460 }
473 } 461 }
474 462
475 } // namespace cast 463 } // namespace cast
476 } // namespace media 464 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698