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

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: rebase 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
« no previous file with comments | « media/cast/rtcp/rtcp.h ('k') | media/cast/rtcp/rtcp_unittest.cc » ('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 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 rtcp_interval_(rtcp_interval), 85 rtcp_interval_(rtcp_interval),
89 rtcp_mode_(rtcp_mode), 86 rtcp_mode_(rtcp_mode),
90 local_ssrc_(local_ssrc), 87 local_ssrc_(local_ssrc),
91 remote_ssrc_(remote_ssrc), 88 remote_ssrc_(remote_ssrc),
92 c_name_(c_name), 89 c_name_(c_name),
93 rtp_receiver_statistics_(rtp_receiver_statistics), 90 rtp_receiver_statistics_(rtp_receiver_statistics),
94 rtt_feedback_(new LocalRtcpRttFeedback(this)), 91 rtt_feedback_(new LocalRtcpRttFeedback(this)),
95 receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)), 92 receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)),
96 rtcp_sender_(new RtcpSender(cast_environment, paced_packet_sender, 93 rtcp_sender_(new RtcpSender(cast_environment, paced_packet_sender,
97 local_ssrc, c_name)), 94 local_ssrc, c_name)),
98 last_report_received_(0), 95 last_report_truncated_ntp_(0),
99 last_received_rtp_timestamp_(0), 96 local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()),
100 last_received_ntp_seconds_(0), 97 lip_sync_rtp_timestamp_(0),
101 last_received_ntp_fraction_(0), 98 lip_sync_ntp_timestamp_(0),
102 min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)), 99 min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)),
103 number_of_rtt_in_avg_(0), 100 number_of_rtt_in_avg_(0),
104 is_audio_(is_audio) { 101 is_audio_(is_audio) {
105 rtcp_receiver_.reset(new RtcpReceiver(cast_environment, sender_feedback, 102 rtcp_receiver_.reset(new RtcpReceiver(cast_environment, sender_feedback,
106 receiver_feedback_.get(), 103 receiver_feedback_.get(),
107 rtt_feedback_.get(), local_ssrc)); 104 rtt_feedback_.get(), local_ssrc));
108 rtcp_receiver_->SetRemoteSSRC(remote_ssrc); 105 rtcp_receiver_->SetRemoteSSRC(remote_ssrc);
109 } 106 }
110 107
111 Rtcp::~Rtcp() {} 108 Rtcp::~Rtcp() {}
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 packet_type_flags |= transport::kRtcpRr; 174 packet_type_flags |= transport::kRtcpRr;
178 175
179 report_block.remote_ssrc = 0; // Not needed to set send side. 176 report_block.remote_ssrc = 0; // Not needed to set send side.
180 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender. 177 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender.
181 if (rtp_receiver_statistics_) { 178 if (rtp_receiver_statistics_) {
182 rtp_receiver_statistics_->GetStatistics( 179 rtp_receiver_statistics_->GetStatistics(
183 &report_block.fraction_lost, &report_block.cumulative_lost, 180 &report_block.fraction_lost, &report_block.cumulative_lost,
184 &report_block.extended_high_sequence_number, &report_block.jitter); 181 &report_block.extended_high_sequence_number, &report_block.jitter);
185 } 182 }
186 183
187 report_block.last_sr = last_report_received_; 184 report_block.last_sr = last_report_truncated_ntp_;
188 if (!time_last_report_received_.is_null()) { 185 if (!time_last_report_received_.is_null()) {
189 uint32 delay_seconds = 0; 186 uint32 delay_seconds = 0;
190 uint32 delay_fraction = 0; 187 uint32 delay_fraction = 0;
191 base::TimeDelta delta = now - time_last_report_received_; 188 base::TimeDelta delta = now - time_last_report_received_;
192 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds, 189 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
193 &delay_fraction); 190 &delay_fraction);
194 report_block.delay_since_last_sr = 191 report_block.delay_since_last_sr =
195 ConvertToNtpDiff(delay_seconds, delay_fraction); 192 ConvertToNtpDiff(delay_seconds, delay_fraction);
196 } else { 193 } else {
197 report_block.delay_since_last_sr = 0; 194 report_block.delay_since_last_sr = 0;
(...skipping 15 matching lines...) Expand all
213 uint32 current_ntp_seconds = 0; 210 uint32 current_ntp_seconds = 0;
214 uint32 current_ntp_fractions = 0; 211 uint32 current_ntp_fractions = 0;
215 ConvertTimeTicksToNtp(current_time, &current_ntp_seconds, 212 ConvertTimeTicksToNtp(current_time, &current_ntp_seconds,
216 &current_ntp_fractions); 213 &current_ntp_fractions);
217 SaveLastSentNtpTime(current_time, current_ntp_seconds, 214 SaveLastSentNtpTime(current_time, current_ntp_seconds,
218 current_ntp_fractions); 215 current_ntp_fractions);
219 216
220 transport::RtcpDlrrReportBlock dlrr; 217 transport::RtcpDlrrReportBlock dlrr;
221 if (!time_last_report_received_.is_null()) { 218 if (!time_last_report_received_.is_null()) {
222 packet_type_flags |= transport::kRtcpDlrr; 219 packet_type_flags |= transport::kRtcpDlrr;
223 dlrr.last_rr = last_report_received_; 220 dlrr.last_rr = last_report_truncated_ntp_;
224 uint32 delay_seconds = 0; 221 uint32 delay_seconds = 0;
225 uint32 delay_fraction = 0; 222 uint32 delay_fraction = 0;
226 base::TimeDelta delta = current_time - time_last_report_received_; 223 base::TimeDelta delta = current_time - time_last_report_received_;
227 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds, 224 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
228 &delay_fraction); 225 &delay_fraction);
229 226
230 dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction); 227 dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction);
231 } 228 }
232 229
233 transport_sender_->SendRtcpFromRtpSender( 230 transport_sender_->SendRtcpFromRtpSender(
234 packet_type_flags, current_ntp_seconds, current_ntp_fractions, 231 packet_type_flags, current_ntp_seconds, current_ntp_fractions,
235 current_time_as_rtp_timestamp, dlrr, local_ssrc_, c_name_); 232 current_time_as_rtp_timestamp, dlrr, local_ssrc_, c_name_);
236 UpdateNextTimeToSendRtcp(); 233 UpdateNextTimeToSendRtcp();
237 } 234 }
238 235
239 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) { 236 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
240 last_report_received_ = (ntp_seconds << 16) + (ntp_fraction >> 16); 237 last_report_truncated_ntp_ = ConvertToNtpDiff(ntp_seconds, ntp_fraction);
241 238
242 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 239 const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
243 time_last_report_received_ = now; 240 time_last_report_received_ = now;
241
242 // TODO(miu): This clock offset calculation does not account for packet
243 // transit time over the network. End2EndTest.EvilNetwork confirms that this
244 // contributes a very significant source of error here. Fix this along with
245 // the RTT clean-up.
246 const base::TimeDelta measured_offset =
247 now - ConvertNtpToTimeTicks(ntp_seconds, ntp_fraction);
248 local_clock_ahead_by_.Update(now, measured_offset);
249 if (measured_offset < local_clock_ahead_by_.Current()) {
250 // Logically, the minimum offset between the clocks has to be the correct
251 // one. For example, the time it took to transmit the current report may
252 // have been lower than usual, and so some of the error introduced by the
253 // transmission time can be eliminated.
254 local_clock_ahead_by_.Reset(now, measured_offset);
255 }
256 VLOG(1) << "Local clock is ahead of the remote clock by: "
257 << "measured=" << measured_offset.InMicroseconds() << " usec, "
258 << "filtered=" << local_clock_ahead_by_.Current().InMicroseconds()
259 << " usec.";
244 } 260 }
245 261
246 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, uint32 ntp_seconds, 262 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, uint32 ntp_seconds,
247 uint32 ntp_fraction) { 263 uint32 ntp_fraction) {
248 last_received_rtp_timestamp_ = rtp_timestamp; 264 if (ntp_seconds == 0) {
249 last_received_ntp_seconds_ = ntp_seconds; 265 NOTREACHED();
250 last_received_ntp_fraction_ = ntp_fraction; 266 return;
267 }
268 lip_sync_rtp_timestamp_ = rtp_timestamp;
269 lip_sync_ntp_timestamp_ =
270 (static_cast<uint64>(ntp_seconds) << 32) | ntp_fraction;
271 }
272
273 bool Rtcp::GetLatestLipSyncTimes(uint32* rtp_timestamp,
274 base::TimeTicks* reference_time) const {
275 if (!lip_sync_ntp_timestamp_)
276 return false;
277
278 const base::TimeTicks local_reference_time =
279 ConvertNtpToTimeTicks(static_cast<uint32>(lip_sync_ntp_timestamp_ >> 32),
280 static_cast<uint32>(lip_sync_ntp_timestamp_)) +
281 local_clock_ahead_by_.Current();
282
283 // Sanity-check: Getting regular lip sync updates?
284 DCHECK((cast_environment_->Clock()->NowTicks() - local_reference_time) <
285 base::TimeDelta::FromMinutes(1));
286
287 *rtp_timestamp = lip_sync_rtp_timestamp_;
288 *reference_time = local_reference_time;
289 return true;
251 } 290 }
252 291
253 void Rtcp::OnReceivedSendReportRequest() { 292 void Rtcp::OnReceivedSendReportRequest() {
254 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 293 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
255 294
256 // Trigger a new RTCP report at next timer. 295 // Trigger a new RTCP report at next timer.
257 next_time_to_send_rtcp_ = now; 296 next_time_to_send_rtcp_ = now;
258 } 297 }
259 298
260 bool Rtcp::RtpTimestampInSenderTime(int frequency, uint32 rtp_timestamp,
261 base::TimeTicks* rtp_timestamp_in_ticks)
262 const {
263 if (last_received_ntp_seconds_ == 0)
264 return false;
265
266 int wrap = CheckForWrapAround(rtp_timestamp, last_received_rtp_timestamp_);
267 int64 rtp_timestamp_int64 = rtp_timestamp;
268 int64 last_received_rtp_timestamp_int64 = last_received_rtp_timestamp_;
269
270 if (wrap == 1) {
271 rtp_timestamp_int64 += (1LL << 32);
272 } else if (wrap == -1) {
273 last_received_rtp_timestamp_int64 += (1LL << 32);
274 }
275 // Time since the last RTCP message.
276 // Note that this can be negative since we can compare a rtp timestamp from
277 // a frame older than the last received RTCP message.
278 int64 rtp_timestamp_diff =
279 rtp_timestamp_int64 - last_received_rtp_timestamp_int64;
280
281 int frequency_khz = frequency / 1000;
282 int64 rtp_time_diff_ms = rtp_timestamp_diff / frequency_khz;
283
284 // Sanity check.
285 if (std::abs(rtp_time_diff_ms) > kMaxDiffSinceReceivedRtcpMs)
286 return false;
287
288 *rtp_timestamp_in_ticks = ConvertNtpToTimeTicks(last_received_ntp_seconds_,
289 last_received_ntp_fraction_) +
290 base::TimeDelta::FromMilliseconds(rtp_time_diff_ms);
291 return true;
292 }
293
294 void Rtcp::SetCastReceiverEventHistorySize(size_t size) { 299 void Rtcp::SetCastReceiverEventHistorySize(size_t size) {
295 rtcp_receiver_->SetCastReceiverEventHistorySize(size); 300 rtcp_receiver_->SetCastReceiverEventHistorySize(size);
296 } 301 }
297 302
298 void Rtcp::SetTargetDelay(base::TimeDelta target_delay) { 303 void Rtcp::SetTargetDelay(base::TimeDelta target_delay) {
304 DCHECK(target_delay.InMilliseconds() < kMaxDelay);
299 target_delay_ms_ = static_cast<uint16>(target_delay.InMilliseconds()); 305 target_delay_ms_ = static_cast<uint16>(target_delay.InMilliseconds());
300 DCHECK(target_delay_ms_ < kMaxDelay);
301 } 306 }
302 307
303 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc, 308 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
304 uint32 last_report, 309 uint32 last_report,
305 uint32 delay_since_last_report) { 310 uint32 delay_since_last_report) {
306 RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report); 311 RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report);
307 if (it == last_reports_sent_map_.end()) { 312 if (it == last_reports_sent_map_.end()) {
308 return; // Feedback on another report. 313 return; // Feedback on another report.
309 } 314 }
310 315
(...skipping 24 matching lines...) Expand all
335 last_reports_sent_queue_.pop(); 340 last_reports_sent_queue_.pop();
336 } else { 341 } else {
337 break; 342 break;
338 } 343 }
339 } 344 }
340 } 345 }
341 346
342 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay, 347 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay,
343 const base::TimeDelta& receiver_delay) { 348 const base::TimeDelta& receiver_delay) {
344 base::TimeDelta rtt = sender_delay - receiver_delay; 349 base::TimeDelta rtt = sender_delay - receiver_delay;
350 // TODO(miu): Find out why this must be >= 1 ms, and remove the fudge if it's
351 // bogus.
345 rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1)); 352 rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1));
346 rtt_ = rtt; 353 rtt_ = rtt;
347 min_rtt_ = std::min(min_rtt_, rtt); 354 min_rtt_ = std::min(min_rtt_, rtt);
348 max_rtt_ = std::max(max_rtt_, rtt); 355 max_rtt_ = std::max(max_rtt_, rtt);
349 356
357 // TODO(miu): Replace "average for all time" with an EWMA, or suitable
358 // "average over recent past" mechanism.
350 if (number_of_rtt_in_avg_ != 0) { 359 if (number_of_rtt_in_avg_ != 0) {
351 float ac = static_cast<float>(number_of_rtt_in_avg_); 360 const double ac = static_cast<double>(number_of_rtt_in_avg_);
352 avg_rtt_ms_ = ((ac / (ac + 1.0)) * avg_rtt_ms_) + 361 avg_rtt_ms_ = ((ac / (ac + 1.0)) * avg_rtt_ms_) +
353 ((1.0 / (ac + 1.0)) * rtt.InMilliseconds()); 362 ((1.0 / (ac + 1.0)) * rtt.InMillisecondsF());
354 } else { 363 } else {
355 avg_rtt_ms_ = rtt.InMilliseconds(); 364 avg_rtt_ms_ = rtt.InMillisecondsF();
356 } 365 }
357 number_of_rtt_in_avg_++; 366 number_of_rtt_in_avg_++;
358 } 367 }
359 368
360 bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt, 369 bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
361 base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const { 370 base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const {
362 DCHECK(rtt) << "Invalid argument"; 371 DCHECK(rtt) << "Invalid argument";
363 DCHECK(avg_rtt) << "Invalid argument"; 372 DCHECK(avg_rtt) << "Invalid argument";
364 DCHECK(min_rtt) << "Invalid argument"; 373 DCHECK(min_rtt) << "Invalid argument";
365 DCHECK(max_rtt) << "Invalid argument"; 374 DCHECK(max_rtt) << "Invalid argument";
366 375
367 if (number_of_rtt_in_avg_ == 0) return false; 376 if (number_of_rtt_in_avg_ == 0) return false;
368 377
369 *rtt = rtt_; 378 *rtt = rtt_;
370 *avg_rtt = base::TimeDelta::FromMilliseconds(avg_rtt_ms_); 379 *avg_rtt = base::TimeDelta::FromMillisecondsD(avg_rtt_ms_);
371 *min_rtt = min_rtt_; 380 *min_rtt = min_rtt_;
372 *max_rtt = max_rtt_; 381 *max_rtt = max_rtt_;
373 return true; 382 return true;
374 } 383 }
375 384
376 int Rtcp::CheckForWrapAround(uint32 new_timestamp, uint32 old_timestamp) const {
377 if (new_timestamp < old_timestamp) {
378 // This difference should be less than -2^31 if we have had a wrap around
379 // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
380 // cast to a int32_t, it should be positive.
381 if (static_cast<int32>(new_timestamp - old_timestamp) > 0) {
382 return 1; // Forward wrap around.
383 }
384 } else if (static_cast<int32>(old_timestamp - new_timestamp) > 0) {
385 // This difference should be less than -2^31 if we have had a backward wrap
386 // around. Since it is cast to a int32, it should be positive.
387 return -1;
388 }
389 return 0;
390 }
391
392 void Rtcp::UpdateNextTimeToSendRtcp() { 385 void Rtcp::UpdateNextTimeToSendRtcp() {
393 int random = base::RandInt(0, 999); 386 int random = base::RandInt(0, 999);
394 base::TimeDelta time_to_next = 387 base::TimeDelta time_to_next =
395 (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000); 388 (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000);
396 389
397 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 390 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
398 next_time_to_send_rtcp_ = now + time_to_next; 391 next_time_to_send_rtcp_ = now + time_to_next;
399 } 392 }
400 393
401 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) { 394 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) {
(...skipping 28 matching lines...) Expand all
430 VLOG(2) << "Received log message via RTCP that we did not expect: " 423 VLOG(2) << "Received log message via RTCP that we did not expect: "
431 << static_cast<int>(event_it->type); 424 << static_cast<int>(event_it->type);
432 break; 425 break;
433 } 426 }
434 } 427 }
435 } 428 }
436 } 429 }
437 430
438 } // namespace cast 431 } // namespace cast
439 } // namespace media 432 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/rtcp/rtcp.h ('k') | media/cast/rtcp/rtcp_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698