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

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: Fixes 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this)); 94 incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this));
93 if (audio_config.use_external_decoder) { 95 if (audio_config.use_external_decoder) {
94 audio_buffer_.reset(new Framer(cast_environment->Clock(), 96 audio_buffer_.reset(new Framer(cast_environment->Clock(),
95 incoming_payload_feedback_.get(), 97 incoming_payload_feedback_.get(),
96 audio_config.incoming_ssrc, 98 audio_config.incoming_ssrc,
97 true, 99 true,
98 0)); 100 0));
99 } else { 101 } else {
100 audio_decoder_ = new AudioDecoder(audio_config); 102 audio_decoder_ = new AudioDecoder(audio_config);
101 } 103 }
104 if (audio_config.aes_iv_mask.size() == kAesKeySize &&
105 audio_config.aes_key.size() == kAesKeySize) {
106 iv_mask_ = audio_config.aes_iv_mask;
107 crypto::SymmetricKey* key = crypto::SymmetricKey::Import(
108 crypto::SymmetricKey::AES, audio_config.aes_key);
109 decryptor_.reset(new crypto::Encryptor());
110 decryptor_->Init(key, crypto::Encryptor::CTR, std::string());
111 } else if (audio_config.aes_iv_mask.size() != 0 ||
112 audio_config.aes_key.size() != 0) {
113 DCHECK(false) << "Invalid crypto configuration";
114 }
115
102 rtp_receiver_.reset(new RtpReceiver(cast_environment->Clock(), 116 rtp_receiver_.reset(new RtpReceiver(cast_environment->Clock(),
103 &audio_config, 117 &audio_config,
104 NULL, 118 NULL,
105 incoming_payload_callback_.get())); 119 incoming_payload_callback_.get()));
106 rtp_audio_receiver_statistics_.reset( 120 rtp_audio_receiver_statistics_.reset(
107 new LocalRtpReceiverStatistics(rtp_receiver_.get())); 121 new LocalRtpReceiverStatistics(rtp_receiver_.get()));
108 base::TimeDelta rtcp_interval_delta = 122 base::TimeDelta rtcp_interval_delta =
109 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval); 123 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval);
110 rtcp_.reset(new Rtcp(cast_environment->Clock(), 124 rtcp_.reset(new Rtcp(cast_environment->Clock(),
111 NULL, 125 NULL,
(...skipping 16 matching lines...) Expand all
128 size_t payload_size, 142 size_t payload_size,
129 const RtpCastHeader& rtp_header) { 143 const RtpCastHeader& rtp_header) {
130 // TODO(pwestin): update this as video to refresh over time. 144 // TODO(pwestin): update this as video to refresh over time.
131 if (time_first_incoming_packet_.is_null()) { 145 if (time_first_incoming_packet_.is_null()) {
132 first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp; 146 first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp;
133 time_first_incoming_packet_ = cast_environment_->Clock()->NowTicks(); 147 time_first_incoming_packet_ = cast_environment_->Clock()->NowTicks();
134 } 148 }
135 149
136 if (audio_decoder_) { 150 if (audio_decoder_) {
137 DCHECK(!audio_buffer_) << "Invalid internal state"; 151 DCHECK(!audio_buffer_) << "Invalid internal state";
138 audio_decoder_->IncomingParsedRtpPacket(payload_data, payload_size, 152 std::string plaintext(reinterpret_cast<const char*>(payload_data),
139 rtp_header); 153 payload_size);
wtc 2013/11/15 20:13:37 The changes you made to these audio_xxx files shou
pwestin 2013/11/15 22:11:10 Done.
154 if (decryptor_) {
155 plaintext.clear();
156 if (!decryptor_->SetCounter(GetAesNonce(rtp_header.frame_id, iv_mask_))) {
157 NOTREACHED();
wtc 2013/11/15 20:13:37 Should we add a return statement?
pwestin 2013/11/15 22:11:10 Done.
158 }
159 if (!decryptor_->Decrypt(base::StringPiece(reinterpret_cast<const char*>(
160 payload_data), payload_size), &plaintext)) {
161 VLOG(0) << "Decryption error";
162 return;
163 }
164 }
165 audio_decoder_->IncomingParsedRtpPacket(
166 reinterpret_cast<const uint8*>(plaintext.data()), plaintext.size(),
167 rtp_header);
140 return; 168 return;
141 } 169 }
142 DCHECK(audio_buffer_) << "Invalid internal state"; 170 DCHECK(audio_buffer_) << "Invalid internal state";
143 DCHECK(!audio_decoder_) << "Invalid internal state"; 171 DCHECK(!audio_decoder_) << "Invalid internal state";
144 bool complete = audio_buffer_->InsertPacket(payload_data, payload_size, 172 bool complete = audio_buffer_->InsertPacket(payload_data, payload_size,
145 rtp_header); 173 rtp_header);
146 if (!complete) return; // Audio frame not complete; wait for more packets. 174 if (!complete) return; // Audio frame not complete; wait for more packets.
147 if (queued_encoded_callbacks_.empty()) return; // No pending callback. 175 if (queued_encoded_callbacks_.empty()) return; // No pending callback.
148 176
149 AudioFrameEncodedCallback callback = queued_encoded_callbacks_.front(); 177 AudioFrameEncodedCallback callback = queued_encoded_callbacks_.front();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 230
203 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), 231 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(),
204 &rtp_timestamp, &next_frame)) { 232 &rtp_timestamp, &next_frame)) {
205 // We have no audio frames. Wait for new packet(s). 233 // We have no audio frames. Wait for new packet(s).
206 // Since the application can post multiple AudioFrameEncodedCallback and 234 // Since the application can post multiple AudioFrameEncodedCallback and
207 // we only check the next frame to play out we might have multiple timeout 235 // we only check the next frame to play out we might have multiple timeout
208 // events firing after each other; however this should be a rare event. 236 // events firing after each other; however this should be a rare event.
209 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; 237 VLOG(1) << "Failed to retrieved a complete frame at this point in time";
210 return; 238 return;
211 } 239 }
240
241 if (decryptor_) {
242 if (!DecryptAudioFrame(&encoded_frame)) {
243 VLOG(0) << "Decryption error";
244 return;
245 }
246 }
247
212 if (PostEncodedAudioFrame(queued_encoded_callbacks_.front(), rtp_timestamp, 248 if (PostEncodedAudioFrame(queued_encoded_callbacks_.front(), rtp_timestamp,
213 next_frame, &encoded_frame)) { 249 next_frame, &encoded_frame)) {
214 // Call succeed remove callback from list. 250 // Call succeed remove callback from list.
215 queued_encoded_callbacks_.pop_front(); 251 queued_encoded_callbacks_.pop_front();
216 } 252 }
217 } 253 }
218 254
219 void AudioReceiver::GetEncodedAudioFrame( 255 void AudioReceiver::GetEncodedAudioFrame(
220 const AudioFrameEncodedCallback& callback) { 256 const AudioFrameEncodedCallback& callback) {
221 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; 257 DCHECK(audio_buffer_) << "Invalid function call in this configuration";
222 258
223 uint32 rtp_timestamp = 0; 259 uint32 rtp_timestamp = 0;
224 bool next_frame = false; 260 bool next_frame = false;
225 scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame()); 261 scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame());
226 262
227 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), 263 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(),
228 &rtp_timestamp, &next_frame)) { 264 &rtp_timestamp, &next_frame)) {
229 // We have no audio frames. Wait for new packet(s). 265 // We have no audio frames. Wait for new packet(s).
230 VLOG(1) << "Wait for more audio packets in frame"; 266 VLOG(1) << "Wait for more audio packets in frame";
231 queued_encoded_callbacks_.push_back(callback); 267 queued_encoded_callbacks_.push_back(callback);
232 return; 268 return;
233 } 269 }
270 if (decryptor_) {
271 if (!DecryptAudioFrame(&encoded_frame)) {
272 VLOG(0) << "Decryption error";
273 queued_encoded_callbacks_.push_back(callback);
274 return;
275 }
276 }
234 if (!PostEncodedAudioFrame(callback, rtp_timestamp, next_frame, 277 if (!PostEncodedAudioFrame(callback, rtp_timestamp, next_frame,
235 &encoded_frame)) { 278 &encoded_frame)) {
236 // We have an audio frame; however we are missing packets and we have time 279 // We have an audio frame; however we are missing packets and we have time
237 // to wait for new packet(s). 280 // to wait for new packet(s).
238 queued_encoded_callbacks_.push_back(callback); 281 queued_encoded_callbacks_.push_back(callback);
239 } 282 }
240 } 283 }
241 284
242 bool AudioReceiver::PostEncodedAudioFrame( 285 bool AudioReceiver::PostEncodedAudioFrame(
243 const AudioFrameEncodedCallback& callback, 286 const AudioFrameEncodedCallback& callback,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 base::TimeDelta()); 350 base::TimeDelta());
308 } 351 }
309 } 352 }
310 // This can fail if we have not received any RTCP packets in a long time. 353 // This can fail if we have not received any RTCP packets in a long time.
311 return rtcp_->RtpTimestampInSenderTime(frequency_, rtp_timestamp, 354 return rtcp_->RtpTimestampInSenderTime(frequency_, rtp_timestamp,
312 &rtp_timestamp_in_ticks) ? 355 &rtp_timestamp_in_ticks) ?
313 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_ : 356 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_ :
314 now; 357 now;
315 } 358 }
316 359
360 bool AudioReceiver::DecryptAudioFrame(
361 scoped_ptr<EncodedAudioFrame>* audio_frame) {
362 DCHECK(decryptor_) << "Invalid state";
363
364 if (!decryptor_->SetCounter(GetAesNonce((*audio_frame)->frame_id,
365 iv_mask_))) {
366 NOTREACHED();
367 return false;
368 }
369 std::string decrypted_audio_data;
370 if (!decryptor_->Decrypt((*audio_frame)->data, &decrypted_audio_data)) {
371 return false;
372 }
373 (*audio_frame)->data.swap(decrypted_audio_data);
374 return true;
375 }
376
317 void AudioReceiver::ScheduleNextRtcpReport() { 377 void AudioReceiver::ScheduleNextRtcpReport() {
318 base::TimeDelta time_to_send = rtcp_->TimeToSendNextRtcpReport() - 378 base::TimeDelta time_to_send = rtcp_->TimeToSendNextRtcpReport() -
319 cast_environment_->Clock()->NowTicks(); 379 cast_environment_->Clock()->NowTicks();
320 380
321 time_to_send = std::max(time_to_send, 381 time_to_send = std::max(time_to_send,
322 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 382 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
323 383
324 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, 384 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE,
325 base::Bind(&AudioReceiver::SendNextRtcpReport, 385 base::Bind(&AudioReceiver::SendNextRtcpReport,
326 weak_factory_.GetWeakPtr()), time_to_send); 386 weak_factory_.GetWeakPtr()), time_to_send);
(...skipping 22 matching lines...) Expand all
349 } 409 }
350 410
351 void AudioReceiver::SendNextCastMessage() { 411 void AudioReceiver::SendNextCastMessage() {
352 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; 412 DCHECK(audio_buffer_) << "Invalid function call in this configuration";
353 audio_buffer_->SendCastMessage(); // Will only send a message if it is time. 413 audio_buffer_->SendCastMessage(); // Will only send a message if it is time.
354 ScheduleNextCastMessage(); 414 ScheduleNextCastMessage();
355 } 415 }
356 416
357 } // namespace cast 417 } // namespace cast
358 } // namespace media 418 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698