Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: media/cast/audio_receiver/audio_receiver.cc

Issue 62843002: Cast: Added support for AES-CTR crypto. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync TOT Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/cast/audio_receiver/audio_receiver.h ('k') | media/cast/audio_receiver/audio_receiver.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698