| Index: media/filters/video_renderer_impl.cc
|
| diff --git a/media/filters/video_renderer_impl.cc b/media/filters/video_renderer_impl.cc
|
| index 7bf14d7a5d87c41de548e0121a2218c2143a611b..8735a0a96f2ae2ec6424c453673495e9e163fd51 100644
|
| --- a/media/filters/video_renderer_impl.cc
|
| +++ b/media/filters/video_renderer_impl.cc
|
| @@ -34,6 +34,7 @@
|
| thread_(),
|
| pending_read_(false),
|
| drop_frames_(drop_frames),
|
| + playback_rate_(0),
|
| buffering_state_(BUFFERING_HAVE_NOTHING),
|
| paint_cb_(paint_cb),
|
| last_timestamp_(kNoTimestamp()),
|
| @@ -103,6 +104,12 @@
|
| }
|
|
|
| video_frame_stream_.Stop(callback);
|
| +}
|
| +
|
| +void VideoRendererImpl::SetPlaybackRate(float playback_rate) {
|
| + DCHECK(task_runner_->BelongsToCurrentThread());
|
| + base::AutoLock auto_lock(lock_);
|
| + playback_rate_ = playback_rate;
|
| }
|
|
|
| void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
|
| @@ -214,7 +221,8 @@
|
| return;
|
|
|
| // Remain idle as long as we're not playing.
|
| - if (state_ != kPlaying || buffering_state_ != BUFFERING_HAVE_ENOUGH) {
|
| + if (state_ != kPlaying || playback_rate_ == 0 ||
|
| + buffering_state_ != BUFFERING_HAVE_ENOUGH) {
|
| UpdateStatsAndWait_Locked(kIdleTimeDelta);
|
| continue;
|
| }
|
| @@ -230,10 +238,16 @@
|
| continue;
|
| }
|
|
|
| - base::TimeDelta now = get_time_cb_.Run();
|
| - base::TimeDelta target_timestamp = ready_frames_.front()->timestamp();
|
| - base::TimeDelta earliest_paint_timestamp;
|
| - base::TimeDelta latest_paint_timestamp;
|
| + base::TimeDelta remaining_time =
|
| + CalculateSleepDuration(ready_frames_.front(), playback_rate_);
|
| +
|
| + // Sleep up to a maximum of our idle time until we're within the time to
|
| + // render the next frame.
|
| + if (remaining_time.InMicroseconds() > 0) {
|
| + remaining_time = std::min(remaining_time, kIdleTimeDelta);
|
| + UpdateStatsAndWait_Locked(remaining_time);
|
| + continue;
|
| + }
|
|
|
| // Deadline is defined as the midpoint between this frame and the next
|
| // frame, using the delta between this frame and the previous frame as the
|
| @@ -246,24 +260,15 @@
|
| //
|
| // TODO(scherkus): This can be vastly improved. Use a histogram to measure
|
| // the accuracy of our frame timing code. http://crbug.com/149829
|
| - if (last_timestamp_ == kNoTimestamp()) {
|
| - earliest_paint_timestamp = target_timestamp;
|
| - latest_paint_timestamp = base::TimeDelta::Max();
|
| - } else {
|
| - base::TimeDelta duration = target_timestamp - last_timestamp_;
|
| - earliest_paint_timestamp = target_timestamp - duration / 2;
|
| - latest_paint_timestamp = target_timestamp + duration / 2;
|
| - }
|
| -
|
| - // Remain idle until we've reached our target paint window.
|
| - if (now < earliest_paint_timestamp) {
|
| - UpdateStatsAndWait_Locked(kIdleTimeDelta);
|
| - continue;
|
| - }
|
| -
|
| - if (now > latest_paint_timestamp && drop_frames_) {
|
| - DropNextReadyFrame_Locked();
|
| - continue;
|
| + if (drop_frames_ && last_timestamp_ != kNoTimestamp()) {
|
| + base::TimeDelta now = get_time_cb_.Run();
|
| + base::TimeDelta deadline = ready_frames_.front()->timestamp() +
|
| + (ready_frames_.front()->timestamp() - last_timestamp_) / 2;
|
| +
|
| + if (now > deadline) {
|
| + DropNextReadyFrame_Locked();
|
| + continue;
|
| + }
|
| }
|
|
|
| // Congratulations! You've made it past the video frame timing gauntlet.
|
| @@ -472,6 +477,19 @@
|
| base::ResetAndReturn(&flush_cb_).Run();
|
| }
|
|
|
| +base::TimeDelta VideoRendererImpl::CalculateSleepDuration(
|
| + const scoped_refptr<VideoFrame>& next_frame,
|
| + float playback_rate) {
|
| + // Determine the current and next presentation timestamps.
|
| + base::TimeDelta now = get_time_cb_.Run();
|
| + base::TimeDelta next_pts = next_frame->timestamp();
|
| +
|
| + // Scale our sleep based on the playback rate.
|
| + base::TimeDelta sleep = next_pts - now;
|
| + return base::TimeDelta::FromMicroseconds(
|
| + static_cast<int64>(sleep.InMicroseconds() / playback_rate));
|
| +}
|
| +
|
| void VideoRendererImpl::DoStopOrError_Locked() {
|
| lock_.AssertAcquired();
|
| last_timestamp_ = kNoTimestamp();
|
|
|