OLD | NEW |
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/video_receiver/video_receiver.h" | 5 #include "media/cast/video_receiver/video_receiver.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "media/cast/cast_defines.h" | 12 #include "media/cast/cast_defines.h" |
13 #include "media/cast/framer/framer.h" | 13 #include "media/cast/framer/framer.h" |
14 #include "media/cast/rtcp/receiver_rtcp_event_subscriber.h" | 14 #include "media/cast/rtcp/receiver_rtcp_event_subscriber.h" |
15 #include "media/cast/rtcp/rtcp_sender.h" | 15 #include "media/cast/rtcp/rtcp_sender.h" |
16 #include "media/cast/video_receiver/video_decoder.h" | 16 #include "media/cast/video_receiver/video_decoder.h" |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 static const int64 kMinSchedulingDelayMs = 1; | 20 static const int64 kMinSchedulingDelayMs = 1; |
21 static const int64 kMinTimeBetweenOffsetUpdatesMs = 1000; | 21 static const int64 kMinTimeBetweenOffsetUpdatesMs = 2000; |
22 static const int kTimeOffsetMaxCounter = 10; | 22 static const int kTimeOffsetFilter = 8; |
23 static const int64_t kMinProcessIntervalMs = 5; | 23 static const int64_t kMinProcessIntervalMs = 5; |
24 | 24 |
25 } // namespace | 25 } // namespace |
26 | 26 |
27 namespace media { | 27 namespace media { |
28 namespace cast { | 28 namespace cast { |
29 | 29 |
30 // Local implementation of RtpData (defined in rtp_rtcp_defines.h). | 30 // Local implementation of RtpData (defined in rtp_rtcp_defines.h). |
31 // Used to pass payload data into the video receiver. | 31 // Used to pass payload data into the video receiver. |
32 class LocalRtpVideoData : public RtpData { | 32 class LocalRtpVideoData : public RtpData { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 frame_delay_(base::TimeDelta::FromMilliseconds( | 100 frame_delay_(base::TimeDelta::FromMilliseconds( |
101 1000 / video_config.max_frame_rate)), | 101 1000 / video_config.max_frame_rate)), |
102 incoming_payload_callback_(new LocalRtpVideoData(this)), | 102 incoming_payload_callback_(new LocalRtpVideoData(this)), |
103 incoming_payload_feedback_(new LocalRtpVideoFeedback(this)), | 103 incoming_payload_feedback_(new LocalRtpVideoFeedback(this)), |
104 rtp_receiver_(cast_environment_->Clock(), | 104 rtp_receiver_(cast_environment_->Clock(), |
105 NULL, | 105 NULL, |
106 &video_config, | 106 &video_config, |
107 incoming_payload_callback_.get()), | 107 incoming_payload_callback_.get()), |
108 rtp_video_receiver_statistics_( | 108 rtp_video_receiver_statistics_( |
109 new LocalRtpReceiverStatistics(&rtp_receiver_)), | 109 new LocalRtpReceiverStatistics(&rtp_receiver_)), |
110 time_offset_counter_(0), | |
111 decryptor_(), | 110 decryptor_(), |
112 time_incoming_packet_updated_(false), | 111 time_incoming_packet_updated_(false), |
113 incoming_rtp_timestamp_(0), | 112 incoming_rtp_timestamp_(0), |
114 weak_factory_(this) { | 113 weak_factory_(this) { |
115 int max_unacked_frames = | 114 int max_unacked_frames = |
116 video_config.rtp_max_delay_ms * video_config.max_frame_rate / 1000; | 115 video_config.rtp_max_delay_ms * video_config.max_frame_rate / 1000; |
117 DCHECK(max_unacked_frames) << "Invalid argument"; | 116 DCHECK(max_unacked_frames) << "Invalid argument"; |
118 | 117 |
119 decryptor_.Initialize(video_config.aes_key, video_config.aes_iv_mask); | 118 decryptor_.Initialize(video_config.aes_key, video_config.aes_iv_mask); |
120 framer_.reset(new Framer(cast_environment->Clock(), | 119 framer_.reset(new Framer(cast_environment->Clock(), |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 } | 349 } |
351 | 350 |
352 base::TimeTicks VideoReceiver::GetRenderTime(base::TimeTicks now, | 351 base::TimeTicks VideoReceiver::GetRenderTime(base::TimeTicks now, |
353 uint32 rtp_timestamp) { | 352 uint32 rtp_timestamp) { |
354 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 353 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
355 // Senders time in ms when this frame was captured. | 354 // Senders time in ms when this frame was captured. |
356 // Note: the senders clock and our local clock might not be synced. | 355 // Note: the senders clock and our local clock might not be synced. |
357 base::TimeTicks rtp_timestamp_in_ticks; | 356 base::TimeTicks rtp_timestamp_in_ticks; |
358 | 357 |
359 // Compute the time offset_in_ticks based on the incoming_rtp_timestamp_. | 358 // Compute the time offset_in_ticks based on the incoming_rtp_timestamp_. |
360 if (time_offset_counter_ == 0) { | 359 if (time_offset_.InMilliseconds() == 0) { |
361 if (!rtcp_->RtpTimestampInSenderTime(kVideoFrequency, | 360 if (!rtcp_->RtpTimestampInSenderTime(kVideoFrequency, |
362 incoming_rtp_timestamp_, | 361 incoming_rtp_timestamp_, |
363 &rtp_timestamp_in_ticks)) { | 362 &rtp_timestamp_in_ticks)) { |
364 // We have not received any RTCP to sync the stream play it out as soon as | 363 // We have not received any RTCP to sync the stream play it out as soon as |
365 // possible. | 364 // possible. |
366 return now; | 365 return now; |
367 } | 366 } |
368 ++time_offset_counter_; | 367 time_offset_ = time_incoming_packet_ - rtp_timestamp_in_ticks; |
369 return now; | |
370 } else if (time_incoming_packet_updated_) { | 368 } else if (time_incoming_packet_updated_) { |
371 if (rtcp_->RtpTimestampInSenderTime(kVideoFrequency, | 369 if (rtcp_->RtpTimestampInSenderTime(kVideoFrequency, |
372 incoming_rtp_timestamp_, | 370 incoming_rtp_timestamp_, |
373 &rtp_timestamp_in_ticks)) { | 371 &rtp_timestamp_in_ticks)) { |
374 // Time to update the time_offset. | 372 // Time to update the time_offset. |
375 base::TimeDelta time_offset = | 373 base::TimeDelta time_offset = |
376 time_incoming_packet_ - rtp_timestamp_in_ticks; | 374 time_incoming_packet_ - rtp_timestamp_in_ticks; |
377 // Taking the minimum of the first kTimeOffsetMaxCounter values. We are | 375 time_offset_ = ((kTimeOffsetFilter - 1) * time_offset_ + time_offset) / |
378 // assuming that we are looking for the minimum offset, which will occur | 376 kTimeOffsetFilter; |
379 // when network conditions are the best. This should occur at least once | |
380 // within the first kTimeOffsetMaxCounter samples. Any drift should be | |
381 // very slow, and negligible for this use case. | |
382 if (time_offset_counter_ == 1) | |
383 time_offset_ = time_offset; | |
384 else if (time_offset_counter_ < kTimeOffsetMaxCounter) | |
385 time_offset_ = std::min(time_offset_, time_offset); | |
386 ++time_offset_counter_; | |
387 } | 377 } |
388 } | 378 } |
389 // Reset |time_incoming_packet_updated_| to enable a future measurement. | 379 // Reset |time_incoming_packet_updated_| to enable a future measurement. |
390 time_incoming_packet_updated_ = false; | 380 time_incoming_packet_updated_ = false; |
391 // Compute the actual rtp_timestamp_in_ticks based on the current timestamp. | 381 // Compute the actual rtp_timestamp_in_ticks based on the current timestamp. |
392 if (!rtcp_->RtpTimestampInSenderTime( | 382 if (!rtcp_->RtpTimestampInSenderTime( |
393 kVideoFrequency, rtp_timestamp, &rtp_timestamp_in_ticks)) { | 383 kVideoFrequency, rtp_timestamp, &rtp_timestamp_in_ticks)) { |
394 // This can fail if we have not received any RTCP packets in a long time. | 384 // This can fail if we have not received any RTCP packets in a long time. |
395 return now; | 385 return now; |
396 } | 386 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 } | 515 } |
526 | 516 |
527 void VideoReceiver::SendNextRtcpReport() { | 517 void VideoReceiver::SendNextRtcpReport() { |
528 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 518 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
529 rtcp_->SendRtcpFromRtpReceiver(NULL, NULL); | 519 rtcp_->SendRtcpFromRtpReceiver(NULL, NULL); |
530 ScheduleNextRtcpReport(); | 520 ScheduleNextRtcpReport(); |
531 } | 521 } |
532 | 522 |
533 } // namespace cast | 523 } // namespace cast |
534 } // namespace media | 524 } // namespace media |
OLD | NEW |