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/audio_receiver/audio_receiver.h" | 5 #include "media/cast/audio_receiver/audio_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" |
(...skipping 11 matching lines...) Expand all Loading... |
22 namespace cast { | 22 namespace cast { |
23 | 23 |
24 AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment, | 24 AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment, |
25 const AudioReceiverConfig& audio_config, | 25 const AudioReceiverConfig& audio_config, |
26 transport::PacedPacketSender* const packet_sender) | 26 transport::PacedPacketSender* const packet_sender) |
27 : RtpReceiver(cast_environment->Clock(), &audio_config, NULL), | 27 : RtpReceiver(cast_environment->Clock(), &audio_config, NULL), |
28 cast_environment_(cast_environment), | 28 cast_environment_(cast_environment), |
29 event_subscriber_(kReceiverRtcpEventHistorySize, AUDIO_EVENT), | 29 event_subscriber_(kReceiverRtcpEventHistorySize, AUDIO_EVENT), |
30 codec_(audio_config.codec), | 30 codec_(audio_config.codec), |
31 frequency_(audio_config.frequency), | 31 frequency_(audio_config.frequency), |
32 target_delay_delta_( | 32 target_playout_delay_( |
33 base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms)), | 33 base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms)), |
| 34 reports_are_scheduled_(false), |
34 framer_(cast_environment->Clock(), | 35 framer_(cast_environment->Clock(), |
35 this, | 36 this, |
36 audio_config.incoming_ssrc, | 37 audio_config.incoming_ssrc, |
37 true, | 38 true, |
38 audio_config.rtp_max_delay_ms / kTypicalAudioFrameDurationMs), | 39 audio_config.rtp_max_delay_ms / kTypicalAudioFrameDurationMs), |
39 rtcp_(cast_environment, | 40 rtcp_(cast_environment, |
40 NULL, | 41 NULL, |
41 NULL, | 42 NULL, |
42 packet_sender, | 43 packet_sender, |
43 GetStatistics(), | 44 GetStatistics(), |
44 audio_config.rtcp_mode, | 45 audio_config.rtcp_mode, |
45 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval), | 46 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval), |
46 audio_config.feedback_ssrc, | 47 audio_config.feedback_ssrc, |
47 audio_config.incoming_ssrc, | 48 audio_config.incoming_ssrc, |
48 audio_config.rtcp_c_name, | 49 audio_config.rtcp_c_name, |
49 true), | 50 true), |
50 is_waiting_for_consecutive_frame_(false), | 51 is_waiting_for_consecutive_frame_(false), |
| 52 lip_sync_drift_(ClockDriftSmoother::GetDefaultTimeConstant()), |
51 weak_factory_(this) { | 53 weak_factory_(this) { |
52 if (!audio_config.use_external_decoder) | 54 if (!audio_config.use_external_decoder) |
53 audio_decoder_.reset(new AudioDecoder(cast_environment, audio_config)); | 55 audio_decoder_.reset(new AudioDecoder(cast_environment, audio_config)); |
54 decryptor_.Initialize(audio_config.aes_key, audio_config.aes_iv_mask); | 56 decryptor_.Initialize(audio_config.aes_key, audio_config.aes_iv_mask); |
55 rtcp_.SetTargetDelay(target_delay_delta_); | 57 rtcp_.SetTargetDelay(target_playout_delay_); |
56 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); | 58 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); |
57 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); | 59 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); |
58 } | 60 } |
59 | 61 |
60 AudioReceiver::~AudioReceiver() { | 62 AudioReceiver::~AudioReceiver() { |
61 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 63 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
62 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_); | 64 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_); |
63 } | 65 } |
64 | 66 |
65 void AudioReceiver::InitializeTimers() { | |
66 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | |
67 ScheduleNextRtcpReport(); | |
68 ScheduleNextCastMessage(); | |
69 } | |
70 | |
71 void AudioReceiver::OnReceivedPayloadData(const uint8* payload_data, | 67 void AudioReceiver::OnReceivedPayloadData(const uint8* payload_data, |
72 size_t payload_size, | 68 size_t payload_size, |
73 const RtpCastHeader& rtp_header) { | 69 const RtpCastHeader& rtp_header) { |
74 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 70 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
75 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | |
76 | 71 |
77 // TODO(pwestin): update this as video to refresh over time. | 72 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
78 if (time_first_incoming_packet_.is_null()) { | |
79 InitializeTimers(); | |
80 first_incoming_rtp_timestamp_ = rtp_header.rtp_timestamp; | |
81 time_first_incoming_packet_ = now; | |
82 } | |
83 | 73 |
84 frame_id_to_rtp_timestamp_[rtp_header.frame_id & 0xff] = | 74 frame_id_to_rtp_timestamp_[rtp_header.frame_id & 0xff] = |
85 rtp_header.rtp_timestamp; | 75 rtp_header.rtp_timestamp; |
86 cast_environment_->Logging()->InsertPacketEvent( | 76 cast_environment_->Logging()->InsertPacketEvent( |
87 now, PACKET_RECEIVED, AUDIO_EVENT, rtp_header.rtp_timestamp, | 77 now, PACKET_RECEIVED, AUDIO_EVENT, rtp_header.rtp_timestamp, |
88 rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id, | 78 rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id, |
89 payload_size); | 79 payload_size); |
90 | 80 |
91 bool duplicate = false; | 81 bool duplicate = false; |
92 const bool complete = | 82 const bool complete = |
93 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); | 83 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); |
94 | 84 |
95 // Duplicate packets are ignored. | 85 // Duplicate packets are ignored. |
96 if (duplicate || !complete) | 86 if (duplicate) |
| 87 return; |
| 88 |
| 89 // Update lip-sync values upon receiving the first packet of each frame, or if |
| 90 // they have never been set yet. |
| 91 if (rtp_header.packet_id == 0 || lip_sync_reference_time_.is_null()) { |
| 92 RtpTimestamp fresh_sync_rtp; |
| 93 base::TimeTicks fresh_sync_reference; |
| 94 if (!rtcp_.GetLatestLipSyncTimes(&fresh_sync_rtp, &fresh_sync_reference)) { |
| 95 // HACK: The sender should have provided Sender Reports before the first |
| 96 // frame was sent. However, the spec does not currently require this. |
| 97 // Therefore, when the data is missing, the local clock is used to |
| 98 // generate reference timestamps. |
| 99 VLOG(2) << "Lip sync info missing. Falling-back to local clock."; |
| 100 fresh_sync_rtp = rtp_header.rtp_timestamp; |
| 101 fresh_sync_reference = now; |
| 102 } |
| 103 // |lip_sync_reference_time_| is always incremented according to the time |
| 104 // delta computed from the difference in RTP timestamps. Then, |
| 105 // |lip_sync_drift_| accounts for clock drift and also smoothes-out any |
| 106 // sudden/discontinuous shifts in the series of reference time values. |
| 107 if (lip_sync_reference_time_.is_null()) { |
| 108 lip_sync_reference_time_ = fresh_sync_reference; |
| 109 } else { |
| 110 lip_sync_reference_time_ += RtpDeltaToTimeDelta( |
| 111 static_cast<int32>(fresh_sync_rtp - lip_sync_rtp_timestamp_), |
| 112 frequency_); |
| 113 } |
| 114 lip_sync_rtp_timestamp_ = fresh_sync_rtp; |
| 115 lip_sync_drift_.Update( |
| 116 now, fresh_sync_reference - lip_sync_reference_time_); |
| 117 } |
| 118 |
| 119 // Frame not complete; wait for more packets. |
| 120 if (!complete) |
97 return; | 121 return; |
98 | 122 |
99 EmitAvailableEncodedFrames(); | 123 EmitAvailableEncodedFrames(); |
100 } | 124 } |
101 | 125 |
102 void AudioReceiver::GetRawAudioFrame( | 126 void AudioReceiver::GetRawAudioFrame( |
103 const AudioFrameDecodedCallback& callback) { | 127 const AudioFrameDecodedCallback& callback) { |
104 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 128 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
105 DCHECK(!callback.is_null()); | 129 DCHECK(!callback.is_null()); |
106 DCHECK(audio_decoder_.get()); | 130 DCHECK(audio_decoder_.get()); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 // payload yet! Or, at least, peek using a StringPiece instead of a copy. | 192 // payload yet! Or, at least, peek using a StringPiece instead of a copy. |
169 scoped_ptr<transport::EncodedFrame> encoded_frame( | 193 scoped_ptr<transport::EncodedFrame> encoded_frame( |
170 new transport::EncodedFrame()); | 194 new transport::EncodedFrame()); |
171 bool is_consecutively_next_frame = false; | 195 bool is_consecutively_next_frame = false; |
172 if (!framer_.GetEncodedAudioFrame(encoded_frame.get(), | 196 if (!framer_.GetEncodedAudioFrame(encoded_frame.get(), |
173 &is_consecutively_next_frame)) { | 197 &is_consecutively_next_frame)) { |
174 VLOG(1) << "Wait for more audio packets to produce a completed frame."; | 198 VLOG(1) << "Wait for more audio packets to produce a completed frame."; |
175 return; // OnReceivedPayloadData() will invoke this method in the future. | 199 return; // OnReceivedPayloadData() will invoke this method in the future. |
176 } | 200 } |
177 | 201 |
| 202 const base::TimeTicks playout_time = |
| 203 GetPlayoutTime(encoded_frame->rtp_timestamp); |
| 204 |
178 // If |framer_| has a frame ready that is out of sequence, examine the | 205 // If |framer_| has a frame ready that is out of sequence, examine the |
179 // playout time to determine whether it's acceptable to continue, thereby | 206 // playout time to determine whether it's acceptable to continue, thereby |
180 // skipping one or more frames. Skip if the missing frame wouldn't complete | 207 // skipping one or more frames. Skip if the missing frame wouldn't complete |
181 // playing before the start of playback of the available frame. | 208 // playing before the start of playback of the available frame. |
182 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | |
183 const base::TimeTicks playout_time = | |
184 GetPlayoutTime(now, encoded_frame->rtp_timestamp); | |
185 if (!is_consecutively_next_frame) { | 209 if (!is_consecutively_next_frame) { |
| 210 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
186 // TODO(miu): Also account for expected decode time here? | 211 // TODO(miu): Also account for expected decode time here? |
187 const base::TimeTicks earliest_possible_end_time_of_missing_frame = | 212 const base::TimeTicks earliest_possible_end_time_of_missing_frame = |
188 now + base::TimeDelta::FromMilliseconds(kTypicalAudioFrameDurationMs); | 213 now + base::TimeDelta::FromMilliseconds(kTypicalAudioFrameDurationMs); |
189 if (earliest_possible_end_time_of_missing_frame < playout_time) { | 214 if (earliest_possible_end_time_of_missing_frame < playout_time) { |
190 VLOG(1) << "Wait for next consecutive frame instead of skipping."; | 215 VLOG(1) << "Wait for next consecutive frame instead of skipping."; |
191 if (!is_waiting_for_consecutive_frame_) { | 216 if (!is_waiting_for_consecutive_frame_) { |
192 is_waiting_for_consecutive_frame_ = true; | 217 is_waiting_for_consecutive_frame_ = true; |
193 cast_environment_->PostDelayedTask( | 218 cast_environment_->PostDelayedTask( |
194 CastEnvironment::MAIN, | 219 CastEnvironment::MAIN, |
195 FROM_HERE, | 220 FROM_HERE, |
(...skipping 30 matching lines...) Expand all Loading... |
226 } | 251 } |
227 } | 252 } |
228 | 253 |
229 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() { | 254 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() { |
230 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 255 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
231 DCHECK(is_waiting_for_consecutive_frame_); | 256 DCHECK(is_waiting_for_consecutive_frame_); |
232 is_waiting_for_consecutive_frame_ = false; | 257 is_waiting_for_consecutive_frame_ = false; |
233 EmitAvailableEncodedFrames(); | 258 EmitAvailableEncodedFrames(); |
234 } | 259 } |
235 | 260 |
| 261 base::TimeTicks AudioReceiver::GetPlayoutTime(uint32 rtp_timestamp) const { |
| 262 return lip_sync_reference_time_ + |
| 263 lip_sync_drift_.Current() + |
| 264 RtpDeltaToTimeDelta( |
| 265 static_cast<int32>(rtp_timestamp - lip_sync_rtp_timestamp_), |
| 266 frequency_) + |
| 267 target_playout_delay_; |
| 268 } |
| 269 |
236 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) { | 270 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) { |
237 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 271 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
238 if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) { | 272 if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) { |
239 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); | 273 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); |
240 } else { | 274 } else { |
241 ReceivedPacket(&packet->front(), packet->size()); | 275 ReceivedPacket(&packet->front(), packet->size()); |
242 } | 276 } |
243 } | 277 if (!reports_are_scheduled_) { |
244 | 278 ScheduleNextRtcpReport(); |
245 void AudioReceiver::SetTargetDelay(base::TimeDelta target_delay) { | 279 ScheduleNextCastMessage(); |
246 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 280 reports_are_scheduled_ = true; |
247 target_delay_delta_ = target_delay; | 281 } |
248 rtcp_.SetTargetDelay(target_delay_delta_); | |
249 } | 282 } |
250 | 283 |
251 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { | 284 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { |
252 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 285 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
253 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 286 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
254 RtpTimestamp rtp_timestamp = | 287 RtpTimestamp rtp_timestamp = |
255 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id_ & 0xff]; | 288 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id_ & 0xff]; |
256 cast_environment_->Logging()->InsertFrameEvent( | 289 cast_environment_->Logging()->InsertFrameEvent( |
257 now, FRAME_ACK_SENT, AUDIO_EVENT, rtp_timestamp, | 290 now, FRAME_ACK_SENT, AUDIO_EVENT, rtp_timestamp, |
258 cast_message.ack_frame_id_); | 291 cast_message.ack_frame_id_); |
259 | 292 |
260 ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; | 293 ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; |
261 event_subscriber_.GetRtcpEventsAndReset(&rtcp_events); | 294 event_subscriber_.GetRtcpEventsAndReset(&rtcp_events); |
262 rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events); | 295 rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events); |
263 } | 296 } |
264 | 297 |
265 base::TimeTicks AudioReceiver::GetPlayoutTime(base::TimeTicks now, | |
266 uint32 rtp_timestamp) { | |
267 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | |
268 // Senders time in ms when this frame was recorded. | |
269 // Note: the senders clock and our local clock might not be synced. | |
270 base::TimeTicks rtp_timestamp_in_ticks; | |
271 base::TimeTicks playout_time; | |
272 if (time_offset_ == base::TimeDelta()) { | |
273 if (rtcp_.RtpTimestampInSenderTime(frequency_, | |
274 first_incoming_rtp_timestamp_, | |
275 &rtp_timestamp_in_ticks)) { | |
276 time_offset_ = time_first_incoming_packet_ - rtp_timestamp_in_ticks; | |
277 // TODO(miu): As clocks drift w.r.t. each other, and other factors take | |
278 // effect, |time_offset_| should be updated. Otherwise, we might as well | |
279 // always compute the time offsets agnostic of RTCP's time data. | |
280 } else { | |
281 // We have not received any RTCP to sync the stream play it out as soon as | |
282 // possible. | |
283 | |
284 // BUG: This means we're literally switching to a different timeline a | |
285 // short time after a cast receiver has been running. Re-enable | |
286 // End2EndTest.StartSenderBeforeReceiver once this is fixed. | |
287 // http://crbug.com/356942 | |
288 uint32 rtp_timestamp_diff = rtp_timestamp - first_incoming_rtp_timestamp_; | |
289 | |
290 int frequency_khz = frequency_ / 1000; | |
291 base::TimeDelta rtp_time_diff_delta = | |
292 base::TimeDelta::FromMilliseconds(rtp_timestamp_diff / frequency_khz); | |
293 base::TimeDelta time_diff_delta = now - time_first_incoming_packet_; | |
294 | |
295 playout_time = now + std::max(rtp_time_diff_delta - time_diff_delta, | |
296 base::TimeDelta()); | |
297 } | |
298 } | |
299 if (playout_time.is_null()) { | |
300 // This can fail if we have not received any RTCP packets in a long time. | |
301 if (rtcp_.RtpTimestampInSenderTime(frequency_, rtp_timestamp, | |
302 &rtp_timestamp_in_ticks)) { | |
303 playout_time = | |
304 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_; | |
305 } else { | |
306 playout_time = now; | |
307 } | |
308 } | |
309 | |
310 // TODO(miu): This is broken since we literally switch timelines once |rtcp_| | |
311 // can provide us the |time_offset_|. Furthermore, this "getter" method may | |
312 // be called on frames received out-of-order, which means the playout times | |
313 // for earlier frames will be computed incorrectly. | |
314 #if 0 | |
315 // Don't allow the playout time to go backwards. | |
316 if (last_playout_time_ > playout_time) playout_time = last_playout_time_; | |
317 last_playout_time_ = playout_time; | |
318 #endif | |
319 | |
320 return playout_time; | |
321 } | |
322 | |
323 void AudioReceiver::ScheduleNextRtcpReport() { | 298 void AudioReceiver::ScheduleNextRtcpReport() { |
324 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 299 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
325 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() - | 300 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() - |
326 cast_environment_->Clock()->NowTicks(); | 301 cast_environment_->Clock()->NowTicks(); |
327 | 302 |
328 time_to_send = std::max( | 303 time_to_send = std::max( |
329 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 304 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
330 | 305 |
331 cast_environment_->PostDelayedTask( | 306 cast_environment_->PostDelayedTask( |
332 CastEnvironment::MAIN, | 307 CastEnvironment::MAIN, |
(...skipping 29 matching lines...) Expand all Loading... |
362 } | 337 } |
363 | 338 |
364 void AudioReceiver::SendNextCastMessage() { | 339 void AudioReceiver::SendNextCastMessage() { |
365 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 340 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
366 framer_.SendCastMessage(); // Will only send a message if it is time. | 341 framer_.SendCastMessage(); // Will only send a message if it is time. |
367 ScheduleNextCastMessage(); | 342 ScheduleNextCastMessage(); |
368 } | 343 } |
369 | 344 |
370 } // namespace cast | 345 } // namespace cast |
371 } // namespace media | 346 } // namespace media |
OLD | NEW |