| 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/filters/video_renderer_impl.h" | 5 #include "media/filters/video_renderer_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 // | 287 // |
| 288 // TODO(scherkus): An improvement over midpoint might be selecting the | 288 // TODO(scherkus): An improvement over midpoint might be selecting the |
| 289 // minimum and/or maximum between the midpoint and some constants. As a | 289 // minimum and/or maximum between the midpoint and some constants. As a |
| 290 // thought experiment, consider what would be better than the midpoint | 290 // thought experiment, consider what would be better than the midpoint |
| 291 // for both the 1fps case and 120fps case. | 291 // for both the 1fps case and 120fps case. |
| 292 // | 292 // |
| 293 // TODO(scherkus): This can be vastly improved. Use a histogram to measure | 293 // TODO(scherkus): This can be vastly improved. Use a histogram to measure |
| 294 // the accuracy of our frame timing code. http://crbug.com/149829 | 294 // the accuracy of our frame timing code. http://crbug.com/149829 |
| 295 if (drop_frames_ && last_timestamp_ != kNoTimestamp()) { | 295 if (drop_frames_ && last_timestamp_ != kNoTimestamp()) { |
| 296 base::TimeDelta now = get_time_cb_.Run(); | 296 base::TimeDelta now = get_time_cb_.Run(); |
| 297 base::TimeDelta deadline = ready_frames_.front()->GetTimestamp() + | 297 base::TimeDelta deadline = ready_frames_.front()->timestamp() + |
| 298 (ready_frames_.front()->GetTimestamp() - last_timestamp_) / 2; | 298 (ready_frames_.front()->timestamp() - last_timestamp_) / 2; |
| 299 | 299 |
| 300 if (now > deadline) { | 300 if (now > deadline) { |
| 301 DropNextReadyFrame_Locked(); | 301 DropNextReadyFrame_Locked(); |
| 302 continue; | 302 continue; |
| 303 } | 303 } |
| 304 } | 304 } |
| 305 | 305 |
| 306 // Congratulations! You've made it past the video frame timing gauntlet. | 306 // Congratulations! You've made it past the video frame timing gauntlet. |
| 307 // | 307 // |
| 308 // At this point enough time has passed that the next frame that ready for | 308 // At this point enough time has passed that the next frame that ready for |
| 309 // rendering. | 309 // rendering. |
| 310 PaintNextReadyFrame_Locked(); | 310 PaintNextReadyFrame_Locked(); |
| 311 } | 311 } |
| 312 } | 312 } |
| 313 | 313 |
| 314 void VideoRendererImpl::PaintNextReadyFrame_Locked() { | 314 void VideoRendererImpl::PaintNextReadyFrame_Locked() { |
| 315 lock_.AssertAcquired(); | 315 lock_.AssertAcquired(); |
| 316 | 316 |
| 317 scoped_refptr<VideoFrame> next_frame = ready_frames_.front(); | 317 scoped_refptr<VideoFrame> next_frame = ready_frames_.front(); |
| 318 ready_frames_.pop_front(); | 318 ready_frames_.pop_front(); |
| 319 frames_decoded_++; | 319 frames_decoded_++; |
| 320 | 320 |
| 321 last_timestamp_ = next_frame->GetTimestamp(); | 321 last_timestamp_ = next_frame->timestamp(); |
| 322 | 322 |
| 323 paint_cb_.Run(next_frame); | 323 paint_cb_.Run(next_frame); |
| 324 | 324 |
| 325 task_runner_->PostTask( | 325 task_runner_->PostTask( |
| 326 FROM_HERE, | 326 FROM_HERE, |
| 327 base::Bind(&VideoRendererImpl::AttemptRead, weak_factory_.GetWeakPtr())); | 327 base::Bind(&VideoRendererImpl::AttemptRead, weak_factory_.GetWeakPtr())); |
| 328 } | 328 } |
| 329 | 329 |
| 330 void VideoRendererImpl::DropNextReadyFrame_Locked() { | 330 void VideoRendererImpl::DropNextReadyFrame_Locked() { |
| 331 TRACE_EVENT0("media", "VideoRendererImpl:frameDropped"); | 331 TRACE_EVENT0("media", "VideoRendererImpl:frameDropped"); |
| 332 | 332 |
| 333 lock_.AssertAcquired(); | 333 lock_.AssertAcquired(); |
| 334 | 334 |
| 335 last_timestamp_ = ready_frames_.front()->GetTimestamp(); | 335 last_timestamp_ = ready_frames_.front()->timestamp(); |
| 336 ready_frames_.pop_front(); | 336 ready_frames_.pop_front(); |
| 337 frames_decoded_++; | 337 frames_decoded_++; |
| 338 frames_dropped_++; | 338 frames_dropped_++; |
| 339 | 339 |
| 340 task_runner_->PostTask( | 340 task_runner_->PostTask( |
| 341 FROM_HERE, | 341 FROM_HERE, |
| 342 base::Bind(&VideoRendererImpl::AttemptRead, weak_factory_.GetWeakPtr())); | 342 base::Bind(&VideoRendererImpl::AttemptRead, weak_factory_.GetWeakPtr())); |
| 343 } | 343 } |
| 344 | 344 |
| 345 void VideoRendererImpl::FrameReady(VideoFrameStream::Status status, | 345 void VideoRendererImpl::FrameReady(VideoFrameStream::Status status, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 | 389 |
| 390 if (state_ == kPrerolling) | 390 if (state_ == kPrerolling) |
| 391 TransitionToPrerolled_Locked(); | 391 TransitionToPrerolled_Locked(); |
| 392 | 392 |
| 393 return; | 393 return; |
| 394 } | 394 } |
| 395 | 395 |
| 396 // Maintain the latest frame decoded so the correct frame is displayed after | 396 // Maintain the latest frame decoded so the correct frame is displayed after |
| 397 // prerolling has completed. | 397 // prerolling has completed. |
| 398 if (state_ == kPrerolling && preroll_timestamp_ != kNoTimestamp() && | 398 if (state_ == kPrerolling && preroll_timestamp_ != kNoTimestamp() && |
| 399 frame->GetTimestamp() <= preroll_timestamp_) { | 399 frame->timestamp() <= preroll_timestamp_) { |
| 400 ready_frames_.clear(); | 400 ready_frames_.clear(); |
| 401 } | 401 } |
| 402 | 402 |
| 403 AddReadyFrame_Locked(frame); | 403 AddReadyFrame_Locked(frame); |
| 404 | 404 |
| 405 if (ShouldTransitionToPrerolled_Locked()) | 405 if (ShouldTransitionToPrerolled_Locked()) |
| 406 TransitionToPrerolled_Locked(); | 406 TransitionToPrerolled_Locked(); |
| 407 | 407 |
| 408 // Always request more decoded video if we have capacity. This serves two | 408 // Always request more decoded video if we have capacity. This serves two |
| 409 // purposes: | 409 // purposes: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 422 const scoped_refptr<VideoFrame>& frame) { | 422 const scoped_refptr<VideoFrame>& frame) { |
| 423 lock_.AssertAcquired(); | 423 lock_.AssertAcquired(); |
| 424 DCHECK(!frame->end_of_stream()); | 424 DCHECK(!frame->end_of_stream()); |
| 425 | 425 |
| 426 // Adjust the incoming frame if its rendering stop time is past the duration | 426 // Adjust the incoming frame if its rendering stop time is past the duration |
| 427 // of the video itself. This is typically the last frame of the video and | 427 // of the video itself. This is typically the last frame of the video and |
| 428 // occurs if the container specifies a duration that isn't a multiple of the | 428 // occurs if the container specifies a duration that isn't a multiple of the |
| 429 // frame rate. Another way for this to happen is for the container to state | 429 // frame rate. Another way for this to happen is for the container to state |
| 430 // a smaller duration than the largest packet timestamp. | 430 // a smaller duration than the largest packet timestamp. |
| 431 base::TimeDelta duration = get_duration_cb_.Run(); | 431 base::TimeDelta duration = get_duration_cb_.Run(); |
| 432 if (frame->GetTimestamp() > duration) { | 432 if (frame->timestamp() > duration) { |
| 433 frame->SetTimestamp(duration); | 433 frame->set_timestamp(duration); |
| 434 } | 434 } |
| 435 | 435 |
| 436 ready_frames_.push_back(frame); | 436 ready_frames_.push_back(frame); |
| 437 DCHECK_LE(ready_frames_.size(), | 437 DCHECK_LE(ready_frames_.size(), |
| 438 static_cast<size_t>(limits::kMaxVideoFrames)); | 438 static_cast<size_t>(limits::kMaxVideoFrames)); |
| 439 | 439 |
| 440 max_time_cb_.Run(frame->GetTimestamp()); | 440 max_time_cb_.Run(frame->timestamp()); |
| 441 | 441 |
| 442 // Avoid needlessly waking up |thread_| unless playing. | 442 // Avoid needlessly waking up |thread_| unless playing. |
| 443 if (state_ == kPlaying) | 443 if (state_ == kPlaying) |
| 444 frame_available_.Signal(); | 444 frame_available_.Signal(); |
| 445 } | 445 } |
| 446 | 446 |
| 447 void VideoRendererImpl::AttemptRead() { | 447 void VideoRendererImpl::AttemptRead() { |
| 448 base::AutoLock auto_lock(lock_); | 448 base::AutoLock auto_lock(lock_); |
| 449 AttemptRead_Locked(); | 449 AttemptRead_Locked(); |
| 450 } | 450 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 state_ = kFlushed; | 492 state_ = kFlushed; |
| 493 last_timestamp_ = kNoTimestamp(); | 493 last_timestamp_ = kNoTimestamp(); |
| 494 base::ResetAndReturn(&flush_cb_).Run(); | 494 base::ResetAndReturn(&flush_cb_).Run(); |
| 495 } | 495 } |
| 496 | 496 |
| 497 base::TimeDelta VideoRendererImpl::CalculateSleepDuration( | 497 base::TimeDelta VideoRendererImpl::CalculateSleepDuration( |
| 498 const scoped_refptr<VideoFrame>& next_frame, | 498 const scoped_refptr<VideoFrame>& next_frame, |
| 499 float playback_rate) { | 499 float playback_rate) { |
| 500 // Determine the current and next presentation timestamps. | 500 // Determine the current and next presentation timestamps. |
| 501 base::TimeDelta now = get_time_cb_.Run(); | 501 base::TimeDelta now = get_time_cb_.Run(); |
| 502 base::TimeDelta next_pts = next_frame->GetTimestamp(); | 502 base::TimeDelta next_pts = next_frame->timestamp(); |
| 503 | 503 |
| 504 // Scale our sleep based on the playback rate. | 504 // Scale our sleep based on the playback rate. |
| 505 base::TimeDelta sleep = next_pts - now; | 505 base::TimeDelta sleep = next_pts - now; |
| 506 return base::TimeDelta::FromMicroseconds( | 506 return base::TimeDelta::FromMicroseconds( |
| 507 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); | 507 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); |
| 508 } | 508 } |
| 509 | 509 |
| 510 void VideoRendererImpl::DoStopOrError_Locked() { | 510 void VideoRendererImpl::DoStopOrError_Locked() { |
| 511 lock_.AssertAcquired(); | 511 lock_.AssertAcquired(); |
| 512 last_timestamp_ = kNoTimestamp(); | 512 last_timestamp_ = kNoTimestamp(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 541 statistics_cb_.Run(statistics); | 541 statistics_cb_.Run(statistics); |
| 542 | 542 |
| 543 frames_decoded_ = 0; | 543 frames_decoded_ = 0; |
| 544 frames_dropped_ = 0; | 544 frames_dropped_ = 0; |
| 545 } | 545 } |
| 546 | 546 |
| 547 frame_available_.TimedWait(wait_duration); | 547 frame_available_.TimedWait(wait_duration); |
| 548 } | 548 } |
| 549 | 549 |
| 550 } // namespace media | 550 } // namespace media |
| OLD | NEW |