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

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: Fixed nits 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/symmetric_key.h"
10 #include "media/cast/audio_receiver/audio_decoder.h" 11 #include "media/cast/audio_receiver/audio_decoder.h"
11 #include "media/cast/framer/framer.h" 12 #include "media/cast/framer/framer.h"
12 #include "media/cast/rtcp/rtcp.h" 13 #include "media/cast/rtcp/rtcp.h"
13 #include "media/cast/rtp_receiver/rtp_receiver.h" 14 #include "media/cast/rtp_receiver/rtp_receiver.h"
14 15
15 // Max time we wait until an audio frame is due to be played out is released. 16 // Max time we wait until an audio frame is due to be played out is released.
16 static const int64 kMaxAudioFrameWaitMs = 20; 17 static const int64 kMaxAudioFrameWaitMs = 20;
17 static const int64 kMinSchedulingDelayMs = 1; 18 static const int64 kMinSchedulingDelayMs = 1;
18 19
19 namespace media { 20 namespace media {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this)); 93 incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this));
93 if (audio_config.use_external_decoder) { 94 if (audio_config.use_external_decoder) {
94 audio_buffer_.reset(new Framer(cast_environment->Clock(), 95 audio_buffer_.reset(new Framer(cast_environment->Clock(),
95 incoming_payload_feedback_.get(), 96 incoming_payload_feedback_.get(),
96 audio_config.incoming_ssrc, 97 audio_config.incoming_ssrc,
97 true, 98 true,
98 0)); 99 0));
99 } else { 100 } else {
100 audio_decoder_ = new AudioDecoder(audio_config); 101 audio_decoder_ = new AudioDecoder(audio_config);
101 } 102 }
103 if (audio_config.aes_iv_mask.size() == kAesBlockSize * 2 &&
104 audio_config.aes_key.size() == kAesBlockSize * 2) {
wtc 2013/11/07 01:00:36 Block size and key size are different quantities,
pwestin 2013/11/07 17:16:04 Done.
105 iv_mask_ = ConvertFromBase16String(audio_config.aes_iv_mask);
106 crypto::SymmetricKey* key = crypto::SymmetricKey::Import(
107 crypto::SymmetricKey::AES,
108 ConvertFromBase16String(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_iv_mask.size() != 0) {
wtc 2013/11/07 01:00:36 BUG: the second one should test audio_config.aes_k
pwestin 2013/11/07 17:16:04 Done.
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 if (decryptor_) {
139 rtp_header); 153 // TODO(pwestin): we need to change to 32 bits frame id.
154 decryptor_->SetCounter(GetAesNounce(rtp_header.frame_id, iv_mask_));
155 std::string plaintext;
156 if (decryptor_->Decrypt(
157 base::StringPiece(reinterpret_cast<const char*>(payload_data),
Alpha Left Google 2013/11/07 01:10:11 nit: indent 4 spaces.
pwestin 2013/11/07 17:16:04 Done.
158 payload_size),
159 &plaintext)) {
Alpha Left Google 2013/11/07 01:10:11 nit: indent 4 spaces as well.
pwestin 2013/11/07 17:16:04 Done.
160 audio_decoder_->IncomingParsedRtpPacket(
161 reinterpret_cast<const uint8*>(plaintext.data()), plaintext.size(),
162 rtp_header);
163 } else {
164 DCHECK(false) << "Decryption error";
165 return;
166 }
167 } else {
168 audio_decoder_->IncomingParsedRtpPacket(payload_data, payload_size,
169 rtp_header);
170 }
140 return; 171 return;
141 } 172 }
142 DCHECK(audio_buffer_) << "Invalid internal state"; 173 DCHECK(audio_buffer_) << "Invalid internal state";
143 DCHECK(!audio_decoder_) << "Invalid internal state"; 174 DCHECK(!audio_decoder_) << "Invalid internal state";
144 bool complete = audio_buffer_->InsertPacket(payload_data, payload_size, 175 bool complete = audio_buffer_->InsertPacket(payload_data, payload_size,
145 rtp_header); 176 rtp_header);
146 if (!complete) return; // Audio frame not complete; wait for more packets. 177 if (!complete) return; // Audio frame not complete; wait for more packets.
147 if (queued_encoded_callbacks_.empty()) return; // No pending callback. 178 if (queued_encoded_callbacks_.empty()) return; // No pending callback.
148 179
149 AudioFrameEncodedCallback callback = queued_encoded_callbacks_.front(); 180 AudioFrameEncodedCallback callback = queued_encoded_callbacks_.front();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 233
203 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), 234 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(),
204 &rtp_timestamp, &next_frame)) { 235 &rtp_timestamp, &next_frame)) {
205 // We have no audio frames. Wait for new packet(s). 236 // We have no audio frames. Wait for new packet(s).
206 // Since the application can post multiple AudioFrameEncodedCallback and 237 // Since the application can post multiple AudioFrameEncodedCallback and
207 // we only check the next frame to play out we might have multiple timeout 238 // 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. 239 // 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"; 240 VLOG(1) << "Failed to retrieved a complete frame at this point in time";
210 return; 241 return;
211 } 242 }
243
244 if (decryptor_) {
245 EncodedAudioFrame* decrypted_audio_frame = new EncodedAudioFrame();
Alpha Left Google 2013/11/07 01:10:11 We should use a scoped_ptr<T> here.
pwestin 2013/11/07 17:16:04 Done.
246 if (DecryptAudioFrame(encoded_frame.get(), decrypted_audio_frame)) {
247 encoded_frame.reset(decrypted_audio_frame);
248 } else {
249 DCHECK(false) << "Decryption error";
250 delete decrypted_audio_frame;
251 return;
252 }
253 }
254
212 if (PostEncodedAudioFrame(queued_encoded_callbacks_.front(), rtp_timestamp, 255 if (PostEncodedAudioFrame(queued_encoded_callbacks_.front(), rtp_timestamp,
213 next_frame, &encoded_frame)) { 256 next_frame, &encoded_frame)) {
214 // Call succeed remove callback from list. 257 // Call succeed remove callback from list.
215 queued_encoded_callbacks_.pop_front(); 258 queued_encoded_callbacks_.pop_front();
216 } 259 }
217 } 260 }
218 261
219 void AudioReceiver::GetEncodedAudioFrame( 262 void AudioReceiver::GetEncodedAudioFrame(
220 const AudioFrameEncodedCallback& callback) { 263 const AudioFrameEncodedCallback& callback) {
221 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; 264 DCHECK(audio_buffer_) << "Invalid function call in this configuration";
222 265
223 uint32 rtp_timestamp = 0; 266 uint32 rtp_timestamp = 0;
224 bool next_frame = false; 267 bool next_frame = false;
225 scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame()); 268 scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame());
226 269
227 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), 270 if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(),
228 &rtp_timestamp, &next_frame)) { 271 &rtp_timestamp, &next_frame)) {
229 // We have no audio frames. Wait for new packet(s). 272 // We have no audio frames. Wait for new packet(s).
230 VLOG(1) << "Wait for more audio packets in frame"; 273 VLOG(1) << "Wait for more audio packets in frame";
231 queued_encoded_callbacks_.push_back(callback); 274 queued_encoded_callbacks_.push_back(callback);
232 return; 275 return;
233 } 276 }
277 if (decryptor_) {
278 EncodedAudioFrame* decrypted_audio_frame = new EncodedAudioFrame();
Alpha Left Google 2013/11/07 01:10:11 Use scoped_ptr<T>.
pwestin 2013/11/07 17:16:04 Done.
279 if (DecryptAudioFrame(encoded_frame.get(), decrypted_audio_frame)) {
280 encoded_frame.reset(decrypted_audio_frame);
281 } else {
282 DCHECK(false) << "Decryption error";
283 delete decrypted_audio_frame;
284 return;
285 }
286 }
234 if (!PostEncodedAudioFrame(callback, rtp_timestamp, next_frame, 287 if (!PostEncodedAudioFrame(callback, rtp_timestamp, next_frame,
235 &encoded_frame)) { 288 &encoded_frame)) {
236 // We have an audio frame; however we are missing packets and we have time 289 // We have an audio frame; however we are missing packets and we have time
237 // to wait for new packet(s). 290 // to wait for new packet(s).
238 queued_encoded_callbacks_.push_back(callback); 291 queued_encoded_callbacks_.push_back(callback);
239 } 292 }
240 } 293 }
241 294
242 bool AudioReceiver::PostEncodedAudioFrame( 295 bool AudioReceiver::PostEncodedAudioFrame(
243 const AudioFrameEncodedCallback& callback, 296 const AudioFrameEncodedCallback& callback,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 base::TimeDelta()); 360 base::TimeDelta());
308 } 361 }
309 } 362 }
310 // This can fail if we have not received any RTCP packets in a long time. 363 // This can fail if we have not received any RTCP packets in a long time.
311 return rtcp_->RtpTimestampInSenderTime(frequency_, rtp_timestamp, 364 return rtcp_->RtpTimestampInSenderTime(frequency_, rtp_timestamp,
312 &rtp_timestamp_in_ticks) ? 365 &rtp_timestamp_in_ticks) ?
313 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_ : 366 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_ :
314 now; 367 now;
315 } 368 }
316 369
370 bool AudioReceiver::DecryptAudioFrame(const EncodedAudioFrame* encrypted_frame,
371 EncodedAudioFrame* audio_frame) {
372 DCHECK(decryptor_) << "Invalid state";
373
374 DCHECK(false);
Alpha Left Google 2013/11/07 01:10:11 Why?
pwestin 2013/11/07 17:16:04 No idea how that ended up there
375
376 // TODO(pwestin): the frame id must be a 32 bit number.
377 decryptor_->SetCounter(GetAesNounce(audio_frame->frame_id, iv_mask_));
378
379 audio_frame->codec = encrypted_frame->codec;
380 audio_frame->frame_id = encrypted_frame->frame_id;
381
382 return decryptor_->Decrypt(encrypted_frame->data, &audio_frame->data);
383 }
384
317 void AudioReceiver::ScheduleNextRtcpReport() { 385 void AudioReceiver::ScheduleNextRtcpReport() {
318 base::TimeDelta time_to_send = rtcp_->TimeToSendNextRtcpReport() - 386 base::TimeDelta time_to_send = rtcp_->TimeToSendNextRtcpReport() -
319 cast_environment_->Clock()->NowTicks(); 387 cast_environment_->Clock()->NowTicks();
320 388
321 time_to_send = std::max(time_to_send, 389 time_to_send = std::max(time_to_send,
322 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 390 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
323 391
324 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, 392 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE,
325 base::Bind(&AudioReceiver::SendNextRtcpReport, 393 base::Bind(&AudioReceiver::SendNextRtcpReport,
326 weak_factory_.GetWeakPtr()), time_to_send); 394 weak_factory_.GetWeakPtr()), time_to_send);
(...skipping 22 matching lines...) Expand all
349 } 417 }
350 418
351 void AudioReceiver::SendNextCastMessage() { 419 void AudioReceiver::SendNextCastMessage() {
352 DCHECK(audio_buffer_) << "Invalid function call in this configuration"; 420 DCHECK(audio_buffer_) << "Invalid function call in this configuration";
353 audio_buffer_->SendCastMessage(); // Will only send a message if it is time. 421 audio_buffer_->SendCastMessage(); // Will only send a message if it is time.
354 ScheduleNextCastMessage(); 422 ScheduleNextCastMessage();
355 } 423 }
356 424
357 } // namespace cast 425 } // namespace cast
358 } // namespace media 426 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698