| 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> |
| 8 |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/logging.h" | 10 #include "base/logging.h" |
| 9 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 10 #include "media/cast/audio_receiver/audio_decoder.h" | 12 #include "media/cast/audio_receiver/audio_decoder.h" |
| 11 #include "media/cast/transport/cast_transport_defines.h" | 13 #include "media/cast/transport/cast_transport_defines.h" |
| 12 | 14 |
| 13 namespace { | 15 namespace { |
| 16 const int kMinSchedulingDelayMs = 1; |
| 17 // TODO(miu): This should go in AudioReceiverConfig. |
| 14 const int kTypicalAudioFrameDurationMs = 10; | 18 const int kTypicalAudioFrameDurationMs = 10; |
| 15 const int kMinSchedulingDelayMs = 1; | |
| 16 } // namespace | 19 } // namespace |
| 17 | 20 |
| 18 namespace media { | 21 namespace media { |
| 19 namespace cast { | 22 namespace cast { |
| 20 | 23 |
| 21 AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment, | 24 AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment, |
| 22 const AudioReceiverConfig& audio_config, | 25 const AudioReceiverConfig& audio_config, |
| 23 transport::PacedPacketSender* const packet_sender) | 26 transport::PacedPacketSender* const packet_sender) |
| 24 : RtpReceiver(cast_environment->Clock(), &audio_config, NULL), | 27 : RtpReceiver(cast_environment->Clock(), &audio_config, NULL), |
| 25 cast_environment_(cast_environment), | 28 cast_environment_(cast_environment), |
| 26 event_subscriber_(kReceiverRtcpEventHistorySize, | 29 event_subscriber_(kReceiverRtcpEventHistorySize, |
| 27 ReceiverRtcpEventSubscriber::kAudioEventSubscriber), | 30 ReceiverRtcpEventSubscriber::kAudioEventSubscriber), |
| 28 codec_(audio_config.codec), | 31 codec_(audio_config.codec), |
| 29 frequency_(audio_config.frequency), | 32 frequency_(audio_config.frequency), |
| 33 target_delay_delta_( |
| 34 base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms)), |
| 30 framer_(cast_environment->Clock(), | 35 framer_(cast_environment->Clock(), |
| 31 this, | 36 this, |
| 32 audio_config.incoming_ssrc, | 37 audio_config.incoming_ssrc, |
| 33 true, | 38 true, |
| 34 0), | 39 audio_config.rtp_max_delay_ms / kTypicalAudioFrameDurationMs), |
| 35 rtcp_(cast_environment, | 40 rtcp_(cast_environment, |
| 36 NULL, | 41 NULL, |
| 37 NULL, | 42 NULL, |
| 38 packet_sender, | 43 packet_sender, |
| 39 GetStatistics(), | 44 GetStatistics(), |
| 40 audio_config.rtcp_mode, | 45 audio_config.rtcp_mode, |
| 41 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval), | 46 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval), |
| 42 audio_config.feedback_ssrc, | 47 audio_config.feedback_ssrc, |
| 43 audio_config.incoming_ssrc, | 48 audio_config.incoming_ssrc, |
| 44 audio_config.rtcp_c_name), | 49 audio_config.rtcp_c_name), |
| 45 is_waiting_for_consecutive_frame_(false), | 50 is_waiting_for_consecutive_frame_(false), |
| 46 weak_factory_(this) { | 51 weak_factory_(this) { |
| 47 target_delay_delta_ = | |
| 48 base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms); | |
| 49 if (!audio_config.use_external_decoder) | 52 if (!audio_config.use_external_decoder) |
| 50 audio_decoder_.reset(new AudioDecoder(cast_environment, audio_config)); | 53 audio_decoder_.reset(new AudioDecoder(cast_environment, audio_config)); |
| 51 decryptor_.Initialize(audio_config.aes_key, audio_config.aes_iv_mask); | 54 decryptor_.Initialize(audio_config.aes_key, audio_config.aes_iv_mask); |
| 52 rtcp_.SetTargetDelay(target_delay_delta_); | 55 rtcp_.SetTargetDelay(target_delay_delta_); |
| 53 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); | 56 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); |
| 54 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); | 57 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); |
| 55 } | 58 } |
| 56 | 59 |
| 57 AudioReceiver::~AudioReceiver() { | 60 AudioReceiver::~AudioReceiver() { |
| 58 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 61 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 74 ScheduleNextRtcpReport(); | 77 ScheduleNextRtcpReport(); |
| 75 ScheduleNextCastMessage(); | 78 ScheduleNextCastMessage(); |
| 76 } | 79 } |
| 77 | 80 |
| 78 void AudioReceiver::OnReceivedPayloadData(const uint8* payload_data, | 81 void AudioReceiver::OnReceivedPayloadData(const uint8* payload_data, |
| 79 size_t payload_size, | 82 size_t payload_size, |
| 80 const RtpCastHeader& rtp_header) { | 83 const RtpCastHeader& rtp_header) { |
| 81 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 84 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 82 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 85 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 83 | 86 |
| 84 frame_id_to_rtp_timestamp_[rtp_header.frame_id & 0xff] = | |
| 85 rtp_header.webrtc.header.timestamp; | |
| 86 cast_environment_->Logging()->InsertPacketEvent( | |
| 87 now, kAudioPacketReceived, rtp_header.webrtc.header.timestamp, | |
| 88 rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id, | |
| 89 payload_size); | |
| 90 | |
| 91 // TODO(pwestin): update this as video to refresh over time. | 87 // TODO(pwestin): update this as video to refresh over time. |
| 92 if (time_first_incoming_packet_.is_null()) { | 88 if (time_first_incoming_packet_.is_null()) { |
| 93 InitializeTimers(); | 89 InitializeTimers(); |
| 94 first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp; | 90 first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp; |
| 95 time_first_incoming_packet_ = now; | 91 time_first_incoming_packet_ = now; |
| 96 } | 92 } |
| 97 | 93 |
| 94 frame_id_to_rtp_timestamp_[rtp_header.frame_id & 0xff] = |
| 95 rtp_header.webrtc.header.timestamp; |
| 96 cast_environment_->Logging()->InsertPacketEvent( |
| 97 now, kAudioPacketReceived, rtp_header.webrtc.header.timestamp, |
| 98 rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id, |
| 99 payload_size); |
| 100 |
| 98 bool duplicate = false; | 101 bool duplicate = false; |
| 99 const bool complete = | 102 const bool complete = |
| 100 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); | 103 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); |
| 101 if (duplicate) { | 104 if (duplicate) { |
| 102 cast_environment_->Logging()->InsertPacketEvent( | 105 cast_environment_->Logging()->InsertPacketEvent( |
| 103 now, kDuplicateAudioPacketReceived, rtp_header.webrtc.header.timestamp, | 106 now, |
| 104 rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id, | 107 kDuplicateAudioPacketReceived, |
| 108 rtp_header.webrtc.header.timestamp, |
| 109 rtp_header.frame_id, |
| 110 rtp_header.packet_id, |
| 111 rtp_header.max_packet_id, |
| 105 payload_size); | 112 payload_size); |
| 106 // Duplicate packets are ignored. | 113 // Duplicate packets are ignored. |
| 107 return; | 114 return; |
| 108 } | 115 } |
| 109 if (!complete) | 116 if (!complete) |
| 110 return; | 117 return; |
| 111 | 118 |
| 112 EmitAvailableEncodedFrames(); | 119 EmitAvailableEncodedFrames(); |
| 113 } | 120 } |
| 114 | 121 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 } | 197 } |
| 191 | 198 |
| 192 // If |framer_| has a frame ready that is out of sequence, examine the | 199 // If |framer_| has a frame ready that is out of sequence, examine the |
| 193 // playout time to determine whether it's acceptable to continue, thereby | 200 // playout time to determine whether it's acceptable to continue, thereby |
| 194 // skipping one or more frames. Skip if the missing frame wouldn't complete | 201 // skipping one or more frames. Skip if the missing frame wouldn't complete |
| 195 // playing before the start of playback of the available frame. | 202 // playing before the start of playback of the available frame. |
| 196 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 203 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 197 const base::TimeTicks playout_time = | 204 const base::TimeTicks playout_time = |
| 198 GetPlayoutTime(now, encoded_frame->rtp_timestamp); | 205 GetPlayoutTime(now, encoded_frame->rtp_timestamp); |
| 199 if (!is_consecutively_next_frame) { | 206 if (!is_consecutively_next_frame) { |
| 207 // TODO(miu): Also account for expected decode time here? |
| 200 const base::TimeTicks earliest_possible_end_time_of_missing_frame = | 208 const base::TimeTicks earliest_possible_end_time_of_missing_frame = |
| 201 now + base::TimeDelta::FromMilliseconds(kTypicalAudioFrameDurationMs); | 209 now + base::TimeDelta::FromMilliseconds(kTypicalAudioFrameDurationMs); |
| 202 if (earliest_possible_end_time_of_missing_frame < playout_time) { | 210 if (earliest_possible_end_time_of_missing_frame < playout_time) { |
| 203 VLOG(1) << "Wait for next consecutive frame instead of skipping."; | 211 VLOG(1) << "Wait for next consecutive frame instead of skipping."; |
| 204 if (!is_waiting_for_consecutive_frame_) { | 212 if (!is_waiting_for_consecutive_frame_) { |
| 205 is_waiting_for_consecutive_frame_ = true; | 213 is_waiting_for_consecutive_frame_ = true; |
| 206 cast_environment_->PostDelayedTask( | 214 cast_environment_->PostDelayedTask( |
| 207 CastEnvironment::MAIN, | 215 CastEnvironment::MAIN, |
| 208 FROM_HERE, | 216 FROM_HERE, |
| 209 base::Bind(&AudioReceiver::EmitAvailableEncodedFramesAfterWaiting, | 217 base::Bind(&AudioReceiver::EmitAvailableEncodedFramesAfterWaiting, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 | 250 |
| 243 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() { | 251 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() { |
| 244 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 252 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 245 DCHECK(is_waiting_for_consecutive_frame_); | 253 DCHECK(is_waiting_for_consecutive_frame_); |
| 246 is_waiting_for_consecutive_frame_ = false; | 254 is_waiting_for_consecutive_frame_ = false; |
| 247 EmitAvailableEncodedFrames(); | 255 EmitAvailableEncodedFrames(); |
| 248 } | 256 } |
| 249 | 257 |
| 250 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) { | 258 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) { |
| 251 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 259 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 252 bool rtcp_packet = Rtcp::IsRtcpPacket(&packet->front(), packet->size()); | 260 if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) { |
| 253 if (!rtcp_packet) { | 261 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); |
| 262 } else { |
| 254 ReceivedPacket(&packet->front(), packet->size()); | 263 ReceivedPacket(&packet->front(), packet->size()); |
| 255 } else { | |
| 256 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); | |
| 257 } | 264 } |
| 258 } | 265 } |
| 259 | 266 |
| 260 void AudioReceiver::SetTargetDelay(base::TimeDelta target_delay) { | 267 void AudioReceiver::SetTargetDelay(base::TimeDelta target_delay) { |
| 261 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 268 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 262 target_delay_delta_ = target_delay; | 269 target_delay_delta_ = target_delay; |
| 263 rtcp_.SetTargetDelay(target_delay_delta_); | 270 rtcp_.SetTargetDelay(target_delay_delta_); |
| 264 } | 271 } |
| 265 | 272 |
| 266 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { | 273 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 | 343 |
| 337 void AudioReceiver::ScheduleNextRtcpReport() { | 344 void AudioReceiver::ScheduleNextRtcpReport() { |
| 338 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 345 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 339 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() - | 346 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() - |
| 340 cast_environment_->Clock()->NowTicks(); | 347 cast_environment_->Clock()->NowTicks(); |
| 341 | 348 |
| 342 time_to_send = std::max( | 349 time_to_send = std::max( |
| 343 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 350 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
| 344 | 351 |
| 345 cast_environment_->PostDelayedTask( | 352 cast_environment_->PostDelayedTask( |
| 346 CastEnvironment::MAIN, FROM_HERE, | 353 CastEnvironment::MAIN, |
| 354 FROM_HERE, |
| 347 base::Bind(&AudioReceiver::SendNextRtcpReport, | 355 base::Bind(&AudioReceiver::SendNextRtcpReport, |
| 348 weak_factory_.GetWeakPtr()), | 356 weak_factory_.GetWeakPtr()), |
| 349 time_to_send); | 357 time_to_send); |
| 350 } | 358 } |
| 351 | 359 |
| 352 void AudioReceiver::SendNextRtcpReport() { | 360 void AudioReceiver::SendNextRtcpReport() { |
| 353 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 361 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 354 // TODO(pwestin): add logging. | 362 // TODO(pwestin): add logging. |
| 355 rtcp_.SendRtcpFromRtpReceiver(NULL, NULL); | 363 rtcp_.SendRtcpFromRtpReceiver(NULL, NULL); |
| 356 ScheduleNextRtcpReport(); | 364 ScheduleNextRtcpReport(); |
| 357 } | 365 } |
| 358 | 366 |
| 359 // Cast messages should be sent within a maximum interval. Schedule a call | 367 // Cast messages should be sent within a maximum interval. Schedule a call |
| 360 // if not triggered elsewhere, e.g. by the cast message_builder. | 368 // if not triggered elsewhere, e.g. by the cast message_builder. |
| 361 void AudioReceiver::ScheduleNextCastMessage() { | 369 void AudioReceiver::ScheduleNextCastMessage() { |
| 362 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 370 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 363 base::TimeTicks send_time; | 371 base::TimeTicks send_time; |
| 364 framer_.TimeToSendNextCastMessage(&send_time); | 372 framer_.TimeToSendNextCastMessage(&send_time); |
| 365 base::TimeDelta time_to_send = | 373 base::TimeDelta time_to_send = |
| 366 send_time - cast_environment_->Clock()->NowTicks(); | 374 send_time - cast_environment_->Clock()->NowTicks(); |
| 367 time_to_send = std::max( | 375 time_to_send = std::max( |
| 368 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 376 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
| 369 cast_environment_->PostDelayedTask( | 377 cast_environment_->PostDelayedTask( |
| 370 CastEnvironment::MAIN, FROM_HERE, | 378 CastEnvironment::MAIN, |
| 379 FROM_HERE, |
| 371 base::Bind(&AudioReceiver::SendNextCastMessage, | 380 base::Bind(&AudioReceiver::SendNextCastMessage, |
| 372 weak_factory_.GetWeakPtr()), | 381 weak_factory_.GetWeakPtr()), |
| 373 time_to_send); | 382 time_to_send); |
| 374 } | 383 } |
| 375 | 384 |
| 376 void AudioReceiver::SendNextCastMessage() { | 385 void AudioReceiver::SendNextCastMessage() { |
| 377 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 386 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 378 // Will only send a message if it is time. | 387 framer_.SendCastMessage(); // Will only send a message if it is time. |
| 379 framer_.SendCastMessage(); | |
| 380 ScheduleNextCastMessage(); | 388 ScheduleNextCastMessage(); |
| 381 } | 389 } |
| 382 | 390 |
| 383 } // namespace cast | 391 } // namespace cast |
| 384 } // namespace media | 392 } // namespace media |
| OLD | NEW |