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() == kAesKeySize && |
| 131 video_config.aes_key.size() == kAesKeySize) { |
| 132 iv_mask_ = video_config.aes_iv_mask; |
| 133 crypto::SymmetricKey* key = crypto::SymmetricKey::Import( |
| 134 crypto::SymmetricKey::AES, video_config.aes_key); |
| 135 decryptor_.reset(new crypto::Encryptor()); |
| 136 decryptor_->Init(key, crypto::Encryptor::CTR, std::string()); |
| 137 } else if (video_config.aes_iv_mask.size() != 0 || |
| 138 video_config.aes_key.size() != 0) { |
| 139 DCHECK(false) << "Invalid crypto configuration"; |
| 140 } |
| 141 |
128 framer_.reset(new Framer(cast_environment->Clock(), | 142 framer_.reset(new Framer(cast_environment->Clock(), |
129 incoming_payload_feedback_.get(), | 143 incoming_payload_feedback_.get(), |
130 video_config.incoming_ssrc, | 144 video_config.incoming_ssrc, |
131 video_config.decoder_faster_than_max_frame_rate, | 145 video_config.decoder_faster_than_max_frame_rate, |
132 max_unacked_frames)); | 146 max_unacked_frames)); |
133 if (!video_config.use_external_decoder) { | 147 if (!video_config.use_external_decoder) { |
134 video_decoder_.reset(new VideoDecoder(video_config)); | 148 video_decoder_.reset(new VideoDecoder(video_config)); |
135 } | 149 } |
136 | 150 |
137 rtcp_.reset( | 151 rtcp_.reset( |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 base::Bind(frame_decoded_callback, | 207 base::Bind(frame_decoded_callback, |
194 base::Passed(&video_frame), render_time)); | 208 base::Passed(&video_frame), render_time)); |
195 } else { | 209 } else { |
196 // This will happen if we decide to decode but not show a frame. | 210 // This will happen if we decide to decode but not show a frame. |
197 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 211 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
198 base::Bind(&VideoReceiver::GetRawVideoFrame, | 212 base::Bind(&VideoReceiver::GetRawVideoFrame, |
199 weak_factory_.GetWeakPtr(), frame_decoded_callback)); | 213 weak_factory_.GetWeakPtr(), frame_decoded_callback)); |
200 } | 214 } |
201 } | 215 } |
202 | 216 |
| 217 bool VideoReceiver::DecryptVideoFrame( |
| 218 scoped_ptr<EncodedVideoFrame>* video_frame) { |
| 219 DCHECK(decryptor_) << "Invalid state"; |
| 220 |
| 221 scoped_ptr<EncodedVideoFrame> decrypted_video_frame( |
| 222 new EncodedVideoFrame()); |
| 223 |
| 224 // TODO(pwestin): the frame id must be a 32 bit number. |
| 225 decryptor_->SetCounter(GetAesNounce((*video_frame)->frame_id, iv_mask_)); |
| 226 |
| 227 if (!decryptor_->Decrypt((*video_frame)->data, |
| 228 &decrypted_video_frame->data)) { |
| 229 return false; |
| 230 } |
| 231 decrypted_video_frame->codec = (*video_frame)->codec; |
| 232 decrypted_video_frame->key_frame = (*video_frame)->key_frame; |
| 233 decrypted_video_frame->frame_id = (*video_frame)->frame_id; |
| 234 decrypted_video_frame->last_referenced_frame_id = |
| 235 (*video_frame)->last_referenced_frame_id; |
| 236 |
| 237 video_frame->swap(decrypted_video_frame); |
| 238 return true; |
| 239 } |
| 240 |
203 // Called from the main cast thread. | 241 // Called from the main cast thread. |
204 void VideoReceiver::GetEncodedVideoFrame( | 242 void VideoReceiver::GetEncodedVideoFrame( |
205 const VideoFrameEncodedCallback& callback) { | 243 const VideoFrameEncodedCallback& callback) { |
206 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); | 244 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); |
207 uint32 rtp_timestamp = 0; | 245 uint32 rtp_timestamp = 0; |
208 bool next_frame = false; | 246 bool next_frame = false; |
209 | 247 |
210 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, | 248 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, |
211 &next_frame)) { | 249 &next_frame)) { |
212 // We have no video frames. Wait for new packet(s). | 250 // We have no video frames. Wait for new packet(s). |
213 queued_encoded_callbacks_.push_back(callback); | 251 queued_encoded_callbacks_.push_back(callback); |
214 return; | 252 return; |
215 } | 253 } |
| 254 |
| 255 if (decryptor_) { |
| 256 if (!DecryptVideoFrame(&encoded_frame)) { |
| 257 DCHECK(false) << "Decryption error"; |
| 258 return; |
| 259 } |
| 260 } |
| 261 |
216 base::TimeTicks render_time; | 262 base::TimeTicks render_time; |
217 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, | 263 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, |
218 &render_time)) { | 264 &render_time)) { |
219 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 265 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
220 base::Bind(callback, base::Passed(&encoded_frame), render_time)); | 266 base::Bind(callback, base::Passed(&encoded_frame), render_time)); |
221 } else { | 267 } else { |
222 // We have a video frame; however we are missing packets and we have time | 268 // We have a video frame; however we are missing packets and we have time |
223 // to wait for new packet(s). | 269 // to wait for new packet(s). |
224 queued_encoded_callbacks_.push_back(callback); | 270 queued_encoded_callbacks_.push_back(callback); |
225 } | 271 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 // We have no video frames. Wait for new packet(s). | 332 // We have no video frames. Wait for new packet(s). |
287 // Since the application can post multiple VideoFrameEncodedCallback and | 333 // Since the application can post multiple VideoFrameEncodedCallback and |
288 // we only check the next frame to play out we might have multiple timeout | 334 // 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. | 335 // 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"; | 336 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; |
291 return; | 337 return; |
292 } | 338 } |
293 VLOG(1) << "PlayoutTimeout retrieved frame " | 339 VLOG(1) << "PlayoutTimeout retrieved frame " |
294 << static_cast<int>(encoded_frame->frame_id); | 340 << static_cast<int>(encoded_frame->frame_id); |
295 | 341 |
| 342 if (decryptor_) { |
| 343 if (!DecryptVideoFrame(&encoded_frame)) { |
| 344 DCHECK(false) << "Decryption error"; |
| 345 return; |
| 346 } |
| 347 } |
| 348 |
296 base::TimeTicks render_time; | 349 base::TimeTicks render_time; |
297 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, | 350 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, |
298 &render_time)) { | 351 &render_time)) { |
299 if (!queued_encoded_callbacks_.empty()) { | 352 if (!queued_encoded_callbacks_.empty()) { |
300 VideoFrameEncodedCallback callback = queued_encoded_callbacks_.front(); | 353 VideoFrameEncodedCallback callback = queued_encoded_callbacks_.front(); |
301 queued_encoded_callbacks_.pop_front(); | 354 queued_encoded_callbacks_.pop_front(); |
302 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 355 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
303 base::Bind(callback, base::Passed(&encoded_frame), render_time)); | 356 base::Bind(callback, base::Passed(&encoded_frame), render_time)); |
304 } | 357 } |
305 } else { | 358 } else { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 weak_factory_.GetWeakPtr()), time_to_next); | 472 weak_factory_.GetWeakPtr()), time_to_next); |
420 } | 473 } |
421 | 474 |
422 void VideoReceiver::SendNextRtcpReport() { | 475 void VideoReceiver::SendNextRtcpReport() { |
423 rtcp_->SendRtcpReport(incoming_ssrc_); | 476 rtcp_->SendRtcpReport(incoming_ssrc_); |
424 ScheduleNextRtcpReport(); | 477 ScheduleNextRtcpReport(); |
425 } | 478 } |
426 | 479 |
427 } // namespace cast | 480 } // namespace cast |
428 } // namespace media | 481 } // namespace media |
OLD | NEW |