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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "crypto/encryptor.h" |
| 11 #include "crypto/symmetric_key.h" |
10 #include "media/cast/audio_receiver/audio_decoder.h" | 12 #include "media/cast/audio_receiver/audio_decoder.h" |
11 #include "media/cast/framer/framer.h" | 13 #include "media/cast/framer/framer.h" |
12 #include "media/cast/rtcp/rtcp.h" | 14 #include "media/cast/rtcp/rtcp.h" |
13 #include "media/cast/rtp_receiver/rtp_receiver.h" | 15 #include "media/cast/rtp_receiver/rtp_receiver.h" |
14 | 16 |
15 // Max time we wait until an audio frame is due to be played out is released. | 17 // Max time we wait until an audio frame is due to be played out is released. |
16 static const int64 kMaxAudioFrameWaitMs = 20; | 18 static const int64 kMaxAudioFrameWaitMs = 20; |
17 static const int64 kMinSchedulingDelayMs = 1; | 19 static const int64 kMinSchedulingDelayMs = 1; |
18 | 20 |
19 namespace media { | 21 namespace media { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this)); | 92 incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this)); |
91 if (audio_config.use_external_decoder) { | 93 if (audio_config.use_external_decoder) { |
92 audio_buffer_.reset(new Framer(cast_environment->Clock(), | 94 audio_buffer_.reset(new Framer(cast_environment->Clock(), |
93 incoming_payload_feedback_.get(), | 95 incoming_payload_feedback_.get(), |
94 audio_config.incoming_ssrc, | 96 audio_config.incoming_ssrc, |
95 true, | 97 true, |
96 0)); | 98 0)); |
97 } else { | 99 } else { |
98 audio_decoder_ = new AudioDecoder(audio_config); | 100 audio_decoder_ = new AudioDecoder(audio_config); |
99 } | 101 } |
| 102 if (audio_config.aes_iv_mask.size() == kAesKeySize && |
| 103 audio_config.aes_key.size() == kAesKeySize) { |
| 104 iv_mask_ = audio_config.aes_iv_mask; |
| 105 crypto::SymmetricKey* key = crypto::SymmetricKey::Import( |
| 106 crypto::SymmetricKey::AES, audio_config.aes_key); |
| 107 decryptor_.reset(new crypto::Encryptor()); |
| 108 decryptor_->Init(key, crypto::Encryptor::CTR, std::string()); |
| 109 } else if (audio_config.aes_iv_mask.size() != 0 || |
| 110 audio_config.aes_key.size() != 0) { |
| 111 DCHECK(false) << "Invalid crypto configuration"; |
| 112 } |
| 113 |
100 rtp_receiver_.reset(new RtpReceiver(cast_environment->Clock(), | 114 rtp_receiver_.reset(new RtpReceiver(cast_environment->Clock(), |
101 &audio_config, | 115 &audio_config, |
102 NULL, | 116 NULL, |
103 incoming_payload_callback_.get())); | 117 incoming_payload_callback_.get())); |
104 rtp_audio_receiver_statistics_.reset( | 118 rtp_audio_receiver_statistics_.reset( |
105 new LocalRtpReceiverStatistics(rtp_receiver_.get())); | 119 new LocalRtpReceiverStatistics(rtp_receiver_.get())); |
106 base::TimeDelta rtcp_interval_delta = | 120 base::TimeDelta rtcp_interval_delta = |
107 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval); | 121 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval); |
108 rtcp_.reset(new Rtcp(cast_environment->Clock(), | 122 rtcp_.reset(new Rtcp(cast_environment->Clock(), |
109 NULL, | 123 NULL, |
(...skipping 21 matching lines...) Expand all Loading... |
131 // TODO(pwestin): update this as video to refresh over time. | 145 // TODO(pwestin): update this as video to refresh over time. |
132 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 146 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
133 if (time_first_incoming_packet_.is_null()) { | 147 if (time_first_incoming_packet_.is_null()) { |
134 InitializeTimers(); | 148 InitializeTimers(); |
135 first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp; | 149 first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp; |
136 time_first_incoming_packet_ = cast_environment_->Clock()->NowTicks(); | 150 time_first_incoming_packet_ = cast_environment_->Clock()->NowTicks(); |
137 } | 151 } |
138 | 152 |
139 if (audio_decoder_) { | 153 if (audio_decoder_) { |
140 DCHECK(!audio_buffer_) << "Invalid internal state"; | 154 DCHECK(!audio_buffer_) << "Invalid internal state"; |
141 audio_decoder_->IncomingParsedRtpPacket(payload_data, payload_size, | 155 std::string plaintext(reinterpret_cast<const char*>(payload_data), |
142 rtp_header); | 156 payload_size); |
| 157 if (decryptor_) { |
| 158 plaintext.clear(); |
| 159 if (!decryptor_->SetCounter(GetAesNonce(rtp_header.frame_id, iv_mask_))) { |
| 160 NOTREACHED() << "Failed to set counter"; |
| 161 return; |
| 162 } |
| 163 if (!decryptor_->Decrypt(base::StringPiece(reinterpret_cast<const char*>( |
| 164 payload_data), payload_size), &plaintext)) { |
| 165 VLOG(0) << "Decryption error"; |
| 166 return; |
| 167 } |
| 168 } |
| 169 audio_decoder_->IncomingParsedRtpPacket( |
| 170 reinterpret_cast<const uint8*>(plaintext.data()), plaintext.size(), |
| 171 rtp_header); |
143 return; | 172 return; |
144 } | 173 } |
145 DCHECK(audio_buffer_) << "Invalid internal state"; | 174 DCHECK(audio_buffer_) << "Invalid internal state"; |
146 DCHECK(!audio_decoder_) << "Invalid internal state"; | 175 DCHECK(!audio_decoder_) << "Invalid internal state"; |
147 bool complete = audio_buffer_->InsertPacket(payload_data, payload_size, | 176 bool complete = audio_buffer_->InsertPacket(payload_data, payload_size, |
148 rtp_header); | 177 rtp_header); |
149 if (!complete) return; // Audio frame not complete; wait for more packets. | 178 if (!complete) return; // Audio frame not complete; wait for more packets. |
150 if (queued_encoded_callbacks_.empty()) return; // No pending callback. | 179 if (queued_encoded_callbacks_.empty()) return; // No pending callback. |
151 | 180 |
152 AudioFrameEncodedCallback callback = queued_encoded_callbacks_.front(); | 181 AudioFrameEncodedCallback callback = queued_encoded_callbacks_.front(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 | 236 |
208 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), | 237 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), |
209 &rtp_timestamp, &next_frame)) { | 238 &rtp_timestamp, &next_frame)) { |
210 // We have no audio frames. Wait for new packet(s). | 239 // We have no audio frames. Wait for new packet(s). |
211 // Since the application can post multiple AudioFrameEncodedCallback and | 240 // Since the application can post multiple AudioFrameEncodedCallback and |
212 // we only check the next frame to play out we might have multiple timeout | 241 // we only check the next frame to play out we might have multiple timeout |
213 // events firing after each other; however this should be a rare event. | 242 // events firing after each other; however this should be a rare event. |
214 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; | 243 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; |
215 return; | 244 return; |
216 } | 245 } |
| 246 |
| 247 if (decryptor_ && !DecryptAudioFrame(&encoded_frame)) { |
| 248 // Logging already done. |
| 249 return; |
| 250 } |
| 251 |
217 if (PostEncodedAudioFrame(queued_encoded_callbacks_.front(), rtp_timestamp, | 252 if (PostEncodedAudioFrame(queued_encoded_callbacks_.front(), rtp_timestamp, |
218 next_frame, &encoded_frame)) { | 253 next_frame, &encoded_frame)) { |
219 // Call succeed remove callback from list. | 254 // Call succeed remove callback from list. |
220 queued_encoded_callbacks_.pop_front(); | 255 queued_encoded_callbacks_.pop_front(); |
221 } | 256 } |
222 } | 257 } |
223 | 258 |
224 void AudioReceiver::GetEncodedAudioFrame( | 259 void AudioReceiver::GetEncodedAudioFrame( |
225 const AudioFrameEncodedCallback& callback) { | 260 const AudioFrameEncodedCallback& callback) { |
226 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 261 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
227 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; | 262 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; |
228 | 263 |
229 uint32 rtp_timestamp = 0; | 264 uint32 rtp_timestamp = 0; |
230 bool next_frame = false; | 265 bool next_frame = false; |
231 scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame()); | 266 scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame()); |
232 | 267 |
233 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), | 268 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), |
234 &rtp_timestamp, &next_frame)) { | 269 &rtp_timestamp, &next_frame)) { |
235 // We have no audio frames. Wait for new packet(s). | 270 // We have no audio frames. Wait for new packet(s). |
236 VLOG(1) << "Wait for more audio packets in frame"; | 271 VLOG(1) << "Wait for more audio packets in frame"; |
237 queued_encoded_callbacks_.push_back(callback); | 272 queued_encoded_callbacks_.push_back(callback); |
238 return; | 273 return; |
239 } | 274 } |
| 275 if (decryptor_ && !DecryptAudioFrame(&encoded_frame)) { |
| 276 // Logging already done. |
| 277 queued_encoded_callbacks_.push_back(callback); |
| 278 return; |
| 279 } |
240 if (!PostEncodedAudioFrame(callback, rtp_timestamp, next_frame, | 280 if (!PostEncodedAudioFrame(callback, rtp_timestamp, next_frame, |
241 &encoded_frame)) { | 281 &encoded_frame)) { |
242 // We have an audio frame; however we are missing packets and we have time | 282 // We have an audio frame; however we are missing packets and we have time |
243 // to wait for new packet(s). | 283 // to wait for new packet(s). |
244 queued_encoded_callbacks_.push_back(callback); | 284 queued_encoded_callbacks_.push_back(callback); |
245 } | 285 } |
246 } | 286 } |
247 | 287 |
248 bool AudioReceiver::PostEncodedAudioFrame( | 288 bool AudioReceiver::PostEncodedAudioFrame( |
249 const AudioFrameEncodedCallback& callback, | 289 const AudioFrameEncodedCallback& callback, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 base::TimeDelta()); | 357 base::TimeDelta()); |
318 } | 358 } |
319 } | 359 } |
320 // This can fail if we have not received any RTCP packets in a long time. | 360 // This can fail if we have not received any RTCP packets in a long time. |
321 return rtcp_->RtpTimestampInSenderTime(frequency_, rtp_timestamp, | 361 return rtcp_->RtpTimestampInSenderTime(frequency_, rtp_timestamp, |
322 &rtp_timestamp_in_ticks) ? | 362 &rtp_timestamp_in_ticks) ? |
323 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_ : | 363 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_ : |
324 now; | 364 now; |
325 } | 365 } |
326 | 366 |
| 367 bool AudioReceiver::DecryptAudioFrame( |
| 368 scoped_ptr<EncodedAudioFrame>* audio_frame) { |
| 369 DCHECK(decryptor_) << "Invalid state"; |
| 370 |
| 371 if (!decryptor_->SetCounter(GetAesNonce((*audio_frame)->frame_id, |
| 372 iv_mask_))) { |
| 373 NOTREACHED() << "Failed to set counter"; |
| 374 return false; |
| 375 } |
| 376 std::string decrypted_audio_data; |
| 377 if (!decryptor_->Decrypt((*audio_frame)->data, &decrypted_audio_data)) { |
| 378 VLOG(0) << "Decryption error"; |
| 379 // Give up on this frame, release it from jitter buffer. |
| 380 audio_buffer_->ReleaseFrame((*audio_frame)->frame_id); |
| 381 return false; |
| 382 } |
| 383 (*audio_frame)->data.swap(decrypted_audio_data); |
| 384 return true; |
| 385 } |
| 386 |
327 void AudioReceiver::ScheduleNextRtcpReport() { | 387 void AudioReceiver::ScheduleNextRtcpReport() { |
328 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 388 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
329 base::TimeDelta time_to_send = rtcp_->TimeToSendNextRtcpReport() - | 389 base::TimeDelta time_to_send = rtcp_->TimeToSendNextRtcpReport() - |
330 cast_environment_->Clock()->NowTicks(); | 390 cast_environment_->Clock()->NowTicks(); |
331 | 391 |
332 time_to_send = std::max(time_to_send, | 392 time_to_send = std::max(time_to_send, |
333 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 393 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
334 | 394 |
335 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, | 395 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, |
336 base::Bind(&AudioReceiver::SendNextRtcpReport, | 396 base::Bind(&AudioReceiver::SendNextRtcpReport, |
(...skipping 27 matching lines...) Expand all Loading... |
364 | 424 |
365 void AudioReceiver::SendNextCastMessage() { | 425 void AudioReceiver::SendNextCastMessage() { |
366 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 426 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
367 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; | 427 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; |
368 audio_buffer_->SendCastMessage(); // Will only send a message if it is time. | 428 audio_buffer_->SendCastMessage(); // Will only send a message if it is time. |
369 ScheduleNextCastMessage(); | 429 ScheduleNextCastMessage(); |
370 } | 430 } |
371 | 431 |
372 } // namespace cast | 432 } // namespace cast |
373 } // namespace media | 433 } // namespace media |
OLD | NEW |