| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 bool have_multiple_complete_frames = false; | 196 bool have_multiple_complete_frames = false; |
| 173 if (!framer_.GetEncodedFrame(encoded_frame.get(), | 197 if (!framer_.GetEncodedFrame(encoded_frame.get(), |
| 174 &is_consecutively_next_frame, | 198 &is_consecutively_next_frame, |
| 175 &have_multiple_complete_frames)) { | 199 &have_multiple_complete_frames)) { |
| 176 VLOG(1) << "Wait for more audio packets to produce a completed frame."; | 200 VLOG(1) << "Wait for more audio packets to produce a completed frame."; |
| 177 return; // OnReceivedPayloadData() will invoke this method in the future. | 201 return; // OnReceivedPayloadData() will invoke this method in the future. |
| 178 } | 202 } |
| 179 | 203 |
| 180 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 204 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 181 const base::TimeTicks playout_time = | 205 const base::TimeTicks playout_time = |
| 182 GetPlayoutTime(now, encoded_frame->rtp_timestamp); | 206 GetPlayoutTime(encoded_frame->rtp_timestamp); |
| 183 | 207 |
| 184 // If we have multiple decodable frames, and the current frame is | 208 // If we have multiple decodable frames, and the current frame is |
| 185 // too old, then skip it and decode the next frame instead. | 209 // too old, then skip it and decode the next frame instead. |
| 186 if (have_multiple_complete_frames && now > playout_time) { | 210 if (have_multiple_complete_frames && now > playout_time) { |
| 187 framer_.ReleaseFrame(encoded_frame->frame_id); | 211 framer_.ReleaseFrame(encoded_frame->frame_id); |
| 188 continue; | 212 continue; |
| 189 } | 213 } |
| 190 | 214 |
| 191 // If |framer_| has a frame ready that is out of sequence, examine the | 215 // If |framer_| has a frame ready that is out of sequence, examine the |
| 192 // playout time to determine whether it's acceptable to continue, thereby | 216 // playout time to determine whether it's acceptable to continue, thereby |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 } | 260 } |
| 237 } | 261 } |
| 238 | 262 |
| 239 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() { | 263 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() { |
| 240 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 264 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 241 DCHECK(is_waiting_for_consecutive_frame_); | 265 DCHECK(is_waiting_for_consecutive_frame_); |
| 242 is_waiting_for_consecutive_frame_ = false; | 266 is_waiting_for_consecutive_frame_ = false; |
| 243 EmitAvailableEncodedFrames(); | 267 EmitAvailableEncodedFrames(); |
| 244 } | 268 } |
| 245 | 269 |
| 270 base::TimeTicks AudioReceiver::GetPlayoutTime(uint32 rtp_timestamp) const { |
| 271 return lip_sync_reference_time_ + |
| 272 lip_sync_drift_.Current() + |
| 273 RtpDeltaToTimeDelta( |
| 274 static_cast<int32>(rtp_timestamp - lip_sync_rtp_timestamp_), |
| 275 frequency_) + |
| 276 target_playout_delay_; |
| 277 } |
| 278 |
| 246 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) { | 279 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) { |
| 247 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 280 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 248 if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) { | 281 if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) { |
| 249 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); | 282 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); |
| 250 } else { | 283 } else { |
| 251 ReceivedPacket(&packet->front(), packet->size()); | 284 ReceivedPacket(&packet->front(), packet->size()); |
| 252 } | 285 } |
| 253 } | 286 if (!reports_are_scheduled_) { |
| 254 | 287 ScheduleNextRtcpReport(); |
| 255 void AudioReceiver::SetTargetDelay(base::TimeDelta target_delay) { | 288 ScheduleNextCastMessage(); |
| 256 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 289 reports_are_scheduled_ = true; |
| 257 target_delay_delta_ = target_delay; | 290 } |
| 258 rtcp_.SetTargetDelay(target_delay_delta_); | |
| 259 } | 291 } |
| 260 | 292 |
| 261 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { | 293 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { |
| 262 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 294 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 263 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 295 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 264 RtpTimestamp rtp_timestamp = | 296 RtpTimestamp rtp_timestamp = |
| 265 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id_ & 0xff]; | 297 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id_ & 0xff]; |
| 266 cast_environment_->Logging()->InsertFrameEvent( | 298 cast_environment_->Logging()->InsertFrameEvent( |
| 267 now, FRAME_ACK_SENT, AUDIO_EVENT, rtp_timestamp, | 299 now, FRAME_ACK_SENT, AUDIO_EVENT, rtp_timestamp, |
| 268 cast_message.ack_frame_id_); | 300 cast_message.ack_frame_id_); |
| 269 | 301 |
| 270 ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; | 302 ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; |
| 271 event_subscriber_.GetRtcpEventsAndReset(&rtcp_events); | 303 event_subscriber_.GetRtcpEventsAndReset(&rtcp_events); |
| 272 rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events); | 304 rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events); |
| 273 } | 305 } |
| 274 | 306 |
| 275 base::TimeTicks AudioReceiver::GetPlayoutTime(base::TimeTicks now, | |
| 276 uint32 rtp_timestamp) { | |
| 277 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | |
| 278 // Senders time in ms when this frame was recorded. | |
| 279 // Note: the senders clock and our local clock might not be synced. | |
| 280 base::TimeTicks rtp_timestamp_in_ticks; | |
| 281 base::TimeTicks playout_time; | |
| 282 if (time_offset_ == base::TimeDelta()) { | |
| 283 if (rtcp_.RtpTimestampInSenderTime(frequency_, | |
| 284 first_incoming_rtp_timestamp_, | |
| 285 &rtp_timestamp_in_ticks)) { | |
| 286 time_offset_ = time_first_incoming_packet_ - rtp_timestamp_in_ticks; | |
| 287 // TODO(miu): As clocks drift w.r.t. each other, and other factors take | |
| 288 // effect, |time_offset_| should be updated. Otherwise, we might as well | |
| 289 // always compute the time offsets agnostic of RTCP's time data. | |
| 290 } else { | |
| 291 // We have not received any RTCP to sync the stream play it out as soon as | |
| 292 // possible. | |
| 293 | |
| 294 // BUG: This means we're literally switching to a different timeline a | |
| 295 // short time after a cast receiver has been running. Re-enable | |
| 296 // End2EndTest.StartSenderBeforeReceiver once this is fixed. | |
| 297 // http://crbug.com/356942 | |
| 298 uint32 rtp_timestamp_diff = rtp_timestamp - first_incoming_rtp_timestamp_; | |
| 299 | |
| 300 int frequency_khz = frequency_ / 1000; | |
| 301 base::TimeDelta rtp_time_diff_delta = | |
| 302 base::TimeDelta::FromMilliseconds(rtp_timestamp_diff / frequency_khz); | |
| 303 base::TimeDelta time_diff_delta = now - time_first_incoming_packet_; | |
| 304 | |
| 305 playout_time = now + std::max(rtp_time_diff_delta - time_diff_delta, | |
| 306 base::TimeDelta()); | |
| 307 } | |
| 308 } | |
| 309 if (playout_time.is_null()) { | |
| 310 // This can fail if we have not received any RTCP packets in a long time. | |
| 311 if (rtcp_.RtpTimestampInSenderTime(frequency_, rtp_timestamp, | |
| 312 &rtp_timestamp_in_ticks)) { | |
| 313 playout_time = | |
| 314 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_; | |
| 315 } else { | |
| 316 playout_time = now; | |
| 317 } | |
| 318 } | |
| 319 | |
| 320 // TODO(miu): This is broken since we literally switch timelines once |rtcp_| | |
| 321 // can provide us the |time_offset_|. Furthermore, this "getter" method may | |
| 322 // be called on frames received out-of-order, which means the playout times | |
| 323 // for earlier frames will be computed incorrectly. | |
| 324 #if 0 | |
| 325 // Don't allow the playout time to go backwards. | |
| 326 if (last_playout_time_ > playout_time) playout_time = last_playout_time_; | |
| 327 last_playout_time_ = playout_time; | |
| 328 #endif | |
| 329 | |
| 330 return playout_time; | |
| 331 } | |
| 332 | |
| 333 void AudioReceiver::ScheduleNextRtcpReport() { | 307 void AudioReceiver::ScheduleNextRtcpReport() { |
| 334 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 308 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 335 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() - | 309 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() - |
| 336 cast_environment_->Clock()->NowTicks(); | 310 cast_environment_->Clock()->NowTicks(); |
| 337 | 311 |
| 338 time_to_send = std::max( | 312 time_to_send = std::max( |
| 339 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 313 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
| 340 | 314 |
| 341 cast_environment_->PostDelayedTask( | 315 cast_environment_->PostDelayedTask( |
| 342 CastEnvironment::MAIN, | 316 CastEnvironment::MAIN, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 372 } | 346 } |
| 373 | 347 |
| 374 void AudioReceiver::SendNextCastMessage() { | 348 void AudioReceiver::SendNextCastMessage() { |
| 375 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 349 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 376 framer_.SendCastMessage(); // Will only send a message if it is time. | 350 framer_.SendCastMessage(); // Will only send a message if it is time. |
| 377 ScheduleNextCastMessage(); | 351 ScheduleNextCastMessage(); |
| 378 } | 352 } |
| 379 | 353 |
| 380 } // namespace cast | 354 } // namespace cast |
| 381 } // namespace media | 355 } // namespace media |
| OLD | NEW |