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/video_receiver/video_receiver.h" | 5 #include "media/cast/video_receiver/video_receiver.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | |
8 #include "base/bind.h" | 9 #include "base/bind.h" |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "crypto/symmetric_key.h" | |
11 #include "media/cast/cast_defines.h" | 13 #include "media/cast/cast_defines.h" |
12 #include "media/cast/framer/framer.h" | 14 #include "media/cast/framer/framer.h" |
13 #include "media/cast/video_receiver/video_decoder.h" | 15 #include "media/cast/video_receiver/video_decoder.h" |
14 | 16 |
15 namespace media { | 17 namespace media { |
16 namespace cast { | 18 namespace cast { |
17 | 19 |
18 const int64 kMinSchedulingDelayMs = 1; | 20 const int64 kMinSchedulingDelayMs = 1; |
19 | 21 |
20 static const int64 kMinTimeBetweenOffsetUpdatesMs = 2000; | 22 static const int64 kMinTimeBetweenOffsetUpdatesMs = 2000; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
118 incoming_payload_feedback_(new LocalRtpVideoFeedback(this)), | 120 incoming_payload_feedback_(new LocalRtpVideoFeedback(this)), |
119 rtp_receiver_(cast_environment_->Clock(), NULL, &video_config, | 121 rtp_receiver_(cast_environment_->Clock(), NULL, &video_config, |
120 incoming_payload_callback_.get()), | 122 incoming_payload_callback_.get()), |
121 rtp_video_receiver_statistics_( | 123 rtp_video_receiver_statistics_( |
122 new LocalRtpReceiverStatistics(&rtp_receiver_)), | 124 new LocalRtpReceiverStatistics(&rtp_receiver_)), |
123 weak_factory_(this) { | 125 weak_factory_(this) { |
124 int max_unacked_frames = video_config.rtp_max_delay_ms * | 126 int max_unacked_frames = video_config.rtp_max_delay_ms * |
125 video_config.max_frame_rate / 1000; | 127 video_config.max_frame_rate / 1000; |
126 DCHECK(max_unacked_frames) << "Invalid argument"; | 128 DCHECK(max_unacked_frames) << "Invalid argument"; |
127 | 129 |
130 if (video_config.aes_iv_mask.size() == kAesBlockSize * 2 && | |
131 video_config.aes_key.size() == kAesBlockSize * 2) { | |
132 iv_mask_ = ConvertFromBase16String(video_config.aes_iv_mask); | |
133 crypto::SymmetricKey* key = crypto::SymmetricKey::Import( | |
134 crypto::SymmetricKey::AES, | |
135 ConvertFromBase16String(video_config.aes_key)); | |
Alpha Left Google
2013/11/07 01:10:11
Again don't do the conversion in this low level st
pwestin
2013/11/07 17:16:04
Done.
| |
136 encryptor_.reset(new crypto::Encryptor()); | |
137 encryptor_->Init(key, crypto::Encryptor::CTR, std::string()); | |
138 } else if (video_config.aes_iv_mask.size() != 0 || | |
139 video_config.aes_iv_mask.size() != 0) { | |
140 DCHECK(false) << "Invalid crypto configuration"; | |
141 } | |
142 | |
128 framer_.reset(new Framer(cast_environment->Clock(), | 143 framer_.reset(new Framer(cast_environment->Clock(), |
129 incoming_payload_feedback_.get(), | 144 incoming_payload_feedback_.get(), |
130 video_config.incoming_ssrc, | 145 video_config.incoming_ssrc, |
131 video_config.decoder_faster_than_max_frame_rate, | 146 video_config.decoder_faster_than_max_frame_rate, |
132 max_unacked_frames)); | 147 max_unacked_frames)); |
133 if (!video_config.use_external_decoder) { | 148 if (!video_config.use_external_decoder) { |
134 video_decoder_.reset(new VideoDecoder(video_config)); | 149 video_decoder_.reset(new VideoDecoder(video_config)); |
135 } | 150 } |
136 | 151 |
137 rtcp_.reset( | 152 rtcp_.reset( |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 base::Bind(frame_decoded_callback, | 208 base::Bind(frame_decoded_callback, |
194 base::Passed(&video_frame), render_time)); | 209 base::Passed(&video_frame), render_time)); |
195 } else { | 210 } else { |
196 // This will happen if we decide to decode but not show a frame. | 211 // This will happen if we decide to decode but not show a frame. |
197 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 212 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
198 base::Bind(&VideoReceiver::GetRawVideoFrame, | 213 base::Bind(&VideoReceiver::GetRawVideoFrame, |
199 weak_factory_.GetWeakPtr(), frame_decoded_callback)); | 214 weak_factory_.GetWeakPtr(), frame_decoded_callback)); |
200 } | 215 } |
201 } | 216 } |
202 | 217 |
218 bool VideoReceiver::DecryptVideoFrame( | |
219 const EncodedVideoFrame* encrypted_frame, | |
220 EncodedVideoFrame* video_frame) { | |
221 DCHECK(encryptor_) << "Invalid state"; | |
222 | |
223 // TODO(pwestin): the frame id must be a 32 bit number. | |
224 encryptor_->SetCounter(GetAesNounce(encrypted_frame->frame_id, iv_mask_)); | |
225 | |
226 video_frame->codec = encrypted_frame->codec; | |
227 video_frame->key_frame = encrypted_frame->key_frame; | |
228 video_frame->frame_id = encrypted_frame->frame_id; | |
229 video_frame->last_referenced_frame_id = | |
230 encrypted_frame->last_referenced_frame_id; | |
231 | |
232 return encryptor_->Decrypt(encrypted_frame->data, &video_frame->data); | |
233 } | |
234 | |
203 // Called from the main cast thread. | 235 // Called from the main cast thread. |
204 void VideoReceiver::GetEncodedVideoFrame( | 236 void VideoReceiver::GetEncodedVideoFrame( |
205 const VideoFrameEncodedCallback& callback) { | 237 const VideoFrameEncodedCallback& callback) { |
206 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); | 238 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); |
207 uint32 rtp_timestamp = 0; | 239 uint32 rtp_timestamp = 0; |
208 bool next_frame = false; | 240 bool next_frame = false; |
209 | 241 |
210 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, | 242 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, |
211 &next_frame)) { | 243 &next_frame)) { |
212 // We have no video frames. Wait for new packet(s). | 244 // We have no video frames. Wait for new packet(s). |
213 queued_encoded_callbacks_.push_back(callback); | 245 queued_encoded_callbacks_.push_back(callback); |
214 return; | 246 return; |
215 } | 247 } |
248 | |
249 if (encryptor_) { | |
250 EncodedVideoFrame* decrypted_video_frame = new EncodedVideoFrame(); | |
Alpha Left Google
2013/11/07 01:10:11
This should be a scoped_ptr<T>.
pwestin
2013/11/07 17:16:04
Done.
| |
251 | |
252 if (DecryptVideoFrame(encoded_frame.get(), decrypted_video_frame)) { | |
253 encoded_frame.reset(decrypted_video_frame); | |
254 } else { | |
255 DCHECK(false) << "Decryption error"; | |
256 return; | |
257 } | |
258 } | |
259 | |
216 base::TimeTicks render_time; | 260 base::TimeTicks render_time; |
217 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, | 261 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, |
218 &render_time)) { | 262 &render_time)) { |
219 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 263 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
220 base::Bind(callback, base::Passed(&encoded_frame), render_time)); | 264 base::Bind(callback, base::Passed(&encoded_frame), render_time)); |
221 } else { | 265 } else { |
222 // We have a video frame; however we are missing packets and we have time | 266 // We have a video frame; however we are missing packets and we have time |
223 // to wait for new packet(s). | 267 // to wait for new packet(s). |
224 queued_encoded_callbacks_.push_back(callback); | 268 queued_encoded_callbacks_.push_back(callback); |
225 } | 269 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 // We have no video frames. Wait for new packet(s). | 330 // We have no video frames. Wait for new packet(s). |
287 // Since the application can post multiple VideoFrameEncodedCallback and | 331 // Since the application can post multiple VideoFrameEncodedCallback and |
288 // we only check the next frame to play out we might have multiple timeout | 332 // we only check the next frame to play out we might have multiple timeout |
289 // events firing after each other; however this should be a rare event. | 333 // events firing after each other; however this should be a rare event. |
290 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; | 334 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; |
291 return; | 335 return; |
292 } | 336 } |
293 VLOG(1) << "PlayoutTimeout retrieved frame " | 337 VLOG(1) << "PlayoutTimeout retrieved frame " |
294 << static_cast<int>(encoded_frame->frame_id); | 338 << static_cast<int>(encoded_frame->frame_id); |
295 | 339 |
340 if (encryptor_) { | |
341 EncodedVideoFrame* decrypted_video_frame = new EncodedVideoFrame(); | |
Alpha Left Google
2013/11/07 01:10:11
Same here, use scoped_ptr<T>.
pwestin
2013/11/07 17:16:04
Done.
| |
342 | |
343 if (DecryptVideoFrame(encoded_frame.get(), decrypted_video_frame)) { | |
344 encoded_frame.reset(decrypted_video_frame); | |
345 } else { | |
346 DCHECK(false) << "Decryption error"; | |
347 delete decrypted_video_frame; | |
348 return; | |
349 } | |
350 } | |
351 | |
296 base::TimeTicks render_time; | 352 base::TimeTicks render_time; |
297 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, | 353 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, |
298 &render_time)) { | 354 &render_time)) { |
299 if (!queued_encoded_callbacks_.empty()) { | 355 if (!queued_encoded_callbacks_.empty()) { |
300 VideoFrameEncodedCallback callback = queued_encoded_callbacks_.front(); | 356 VideoFrameEncodedCallback callback = queued_encoded_callbacks_.front(); |
301 queued_encoded_callbacks_.pop_front(); | 357 queued_encoded_callbacks_.pop_front(); |
302 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 358 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
303 base::Bind(callback, base::Passed(&encoded_frame), render_time)); | 359 base::Bind(callback, base::Passed(&encoded_frame), render_time)); |
304 } | 360 } |
305 } else { | 361 } else { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
419 weak_factory_.GetWeakPtr()), time_to_next); | 475 weak_factory_.GetWeakPtr()), time_to_next); |
420 } | 476 } |
421 | 477 |
422 void VideoReceiver::SendNextRtcpReport() { | 478 void VideoReceiver::SendNextRtcpReport() { |
423 rtcp_->SendRtcpReport(incoming_ssrc_); | 479 rtcp_->SendRtcpReport(incoming_ssrc_); |
424 ScheduleNextRtcpReport(); | 480 ScheduleNextRtcpReport(); |
425 } | 481 } |
426 | 482 |
427 } // namespace cast | 483 } // namespace cast |
428 } // namespace media | 484 } // namespace media |
OLD | NEW |