| 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 |