Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(577)

Side by Side Diff: media/filters/video_renderer_impl.cc

Issue 384943002: Remove media::VideoRenderer::SetPlaybackRate(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tweak display window Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/video_renderer_impl.h ('k') | media/filters/video_renderer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 16 matching lines...) Expand all
27 : task_runner_(task_runner), 27 : task_runner_(task_runner),
28 video_frame_stream_(task_runner, decoders.Pass(), set_decryptor_ready_cb), 28 video_frame_stream_(task_runner, decoders.Pass(), set_decryptor_ready_cb),
29 low_delay_(false), 29 low_delay_(false),
30 received_end_of_stream_(false), 30 received_end_of_stream_(false),
31 rendered_end_of_stream_(false), 31 rendered_end_of_stream_(false),
32 frame_available_(&lock_), 32 frame_available_(&lock_),
33 state_(kUninitialized), 33 state_(kUninitialized),
34 thread_(), 34 thread_(),
35 pending_read_(false), 35 pending_read_(false),
36 drop_frames_(drop_frames), 36 drop_frames_(drop_frames),
37 playback_rate_(0),
38 buffering_state_(BUFFERING_HAVE_NOTHING), 37 buffering_state_(BUFFERING_HAVE_NOTHING),
39 paint_cb_(paint_cb), 38 paint_cb_(paint_cb),
40 last_timestamp_(kNoTimestamp()), 39 last_timestamp_(kNoTimestamp()),
41 frames_decoded_(0), 40 frames_decoded_(0),
42 frames_dropped_(0), 41 frames_dropped_(0),
43 weak_factory_(this) { 42 weak_factory_(this) {
44 DCHECK(!paint_cb_.is_null()); 43 DCHECK(!paint_cb_.is_null());
45 } 44 }
46 45
47 VideoRendererImpl::~VideoRendererImpl() { 46 VideoRendererImpl::~VideoRendererImpl() {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 } 98 }
100 99
101 if (!thread_to_join.is_null()) { 100 if (!thread_to_join.is_null()) {
102 base::AutoUnlock auto_unlock(lock_); 101 base::AutoUnlock auto_unlock(lock_);
103 base::PlatformThread::Join(thread_to_join); 102 base::PlatformThread::Join(thread_to_join);
104 } 103 }
105 104
106 video_frame_stream_.Stop(callback); 105 video_frame_stream_.Stop(callback);
107 } 106 }
108 107
109 void VideoRendererImpl::SetPlaybackRate(float playback_rate) {
110 DCHECK(task_runner_->BelongsToCurrentThread());
111 base::AutoLock auto_lock(lock_);
112 playback_rate_ = playback_rate;
113 }
114
115 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { 108 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
116 DCHECK(task_runner_->BelongsToCurrentThread()); 109 DCHECK(task_runner_->BelongsToCurrentThread());
117 base::AutoLock auto_lock(lock_); 110 base::AutoLock auto_lock(lock_);
118 DCHECK_EQ(state_, kFlushed); 111 DCHECK_EQ(state_, kFlushed);
119 DCHECK(!pending_read_); 112 DCHECK(!pending_read_);
120 DCHECK(ready_frames_.empty()); 113 DCHECK(ready_frames_.empty());
121 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); 114 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
122 115
123 state_ = kPlaying; 116 state_ = kPlaying;
124 start_timestamp_ = timestamp; 117 start_timestamp_ = timestamp;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 base::TimeDelta::FromMilliseconds(10); 207 base::TimeDelta::FromMilliseconds(10);
215 208
216 for (;;) { 209 for (;;) {
217 base::AutoLock auto_lock(lock_); 210 base::AutoLock auto_lock(lock_);
218 211
219 // Thread exit condition. 212 // Thread exit condition.
220 if (state_ == kStopped) 213 if (state_ == kStopped)
221 return; 214 return;
222 215
223 // Remain idle as long as we're not playing. 216 // Remain idle as long as we're not playing.
224 if (state_ != kPlaying || playback_rate_ == 0 || 217 if (state_ != kPlaying || buffering_state_ != BUFFERING_HAVE_ENOUGH) {
225 buffering_state_ != BUFFERING_HAVE_ENOUGH) {
226 UpdateStatsAndWait_Locked(kIdleTimeDelta); 218 UpdateStatsAndWait_Locked(kIdleTimeDelta);
227 continue; 219 continue;
228 } 220 }
229 221
230 // Remain idle until we have the next frame ready for rendering. 222 // Remain idle until we have the next frame ready for rendering.
231 if (ready_frames_.empty()) { 223 if (ready_frames_.empty()) {
232 if (received_end_of_stream_ && !rendered_end_of_stream_) { 224 if (received_end_of_stream_ && !rendered_end_of_stream_) {
233 rendered_end_of_stream_ = true; 225 rendered_end_of_stream_ = true;
234 ended_cb_.Run(); 226 ended_cb_.Run();
235 } 227 }
236 228
237 UpdateStatsAndWait_Locked(kIdleTimeDelta); 229 UpdateStatsAndWait_Locked(kIdleTimeDelta);
238 continue; 230 continue;
239 } 231 }
240 232
241 base::TimeDelta remaining_time = 233 base::TimeDelta now = get_time_cb_.Run();
242 CalculateSleepDuration(ready_frames_.front(), playback_rate_); 234 base::TimeDelta earliest_paint_timestamp;
243 235 base::TimeDelta latest_paint_timestamp;
244 // Sleep up to a maximum of our idle time until we're within the time to
245 // render the next frame.
246 if (remaining_time.InMicroseconds() > 0) {
247 remaining_time = std::min(remaining_time, kIdleTimeDelta);
248 UpdateStatsAndWait_Locked(remaining_time);
249 continue;
250 }
251 236
252 // Deadline is defined as the midpoint between this frame and the next 237 // Deadline is defined as the midpoint between this frame and the next
253 // frame, using the delta between this frame and the previous frame as the 238 // frame, using the delta between this frame and the previous frame as the
254 // assumption for frame duration. 239 // assumption for frame duration.
255 // 240 //
256 // TODO(scherkus): An improvement over midpoint might be selecting the 241 // TODO(scherkus): An improvement over midpoint might be selecting the
257 // minimum and/or maximum between the midpoint and some constants. As a 242 // minimum and/or maximum between the midpoint and some constants. As a
258 // thought experiment, consider what would be better than the midpoint 243 // thought experiment, consider what would be better than the midpoint
259 // for both the 1fps case and 120fps case. 244 // for both the 1fps case and 120fps case.
260 // 245 //
261 // TODO(scherkus): This can be vastly improved. Use a histogram to measure 246 // TODO(scherkus): This can be vastly improved. Use a histogram to measure
262 // the accuracy of our frame timing code. http://crbug.com/149829 247 // the accuracy of our frame timing code. http://crbug.com/149829
263 if (drop_frames_ && last_timestamp_ != kNoTimestamp()) { 248 if (last_timestamp_ == kNoTimestamp()) {
264 base::TimeDelta now = get_time_cb_.Run(); 249 earliest_paint_timestamp = ready_frames_.front()->timestamp();
265 base::TimeDelta deadline = ready_frames_.front()->timestamp() + 250 latest_paint_timestamp = base::TimeDelta::Max();
266 (ready_frames_.front()->timestamp() - last_timestamp_) / 2; 251 } else {
252 base::TimeDelta duration =
253 ready_frames_.front()->timestamp() - last_timestamp_;
xhwang 2014/07/11 20:49:49 nit: ready_frames_.front()->timestamp() is used 4
scherkus (not reviewing) 2014/07/11 20:54:02 Done.
254 earliest_paint_timestamp =
255 ready_frames_.front()->timestamp() - duration / 2;
256 latest_paint_timestamp =
257 ready_frames_.front()->timestamp() + duration / 2;
258 }
267 259
268 if (now > deadline) { 260 // Remain idle until we've reached our target paint window.
269 DropNextReadyFrame_Locked(); 261 if (now < earliest_paint_timestamp) {
270 continue; 262 UpdateStatsAndWait_Locked(kIdleTimeDelta);
271 } 263 continue;
264 }
265
266 if (now > latest_paint_timestamp && drop_frames_) {
267 DropNextReadyFrame_Locked();
268 continue;
272 } 269 }
273 270
274 // Congratulations! You've made it past the video frame timing gauntlet. 271 // Congratulations! You've made it past the video frame timing gauntlet.
275 // 272 //
276 // At this point enough time has passed that the next frame that ready for 273 // At this point enough time has passed that the next frame that ready for
277 // rendering. 274 // rendering.
278 PaintNextReadyFrame_Locked(); 275 PaintNextReadyFrame_Locked();
279 } 276 }
280 } 277 }
281 278
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 DCHECK(ready_frames_.empty()); 467 DCHECK(ready_frames_.empty());
471 DCHECK(!received_end_of_stream_); 468 DCHECK(!received_end_of_stream_);
472 DCHECK(!rendered_end_of_stream_); 469 DCHECK(!rendered_end_of_stream_);
473 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); 470 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
474 471
475 state_ = kFlushed; 472 state_ = kFlushed;
476 last_timestamp_ = kNoTimestamp(); 473 last_timestamp_ = kNoTimestamp();
477 base::ResetAndReturn(&flush_cb_).Run(); 474 base::ResetAndReturn(&flush_cb_).Run();
478 } 475 }
479 476
480 base::TimeDelta VideoRendererImpl::CalculateSleepDuration(
481 const scoped_refptr<VideoFrame>& next_frame,
482 float playback_rate) {
483 // Determine the current and next presentation timestamps.
484 base::TimeDelta now = get_time_cb_.Run();
485 base::TimeDelta next_pts = next_frame->timestamp();
486
487 // Scale our sleep based on the playback rate.
488 base::TimeDelta sleep = next_pts - now;
489 return base::TimeDelta::FromMicroseconds(
490 static_cast<int64>(sleep.InMicroseconds() / playback_rate));
491 }
492
493 void VideoRendererImpl::DoStopOrError_Locked() { 477 void VideoRendererImpl::DoStopOrError_Locked() {
494 lock_.AssertAcquired(); 478 lock_.AssertAcquired();
495 last_timestamp_ = kNoTimestamp(); 479 last_timestamp_ = kNoTimestamp();
496 ready_frames_.clear(); 480 ready_frames_.clear();
497 } 481 }
498 482
499 void VideoRendererImpl::UpdateStatsAndWait_Locked( 483 void VideoRendererImpl::UpdateStatsAndWait_Locked(
500 base::TimeDelta wait_duration) { 484 base::TimeDelta wait_duration) {
501 lock_.AssertAcquired(); 485 lock_.AssertAcquired();
502 DCHECK_GE(frames_decoded_, 0); 486 DCHECK_GE(frames_decoded_, 0);
503 DCHECK_LE(frames_dropped_, frames_decoded_); 487 DCHECK_LE(frames_dropped_, frames_decoded_);
504 488
505 if (frames_decoded_) { 489 if (frames_decoded_) {
506 PipelineStatistics statistics; 490 PipelineStatistics statistics;
507 statistics.video_frames_decoded = frames_decoded_; 491 statistics.video_frames_decoded = frames_decoded_;
508 statistics.video_frames_dropped = frames_dropped_; 492 statistics.video_frames_dropped = frames_dropped_;
509 statistics_cb_.Run(statistics); 493 statistics_cb_.Run(statistics);
510 494
511 frames_decoded_ = 0; 495 frames_decoded_ = 0;
512 frames_dropped_ = 0; 496 frames_dropped_ = 0;
513 } 497 }
514 498
515 frame_available_.TimedWait(wait_duration); 499 frame_available_.TimedWait(wait_duration);
516 } 500 }
517 501
518 } // namespace media 502 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/video_renderer_impl.h ('k') | media/filters/video_renderer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698