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 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 void VideoReceiver::GetRawVideoFrame( | 152 void VideoReceiver::GetRawVideoFrame( |
153 const VideoFrameDecodedCallback& callback) { | 153 const VideoFrameDecodedCallback& callback) { |
154 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 154 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
155 GetEncodedVideoFrame(base::Bind(&VideoReceiver::DecodeVideoFrame, | 155 GetEncodedVideoFrame(base::Bind(&VideoReceiver::DecodeVideoFrame, |
156 base::Unretained(this), callback)); | 156 base::Unretained(this), callback)); |
157 } | 157 } |
158 | 158 |
159 // Called when we have a frame to decode. | 159 // Called when we have a frame to decode. |
160 void VideoReceiver::DecodeVideoFrame( | 160 void VideoReceiver::DecodeVideoFrame( |
161 const VideoFrameDecodedCallback& callback, | 161 const VideoFrameDecodedCallback& callback, |
162 scoped_ptr<transport::EncodedVideoFrame> encoded_frame, | 162 scoped_ptr<EncodedVideoFrame> encoded_frame, |
163 const base::TimeTicks& render_time) { | 163 const base::TimeTicks& render_time) { |
164 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 164 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
165 // Hand the ownership of the encoded frame to the decode thread. | 165 // Hand the ownership of the encoded frame to the decode thread. |
166 cast_environment_->PostTask(CastEnvironment::VIDEO_DECODER, FROM_HERE, | 166 cast_environment_->PostTask(CastEnvironment::VIDEO_DECODER, FROM_HERE, |
167 base::Bind(&VideoReceiver::DecodeVideoFrameThread, base::Unretained(this), | 167 base::Bind(&VideoReceiver::DecodeVideoFrameThread, base::Unretained(this), |
168 base::Passed(&encoded_frame), render_time, callback)); | 168 base::Passed(&encoded_frame), render_time, callback)); |
169 } | 169 } |
170 | 170 |
171 // Utility function to run the decoder on a designated decoding thread. | 171 // Utility function to run the decoder on a designated decoding thread. |
172 void VideoReceiver::DecodeVideoFrameThread( | 172 void VideoReceiver::DecodeVideoFrameThread( |
173 scoped_ptr<transport::EncodedVideoFrame> encoded_frame, | 173 scoped_ptr<EncodedVideoFrame> encoded_frame, |
174 const base::TimeTicks render_time, | 174 const base::TimeTicks render_time, |
175 const VideoFrameDecodedCallback& frame_decoded_callback) { | 175 const VideoFrameDecodedCallback& frame_decoded_callback) { |
176 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO_DECODER)); | 176 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO_DECODER)); |
177 DCHECK(video_decoder_); | 177 DCHECK(video_decoder_); |
178 | 178 |
179 if (!(video_decoder_->DecodeVideoFrame(encoded_frame.get(), render_time, | 179 if (!(video_decoder_->DecodeVideoFrame(encoded_frame.get(), render_time, |
180 frame_decoded_callback))) { | 180 frame_decoded_callback))) { |
181 // 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. |
182 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 182 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
183 base::Bind(&VideoReceiver::GetRawVideoFrame, base::Unretained(this), | 183 base::Bind(&VideoReceiver::GetRawVideoFrame, base::Unretained(this), |
184 frame_decoded_callback)); | 184 frame_decoded_callback)); |
185 } | 185 } |
186 } | 186 } |
187 | 187 |
188 bool VideoReceiver::DecryptVideoFrame( | 188 bool VideoReceiver::DecryptVideoFrame( |
189 scoped_ptr<transport::EncodedVideoFrame>* video_frame) { | 189 scoped_ptr<EncodedVideoFrame>* video_frame) { |
190 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 190 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
191 DCHECK(decryptor_) << "Invalid state"; | 191 DCHECK(decryptor_) << "Invalid state"; |
192 | 192 |
193 if (!decryptor_->SetCounter(GetAesNonce((*video_frame)->frame_id, | 193 if (!decryptor_->SetCounter(GetAesNonce((*video_frame)->frame_id, |
194 iv_mask_))) { | 194 iv_mask_))) { |
195 NOTREACHED() << "Failed to set counter"; | 195 NOTREACHED() << "Failed to set counter"; |
196 return false; | 196 return false; |
197 } | 197 } |
198 std::string decrypted_video_data; | 198 std::string decrypted_video_data; |
199 if (!decryptor_->Decrypt((*video_frame)->data, &decrypted_video_data)) { | 199 if (!decryptor_->Decrypt((*video_frame)->data, &decrypted_video_data)) { |
200 VLOG(1) << "Decryption error"; | 200 VLOG(1) << "Decryption error"; |
201 // Give up on this frame, release it from jitter buffer. | 201 // Give up on this frame, release it from jitter buffer. |
202 framer_->ReleaseFrame((*video_frame)->frame_id); | 202 framer_->ReleaseFrame((*video_frame)->frame_id); |
203 return false; | 203 return false; |
204 } | 204 } |
205 (*video_frame)->data.swap(decrypted_video_data); | 205 (*video_frame)->data.swap(decrypted_video_data); |
206 return true; | 206 return true; |
207 } | 207 } |
208 | 208 |
209 // Called from the main cast thread. | 209 // Called from the main cast thread. |
210 void VideoReceiver::GetEncodedVideoFrame( | 210 void VideoReceiver::GetEncodedVideoFrame( |
211 const VideoFrameEncodedCallback& callback) { | 211 const VideoFrameEncodedCallback& callback) { |
212 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 212 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
213 scoped_ptr<transport::EncodedVideoFrame> encoded_frame( | 213 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); |
214 new transport::EncodedVideoFrame()); | |
215 uint32 rtp_timestamp = 0; | 214 uint32 rtp_timestamp = 0; |
216 bool next_frame = false; | 215 bool next_frame = false; |
217 | 216 |
218 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, | 217 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, |
219 &next_frame)) { | 218 &next_frame)) { |
220 // We have no video frames. Wait for new packet(s). | 219 // We have no video frames. Wait for new packet(s). |
221 queued_encoded_callbacks_.push_back(callback); | 220 queued_encoded_callbacks_.push_back(callback); |
222 return; | 221 return; |
223 } | 222 } |
224 | 223 |
(...skipping 14 matching lines...) Expand all Loading... |
239 queued_encoded_callbacks_.push_back(callback); | 238 queued_encoded_callbacks_.push_back(callback); |
240 } | 239 } |
241 } | 240 } |
242 | 241 |
243 // Should we pull the encoded video frame from the framer? decided by if this is | 242 // Should we pull the encoded video frame from the framer? decided by if this is |
244 // the next frame or we are running out of time and have to pull the following | 243 // the next frame or we are running out of time and have to pull the following |
245 // frame. | 244 // frame. |
246 // If the frame is too old to be rendered we set the don't show flag in the | 245 // If the frame is too old to be rendered we set the don't show flag in the |
247 // video bitstream where possible. | 246 // video bitstream where possible. |
248 bool VideoReceiver::PullEncodedVideoFrame(uint32 rtp_timestamp, | 247 bool VideoReceiver::PullEncodedVideoFrame(uint32 rtp_timestamp, |
249 bool next_frame, scoped_ptr<transport::EncodedVideoFrame>* encoded_frame, | 248 bool next_frame, scoped_ptr<EncodedVideoFrame>* encoded_frame, |
250 base::TimeTicks* render_time) { | 249 base::TimeTicks* render_time) { |
251 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 250 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
252 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 251 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
253 *render_time = GetRenderTime(now, rtp_timestamp); | 252 *render_time = GetRenderTime(now, rtp_timestamp); |
254 | 253 |
255 // TODO(mikhal): Store actual render time and not diff. | 254 // TODO(mikhal): Store actual render time and not diff. |
256 cast_environment_->Logging()->InsertFrameEventWithDelay(now, | 255 cast_environment_->Logging()->InsertFrameEventWithDelay(now, |
257 kVideoRenderDelay, rtp_timestamp, (*encoded_frame)->frame_id, | 256 kVideoRenderDelay, rtp_timestamp, (*encoded_frame)->frame_id, |
258 now - *render_time); | 257 now - *render_time); |
259 | 258 |
(...skipping 12 matching lines...) Expand all Loading... |
272 base::Bind(&VideoReceiver::PlayoutTimeout, weak_factory_.GetWeakPtr()), | 271 base::Bind(&VideoReceiver::PlayoutTimeout, weak_factory_.GetWeakPtr()), |
273 time_until_release); | 272 time_until_release); |
274 VLOG(1) << "Wait before releasing frame " | 273 VLOG(1) << "Wait before releasing frame " |
275 << static_cast<int>((*encoded_frame)->frame_id) | 274 << static_cast<int>((*encoded_frame)->frame_id) |
276 << " time " << time_until_release.InMilliseconds(); | 275 << " time " << time_until_release.InMilliseconds(); |
277 return false; | 276 return false; |
278 } | 277 } |
279 | 278 |
280 base::TimeDelta dont_show_timeout_delta = | 279 base::TimeDelta dont_show_timeout_delta = |
281 base::TimeDelta::FromMilliseconds(-kDontShowTimeoutMs); | 280 base::TimeDelta::FromMilliseconds(-kDontShowTimeoutMs); |
282 if (codec_ == transport::kVp8 && | 281 if (codec_ == kVp8 && time_until_render < dont_show_timeout_delta) { |
283 time_until_render < dont_show_timeout_delta) { | |
284 (*encoded_frame)->data[0] &= 0xef; | 282 (*encoded_frame)->data[0] &= 0xef; |
285 VLOG(1) << "Don't show frame " | 283 VLOG(1) << "Don't show frame " |
286 << static_cast<int>((*encoded_frame)->frame_id) | 284 << static_cast<int>((*encoded_frame)->frame_id) |
287 << " time_until_render:" << time_until_render.InMilliseconds(); | 285 << " time_until_render:" << time_until_render.InMilliseconds(); |
288 } else { | 286 } else { |
289 VLOG(1) << "Show frame " | 287 VLOG(1) << "Show frame " |
290 << static_cast<int>((*encoded_frame)->frame_id) | 288 << static_cast<int>((*encoded_frame)->frame_id) |
291 << " time_until_render:" << time_until_render.InMilliseconds(); | 289 << " time_until_render:" << time_until_render.InMilliseconds(); |
292 } | 290 } |
293 // We have a copy of the frame, release this one. | 291 // We have a copy of the frame, release this one. |
294 framer_->ReleaseFrame((*encoded_frame)->frame_id); | 292 framer_->ReleaseFrame((*encoded_frame)->frame_id); |
295 (*encoded_frame)->codec = codec_; | 293 (*encoded_frame)->codec = codec_; |
296 return true; | 294 return true; |
297 } | 295 } |
298 | 296 |
299 void VideoReceiver::PlayoutTimeout() { | 297 void VideoReceiver::PlayoutTimeout() { |
300 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 298 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
301 if (queued_encoded_callbacks_.empty()) return; | 299 if (queued_encoded_callbacks_.empty()) return; |
302 | 300 |
303 uint32 rtp_timestamp = 0; | 301 uint32 rtp_timestamp = 0; |
304 bool next_frame = false; | 302 bool next_frame = false; |
305 scoped_ptr<transport::EncodedVideoFrame> encoded_frame( | 303 scoped_ptr<EncodedVideoFrame> encoded_frame(new EncodedVideoFrame()); |
306 new transport::EncodedVideoFrame()); | |
307 | 304 |
308 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, | 305 if (!framer_->GetEncodedVideoFrame(encoded_frame.get(), &rtp_timestamp, |
309 &next_frame)) { | 306 &next_frame)) { |
310 // We have no video frames. Wait for new packet(s). | 307 // We have no video frames. Wait for new packet(s). |
311 // Since the application can post multiple VideoFrameEncodedCallback and | 308 // Since the application can post multiple VideoFrameEncodedCallback and |
312 // we only check the next frame to play out we might have multiple timeout | 309 // we only check the next frame to play out we might have multiple timeout |
313 // events firing after each other; however this should be a rare event. | 310 // events firing after each other; however this should be a rare event. |
314 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; | 311 VLOG(1) << "Failed to retrieved a complete frame at this point in time"; |
315 return; | 312 return; |
316 } | 313 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 } | 474 } |
478 | 475 |
479 void VideoReceiver::SendNextRtcpReport() { | 476 void VideoReceiver::SendNextRtcpReport() { |
480 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 477 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
481 rtcp_->SendRtcpFromRtpReceiver(NULL, NULL); | 478 rtcp_->SendRtcpFromRtpReceiver(NULL, NULL); |
482 ScheduleNextRtcpReport(); | 479 ScheduleNextRtcpReport(); |
483 } | 480 } |
484 | 481 |
485 } // namespace cast | 482 } // namespace cast |
486 } // namespace media | 483 } // namespace media |
OLD | NEW |