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/encryptor.h" |
| 13 #include "crypto/symmetric_key.h" |
11 #include "media/cast/cast_defines.h" | 14 #include "media/cast/cast_defines.h" |
12 #include "media/cast/framer/framer.h" | 15 #include "media/cast/framer/framer.h" |
13 #include "media/cast/video_receiver/video_decoder.h" | 16 #include "media/cast/video_receiver/video_decoder.h" |
14 | 17 |
15 namespace media { | 18 namespace media { |
16 namespace cast { | 19 namespace cast { |
17 | 20 |
18 const int64 kMinSchedulingDelayMs = 1; | 21 const int64 kMinSchedulingDelayMs = 1; |
19 | 22 |
20 static const int64 kMinTimeBetweenOffsetUpdatesMs = 2000; | 23 static const int64 kMinTimeBetweenOffsetUpdatesMs = 2000; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 incoming_payload_callback_.get()), | 98 incoming_payload_callback_.get()), |
96 rtp_video_receiver_statistics_( | 99 rtp_video_receiver_statistics_( |
97 new LocalRtpReceiverStatistics(&rtp_receiver_)), | 100 new LocalRtpReceiverStatistics(&rtp_receiver_)), |
98 time_incoming_packet_updated_(false), | 101 time_incoming_packet_updated_(false), |
99 incoming_rtp_timestamp_(0), | 102 incoming_rtp_timestamp_(0), |
100 weak_factory_(this) { | 103 weak_factory_(this) { |
101 int max_unacked_frames = video_config.rtp_max_delay_ms * | 104 int max_unacked_frames = video_config.rtp_max_delay_ms * |
102 video_config.max_frame_rate / 1000; | 105 video_config.max_frame_rate / 1000; |
103 DCHECK(max_unacked_frames) << "Invalid argument"; | 106 DCHECK(max_unacked_frames) << "Invalid argument"; |
104 | 107 |
| 108 if (video_config.aes_iv_mask.size() == kAesKeySize && |
| 109 video_config.aes_key.size() == kAesKeySize) { |
| 110 iv_mask_ = video_config.aes_iv_mask; |
| 111 crypto::SymmetricKey* key = crypto::SymmetricKey::Import( |
| 112 crypto::SymmetricKey::AES, video_config.aes_key); |
| 113 decryptor_.reset(new crypto::Encryptor()); |
| 114 decryptor_->Init(key, crypto::Encryptor::CTR, std::string()); |
| 115 } else if (video_config.aes_iv_mask.size() != 0 || |
| 116 video_config.aes_key.size() != 0) { |
| 117 DCHECK(false) << "Invalid crypto configuration"; |
| 118 } |
| 119 |
105 framer_.reset(new Framer(cast_environment->Clock(), | 120 framer_.reset(new Framer(cast_environment->Clock(), |
106 incoming_payload_feedback_.get(), | 121 incoming_payload_feedback_.get(), |
107 video_config.incoming_ssrc, | 122 video_config.incoming_ssrc, |
108 video_config.decoder_faster_than_max_frame_rate, | 123 video_config.decoder_faster_than_max_frame_rate, |
109 max_unacked_frames)); | 124 max_unacked_frames)); |
110 if (!video_config.use_external_decoder) { | 125 if (!video_config.use_external_decoder) { |
111 video_decoder_.reset(new VideoDecoder(video_config, cast_environment)); | 126 video_decoder_.reset(new VideoDecoder(video_config, cast_environment)); |
112 } | 127 } |
113 | 128 |
114 rtcp_.reset( | 129 rtcp_.reset( |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 | 178 |
164 if (!(video_decoder_->DecodeVideoFrame(encoded_frame.get(), render_time, | 179 if (!(video_decoder_->DecodeVideoFrame(encoded_frame.get(), render_time, |
165 frame_decoded_callback))) { | 180 frame_decoded_callback))) { |
166 // This will happen if we decide to decode but not show a frame. | 181 // This will happen if we decide to decode but not show a frame. |
167 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 182 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
168 base::Bind(&VideoReceiver::GetRawVideoFrame, | 183 base::Bind(&VideoReceiver::GetRawVideoFrame, |
169 weak_factory_.GetWeakPtr(), frame_decoded_callback)); | 184 weak_factory_.GetWeakPtr(), frame_decoded_callback)); |
170 } | 185 } |
171 } | 186 } |
172 | 187 |
| 188 bool VideoReceiver::DecryptVideoFrame( |
| 189 scoped_ptr<EncodedVideoFrame>* video_frame) { |
| 190 DCHECK(decryptor_) << "Invalid state"; |
| 191 |
| 192 if (!decryptor_->SetCounter(GetAesNonce((*video_frame)->frame_id, |
| 193 iv_mask_))) { |
| 194 NOTREACHED() << "Failed to set counter"; |
| 195 return false; |
| 196 } |
| 197 std::string decrypted_video_data; |
| 198 if (!decryptor_->Decrypt((*video_frame)->data, &decrypted_video_data)) { |
| 199 VLOG(0) << "Decryption error"; |
| 200 // Give up on this frame, release it from jitter buffer. |
| 201 framer_->ReleaseFrame((*video_frame)->frame_id); |
| 202 return false; |
| 203 } |
| 204 (*video_frame)->data.swap(decrypted_video_data); |
| 205 return true; |
| 206 } |
| 207 |
173 // Called from the main cast thread. | 208 // Called from the main cast thread. |
174 void VideoReceiver::GetEncodedVideoFrame( | 209 void VideoReceiver::GetEncodedVideoFrame( |
175 const VideoFrameEncodedCallback& callback) { | 210 const VideoFrameEncodedCallback& callback) { |
176 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 211 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
177 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); | 212 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); |
178 uint32 rtp_timestamp = 0; | 213 uint32 rtp_timestamp = 0; |
179 bool next_frame = false; | 214 bool next_frame = false; |
180 | 215 |
181 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, | 216 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, |
182 &next_frame)) { | 217 &next_frame)) { |
183 // We have no video frames. Wait for new packet(s). | 218 // We have no video frames. Wait for new packet(s). |
184 queued_encoded_callbacks_.push_back(callback); | 219 queued_encoded_callbacks_.push_back(callback); |
185 return; | 220 return; |
186 } | 221 } |
| 222 |
| 223 if (decryptor_ && !DecryptVideoFrame(&encoded_frame)) { |
| 224 // Logging already done. |
| 225 queued_encoded_callbacks_.push_back(callback); |
| 226 return; |
| 227 } |
| 228 |
187 base::TimeTicks render_time; | 229 base::TimeTicks render_time; |
188 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, | 230 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, |
189 &render_time)) { | 231 &render_time)) { |
190 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 232 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
191 base::Bind(callback, base::Passed(&encoded_frame), render_time)); | 233 base::Bind(callback, base::Passed(&encoded_frame), render_time)); |
192 } else { | 234 } else { |
193 // We have a video frame; however we are missing packets and we have time | 235 // We have a video frame; however we are missing packets and we have time |
194 // to wait for new packet(s). | 236 // to wait for new packet(s). |
195 queued_encoded_callbacks_.push_back(callback); | 237 queued_encoded_callbacks_.push_back(callback); |
196 } | 238 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 // We have no video frames. Wait for new packet(s). | 301 // We have no video frames. Wait for new packet(s). |
260 // Since the application can post multiple VideoFrameEncodedCallback and | 302 // Since the application can post multiple VideoFrameEncodedCallback and |
261 // we only check the next frame to play out we might have multiple timeout | 303 // we only check the next frame to play out we might have multiple timeout |
262 // events firing after each other; however this should be a rare event. | 304 // events firing after each other; however this should be a rare event. |
263 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; | 305 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; |
264 return; | 306 return; |
265 } | 307 } |
266 VLOG(1) << "PlayoutTimeout retrieved frame " | 308 VLOG(1) << "PlayoutTimeout retrieved frame " |
267 << static_cast<int>(encoded_frame->frame_id); | 309 << static_cast<int>(encoded_frame->frame_id); |
268 | 310 |
| 311 if (decryptor_ && !DecryptVideoFrame(&encoded_frame)) { |
| 312 // Logging already done. |
| 313 return; |
| 314 } |
| 315 |
269 base::TimeTicks render_time; | 316 base::TimeTicks render_time; |
270 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, | 317 if (PullEncodedVideoFrame(rtp_timestamp, next_frame, &encoded_frame, |
271 &render_time)) { | 318 &render_time)) { |
272 if (!queued_encoded_callbacks_.empty()) { | 319 if (!queued_encoded_callbacks_.empty()) { |
273 VideoFrameEncodedCallback callback = queued_encoded_callbacks_.front(); | 320 VideoFrameEncodedCallback callback = queued_encoded_callbacks_.front(); |
274 queued_encoded_callbacks_.pop_front(); | 321 queued_encoded_callbacks_.pop_front(); |
275 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 322 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
276 base::Bind(callback, base::Passed(&encoded_frame), render_time)); | 323 base::Bind(callback, base::Passed(&encoded_frame), render_time)); |
277 } | 324 } |
278 } else { | 325 } else { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 } | 449 } |
403 | 450 |
404 void VideoReceiver::SendNextRtcpReport() { | 451 void VideoReceiver::SendNextRtcpReport() { |
405 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 452 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
406 rtcp_->SendRtcpFromRtpReceiver(NULL, NULL); | 453 rtcp_->SendRtcpFromRtpReceiver(NULL, NULL); |
407 ScheduleNextRtcpReport(); | 454 ScheduleNextRtcpReport(); |
408 } | 455 } |
409 | 456 |
410 } // namespace cast | 457 } // namespace cast |
411 } // namespace media | 458 } // namespace media |
OLD | NEW |