OLD | NEW |
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/receiver/frame_receiver.h" | 5 #include "media/cast/receiver/frame_receiver.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/big_endian.h" | 9 #include "base/big_endian.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 config.receiver_ssrc, | 52 config.receiver_ssrc, |
53 config.sender_ssrc), | 53 config.sender_ssrc), |
54 is_waiting_for_consecutive_frame_(false), | 54 is_waiting_for_consecutive_frame_(false), |
55 lip_sync_drift_(ClockDriftSmoother::GetDefaultTimeConstant()), | 55 lip_sync_drift_(ClockDriftSmoother::GetDefaultTimeConstant()), |
56 weak_factory_(this) { | 56 weak_factory_(this) { |
57 transport_->AddValidSsrc(config.sender_ssrc); | 57 transport_->AddValidSsrc(config.sender_ssrc); |
58 DCHECK_GT(config.rtp_max_delay_ms, 0); | 58 DCHECK_GT(config.rtp_max_delay_ms, 0); |
59 DCHECK_GT(config.target_frame_rate, 0); | 59 DCHECK_GT(config.target_frame_rate, 0); |
60 decryptor_.Initialize(config.aes_key, config.aes_iv_mask); | 60 decryptor_.Initialize(config.aes_key, config.aes_iv_mask); |
61 cast_environment_->logger()->Subscribe(&event_subscriber_); | 61 cast_environment_->logger()->Subscribe(&event_subscriber_); |
62 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); | |
63 } | 62 } |
64 | 63 |
65 FrameReceiver::~FrameReceiver() { | 64 FrameReceiver::~FrameReceiver() { |
66 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 65 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
67 cast_environment_->logger()->Unsubscribe(&event_subscriber_); | 66 cast_environment_->logger()->Unsubscribe(&event_subscriber_); |
68 } | 67 } |
69 | 68 |
70 void FrameReceiver::RequestEncodedFrame( | 69 void FrameReceiver::RequestEncodedFrame( |
71 const ReceiveEncodedFrameCallback& callback) { | 70 const ReceiveEncodedFrameCallback& callback) { |
72 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 71 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
(...skipping 12 matching lines...) Expand all Loading... |
85 size_t payload_size; | 84 size_t payload_size; |
86 if (!packet_parser_.ParsePacket(&packet->front(), | 85 if (!packet_parser_.ParsePacket(&packet->front(), |
87 packet->size(), | 86 packet->size(), |
88 &rtp_header, | 87 &rtp_header, |
89 &payload_data, | 88 &payload_data, |
90 &payload_size)) { | 89 &payload_size)) { |
91 return false; | 90 return false; |
92 } | 91 } |
93 | 92 |
94 ProcessParsedPacket(rtp_header, payload_data, payload_size); | 93 ProcessParsedPacket(rtp_header, payload_data, payload_size); |
95 stats_.UpdateStatistics(rtp_header); | 94 stats_.UpdateStatistics(rtp_header, rtp_timebase_); |
96 } | 95 } |
97 | 96 |
98 if (!reports_are_scheduled_) { | 97 if (!reports_are_scheduled_) { |
99 ScheduleNextRtcpReport(); | 98 ScheduleNextRtcpReport(); |
100 ScheduleNextCastMessage(); | 99 ScheduleNextCastMessage(); |
101 reports_are_scheduled_ = true; | 100 reports_are_scheduled_ = true; |
102 } | 101 } |
103 | 102 |
104 return true; | 103 return true; |
105 } | 104 } |
(...skipping 23 matching lines...) Expand all Loading... |
129 const bool complete = | 128 const bool complete = |
130 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); | 129 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); |
131 | 130 |
132 // Duplicate packets are ignored. | 131 // Duplicate packets are ignored. |
133 if (duplicate) | 132 if (duplicate) |
134 return; | 133 return; |
135 | 134 |
136 // Update lip-sync values upon receiving the first packet of each frame, or if | 135 // Update lip-sync values upon receiving the first packet of each frame, or if |
137 // they have never been set yet. | 136 // they have never been set yet. |
138 if (rtp_header.packet_id == 0 || lip_sync_reference_time_.is_null()) { | 137 if (rtp_header.packet_id == 0 || lip_sync_reference_time_.is_null()) { |
139 RtpTimestamp fresh_sync_rtp; | 138 RtpTimeTicks fresh_sync_rtp; |
140 base::TimeTicks fresh_sync_reference; | 139 base::TimeTicks fresh_sync_reference; |
141 if (!rtcp_.GetLatestLipSyncTimes(&fresh_sync_rtp, &fresh_sync_reference)) { | 140 if (!rtcp_.GetLatestLipSyncTimes(&fresh_sync_rtp, &fresh_sync_reference)) { |
142 // HACK: The sender should have provided Sender Reports before the first | 141 // HACK: The sender should have provided Sender Reports before the first |
143 // frame was sent. However, the spec does not currently require this. | 142 // frame was sent. However, the spec does not currently require this. |
144 // Therefore, when the data is missing, the local clock is used to | 143 // Therefore, when the data is missing, the local clock is used to |
145 // generate reference timestamps. | 144 // generate reference timestamps. |
146 VLOG(2) << "Lip sync info missing. Falling-back to local clock."; | 145 VLOG(2) << "Lip sync info missing. Falling-back to local clock."; |
147 fresh_sync_rtp = rtp_header.rtp_timestamp; | 146 fresh_sync_rtp = rtp_header.rtp_timestamp; |
148 fresh_sync_reference = now; | 147 fresh_sync_reference = now; |
149 } | 148 } |
150 // |lip_sync_reference_time_| is always incremented according to the time | 149 // |lip_sync_reference_time_| is always incremented according to the time |
151 // delta computed from the difference in RTP timestamps. Then, | 150 // delta computed from the difference in RTP timestamps. Then, |
152 // |lip_sync_drift_| accounts for clock drift and also smoothes-out any | 151 // |lip_sync_drift_| accounts for clock drift and also smoothes-out any |
153 // sudden/discontinuous shifts in the series of reference time values. | 152 // sudden/discontinuous shifts in the series of reference time values. |
154 if (lip_sync_reference_time_.is_null()) { | 153 if (lip_sync_reference_time_.is_null()) { |
155 lip_sync_reference_time_ = fresh_sync_reference; | 154 lip_sync_reference_time_ = fresh_sync_reference; |
156 } else { | 155 } else { |
157 lip_sync_reference_time_ += RtpDeltaToTimeDelta( | 156 // Note: It's okay for the conversion ToTimeDelta() to be approximate |
158 static_cast<int32>(fresh_sync_rtp - lip_sync_rtp_timestamp_), | 157 // because |lip_sync_drift_| will account for accumulated errors. |
159 rtp_timebase_); | 158 lip_sync_reference_time_ += |
| 159 (fresh_sync_rtp - lip_sync_rtp_timestamp_).ToTimeDelta(rtp_timebase_); |
160 } | 160 } |
161 lip_sync_rtp_timestamp_ = fresh_sync_rtp; | 161 lip_sync_rtp_timestamp_ = fresh_sync_rtp; |
162 lip_sync_drift_.Update( | 162 lip_sync_drift_.Update( |
163 now, fresh_sync_reference - lip_sync_reference_time_); | 163 now, fresh_sync_reference - lip_sync_reference_time_); |
164 } | 164 } |
165 | 165 |
166 // Another frame is complete from a non-duplicate packet. Attempt to emit | 166 // Another frame is complete from a non-duplicate packet. Attempt to emit |
167 // more frames to satisfy enqueued requests. | 167 // more frames to satisfy enqueued requests. |
168 if (complete) | 168 if (complete) |
169 EmitAvailableEncodedFrames(); | 169 EmitAvailableEncodedFrames(); |
170 } | 170 } |
171 | 171 |
172 void FrameReceiver::CastFeedback(const RtcpCastMessage& cast_message) { | 172 void FrameReceiver::CastFeedback(const RtcpCastMessage& cast_message) { |
173 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 173 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
174 | 174 |
175 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 175 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
176 RtpTimestamp rtp_timestamp = | 176 RtpTimeTicks rtp_timestamp = |
177 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id & 0xff]; | 177 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id & 0xff]; |
178 | 178 |
179 scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); | 179 scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); |
180 ack_sent_event->timestamp = now; | 180 ack_sent_event->timestamp = now; |
181 ack_sent_event->type = FRAME_ACK_SENT; | 181 ack_sent_event->type = FRAME_ACK_SENT; |
182 ack_sent_event->media_type = event_media_type_; | 182 ack_sent_event->media_type = event_media_type_; |
183 ack_sent_event->rtp_timestamp = rtp_timestamp; | 183 ack_sent_event->rtp_timestamp = rtp_timestamp; |
184 ack_sent_event->frame_id = cast_message.ack_frame_id; | 184 ack_sent_event->frame_id = cast_message.ack_frame_id; |
185 cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); | 185 cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); |
186 | 186 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 if (!callback.is_null()) | 295 if (!callback.is_null()) |
296 callback.Run(encoded_frame.Pass()); | 296 callback.Run(encoded_frame.Pass()); |
297 } | 297 } |
298 | 298 |
299 base::TimeTicks FrameReceiver::GetPlayoutTime(const EncodedFrame& frame) const { | 299 base::TimeTicks FrameReceiver::GetPlayoutTime(const EncodedFrame& frame) const { |
300 base::TimeDelta target_playout_delay = target_playout_delay_; | 300 base::TimeDelta target_playout_delay = target_playout_delay_; |
301 if (frame.new_playout_delay_ms) { | 301 if (frame.new_playout_delay_ms) { |
302 target_playout_delay = base::TimeDelta::FromMilliseconds( | 302 target_playout_delay = base::TimeDelta::FromMilliseconds( |
303 frame.new_playout_delay_ms); | 303 frame.new_playout_delay_ms); |
304 } | 304 } |
305 return lip_sync_reference_time_ + | 305 return lip_sync_reference_time_ + lip_sync_drift_.Current() + |
306 lip_sync_drift_.Current() + | 306 (frame.rtp_timestamp - lip_sync_rtp_timestamp_) |
307 RtpDeltaToTimeDelta( | 307 .ToTimeDelta(rtp_timebase_) + |
308 static_cast<int32>(frame.rtp_timestamp - lip_sync_rtp_timestamp_), | 308 target_playout_delay; |
309 rtp_timebase_) + | |
310 target_playout_delay; | |
311 } | 309 } |
312 | 310 |
313 void FrameReceiver::ScheduleNextCastMessage() { | 311 void FrameReceiver::ScheduleNextCastMessage() { |
314 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 312 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
315 base::TimeTicks send_time; | 313 base::TimeTicks send_time; |
316 framer_.TimeToSendNextCastMessage(&send_time); | 314 framer_.TimeToSendNextCastMessage(&send_time); |
317 base::TimeDelta time_to_send = | 315 base::TimeDelta time_to_send = |
318 send_time - cast_environment_->Clock()->NowTicks(); | 316 send_time - cast_environment_->Clock()->NowTicks(); |
319 time_to_send = std::max( | 317 time_to_send = std::max( |
320 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 318 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
(...skipping 30 matching lines...) Expand all Loading... |
351 rtcp_.ConvertToNTPAndSave(now), | 349 rtcp_.ConvertToNTPAndSave(now), |
352 NULL, | 350 NULL, |
353 base::TimeDelta(), | 351 base::TimeDelta(), |
354 NULL, | 352 NULL, |
355 &stats); | 353 &stats); |
356 ScheduleNextRtcpReport(); | 354 ScheduleNextRtcpReport(); |
357 } | 355 } |
358 | 356 |
359 } // namespace cast | 357 } // namespace cast |
360 } // namespace media | 358 } // namespace media |
OLD | NEW |