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

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

Issue 12096081: Replace VideoRendererBase Get/PutCurrentFrame() with a VideoFrame-containing callback. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 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_base.h ('k') | media/filters/video_renderer_base_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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_base.h" 5 #include "media/filters/video_renderer_base.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/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/threading/platform_thread.h" 11 #include "base/threading/platform_thread.h"
12 #include "media/base/buffers.h" 12 #include "media/base/buffers.h"
13 #include "media/base/limits.h" 13 #include "media/base/limits.h"
14 #include "media/base/pipeline.h" 14 #include "media/base/pipeline.h"
15 #include "media/base/video_frame.h" 15 #include "media/base/video_frame.h"
16 #include "media/filters/decrypting_demuxer_stream.h" 16 #include "media/filters/decrypting_demuxer_stream.h"
17 #include "media/filters/video_decoder_selector.h" 17 #include "media/filters/video_decoder_selector.h"
18 18
19 namespace media { 19 namespace media {
20 20
21 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { 21 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() {
22 return base::TimeDelta::FromMilliseconds(250); 22 return base::TimeDelta::FromMilliseconds(250);
23 } 23 }
24 24
25 VideoRendererBase::VideoRendererBase( 25 VideoRendererBase::VideoRendererBase(
26 const scoped_refptr<base::MessageLoopProxy>& message_loop, 26 const scoped_refptr<base::MessageLoopProxy>& message_loop,
27 const SetDecryptorReadyCB& set_decryptor_ready_cb, 27 const SetDecryptorReadyCB& set_decryptor_ready_cb,
28 const base::Closure& paint_cb, 28 const PaintCB& paint_cb,
29 const SetOpaqueCB& set_opaque_cb, 29 const SetOpaqueCB& set_opaque_cb,
30 bool drop_frames) 30 bool drop_frames)
31 : message_loop_(message_loop), 31 : message_loop_(message_loop),
32 set_decryptor_ready_cb_(set_decryptor_ready_cb), 32 set_decryptor_ready_cb_(set_decryptor_ready_cb),
33 frame_available_(&lock_), 33 frame_available_(&lock_),
34 state_(kUninitialized), 34 state_(kUninitialized),
35 thread_(base::kNullThreadHandle), 35 thread_(base::kNullThreadHandle),
36 pending_read_(false), 36 pending_read_(false),
37 pending_paint_(false),
38 pending_paint_with_last_available_(false),
39 drop_frames_(drop_frames), 37 drop_frames_(drop_frames),
40 playback_rate_(0), 38 playback_rate_(0),
41 paint_cb_(paint_cb), 39 paint_cb_(paint_cb),
42 set_opaque_cb_(set_opaque_cb) { 40 set_opaque_cb_(set_opaque_cb),
41 last_timestamp_(kNoTimestamp()) {
43 DCHECK(!paint_cb_.is_null()); 42 DCHECK(!paint_cb_.is_null());
44 } 43 }
45 44
46 void VideoRendererBase::Play(const base::Closure& callback) { 45 void VideoRendererBase::Play(const base::Closure& callback) {
47 DCHECK(message_loop_->BelongsToCurrentThread()); 46 DCHECK(message_loop_->BelongsToCurrentThread());
48 base::AutoLock auto_lock(lock_); 47 base::AutoLock auto_lock(lock_);
49 DCHECK_EQ(kPrerolled, state_); 48 DCHECK_EQ(kPrerolled, state_);
50 state_ = kPlaying; 49 state_ = kPlaying;
51 callback.Run(); 50 callback.Run();
52 } 51 }
(...skipping 23 matching lines...) Expand all
76 } 75 }
77 76
78 void VideoRendererBase::ResetDecoder() { 77 void VideoRendererBase::ResetDecoder() {
79 DCHECK(message_loop_->BelongsToCurrentThread()); 78 DCHECK(message_loop_->BelongsToCurrentThread());
80 base::AutoLock auto_lock(lock_); 79 base::AutoLock auto_lock(lock_);
81 decoder_->Reset(base::Bind(&VideoRendererBase::OnDecoderResetDone, this)); 80 decoder_->Reset(base::Bind(&VideoRendererBase::OnDecoderResetDone, this));
82 } 81 }
83 82
84 void VideoRendererBase::Stop(const base::Closure& callback) { 83 void VideoRendererBase::Stop(const base::Closure& callback) {
85 DCHECK(message_loop_->BelongsToCurrentThread()); 84 DCHECK(message_loop_->BelongsToCurrentThread());
85 base::AutoLock auto_lock(lock_);
86 if (state_ == kUninitialized || state_ == kStopped) { 86 if (state_ == kUninitialized || state_ == kStopped) {
87 callback.Run(); 87 callback.Run();
88 return; 88 return;
89 } 89 }
90 90
91 state_ = kStopped;
92
93 statistics_cb_.Reset();
94 max_time_cb_.Reset();
95 DoStopOrError_Locked();
96
97 // Clean up our thread if present.
91 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; 98 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle;
92 { 99 if (thread_ != base::kNullThreadHandle) {
93 base::AutoLock auto_lock(lock_); 100 // Signal the thread since it's possible to get stopped with the video
94 state_ = kStopped; 101 // thread waiting for a read to complete.
102 frame_available_.Signal();
103 std::swap(thread_, thread_to_join);
104 }
95 105
96 statistics_cb_.Reset(); 106 if (thread_to_join != base::kNullThreadHandle) {
97 max_time_cb_.Reset(); 107 base::AutoUnlock auto_unlock(lock_);
98 if (!pending_paint_ && !pending_paint_with_last_available_) 108 base::PlatformThread::Join(thread_to_join);
99 DoStopOrError_Locked();
100
101 // Clean up our thread if present.
102 if (thread_ != base::kNullThreadHandle) {
103 // Signal the thread since it's possible to get stopped with the video
104 // thread waiting for a read to complete.
105 frame_available_.Signal();
106 thread_to_join = thread_;
107 thread_ = base::kNullThreadHandle;
108 }
109 } 109 }
110 if (thread_to_join != base::kNullThreadHandle)
111 base::PlatformThread::Join(thread_to_join);
112 110
113 if (decrypting_demuxer_stream_) { 111 if (decrypting_demuxer_stream_) {
114 decrypting_demuxer_stream_->Reset(base::Bind( 112 decrypting_demuxer_stream_->Reset(base::Bind(
115 &VideoRendererBase::StopDecoder, this, callback)); 113 &VideoRendererBase::StopDecoder, this, callback));
116 return; 114 return;
117 } 115 }
118 116
119 decoder_->Stop(callback); 117 decoder_->Stop(callback);
120 } 118 }
121 119
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 243
246 // The number of milliseconds to idle when we do not have anything to do. 244 // The number of milliseconds to idle when we do not have anything to do.
247 // Nothing special about the value, other than we're being more OS-friendly 245 // Nothing special about the value, other than we're being more OS-friendly
248 // than sleeping for 1 millisecond. 246 // than sleeping for 1 millisecond.
249 // 247 //
250 // TOOD(scherkus): switch to pure event-driven frame timing instead of this 248 // TOOD(scherkus): switch to pure event-driven frame timing instead of this
251 // kIdleTimeDelta business http://crbug.com/106874 249 // kIdleTimeDelta business http://crbug.com/106874
252 const base::TimeDelta kIdleTimeDelta = 250 const base::TimeDelta kIdleTimeDelta =
253 base::TimeDelta::FromMilliseconds(10); 251 base::TimeDelta::FromMilliseconds(10);
254 252
255 uint32 frames_dropped = 0;
256
257 for (;;) { 253 for (;;) {
258 base::AutoLock auto_lock(lock_); 254 base::AutoLock auto_lock(lock_);
259 255
260 // Thread exit condition. 256 // Thread exit condition.
261 if (state_ == kStopped) 257 if (state_ == kStopped)
262 return; 258 return;
263 259
264 if (frames_dropped > 0) {
265 PipelineStatistics statistics;
266 statistics.video_frames_dropped = frames_dropped;
267 statistics_cb_.Run(statistics);
268
269 frames_dropped = 0;
270 }
271
272 // Remain idle as long as we're not playing. 260 // Remain idle as long as we're not playing.
273 if (state_ != kPlaying || playback_rate_ == 0) { 261 if (state_ != kPlaying || playback_rate_ == 0) {
274 frame_available_.TimedWait(kIdleTimeDelta); 262 frame_available_.TimedWait(kIdleTimeDelta);
275 continue; 263 continue;
276 } 264 }
277 265
278 // Remain idle until we have the next frame ready for rendering. 266 // Remain idle until we have the next frame ready for rendering.
279 if (ready_frames_.empty()) { 267 if (ready_frames_.empty()) {
280 frame_available_.TimedWait(kIdleTimeDelta); 268 frame_available_.TimedWait(kIdleTimeDelta);
281 continue; 269 continue;
282 } 270 }
283 271
284 // Remain idle until we've initialized |current_frame_| via prerolling. 272 // We've reached the end!
285 if (!current_frame_) { 273 if (ready_frames_.front()->IsEndOfStream()) {
286 // This can happen if our preroll only contains end of stream frames. 274 state_ = kEnded;
287 if (ready_frames_.front()->IsEndOfStream()) { 275 ended_cb_.Run();
288 state_ = kEnded;
289 ended_cb_.Run();
290 ready_frames_.clear();
acolwell GONE FROM CHROMIUM 2013/02/04 17:35:15 Shouldn't we keep this line?
scherkus (not reviewing) 2013/02/05 00:29:39 Done.
291 276
292 // No need to sleep here as we idle when |state_ != kPlaying|. 277 // No need to sleep here as we idle when |state_ != kPlaying|.
293 continue;
294 }
295
296 frame_available_.TimedWait(kIdleTimeDelta);
297 continue; 278 continue;
298 } 279 }
299 280
300 // Calculate how long until we should advance the frame, which is
301 // typically negative but for playback rates < 1.0f may be long enough
302 // that it makes more sense to idle and check again.
303 base::TimeDelta remaining_time = 281 base::TimeDelta remaining_time =
304 CalculateSleepDuration(ready_frames_.front(), playback_rate_); 282 CalculateSleepDuration(ready_frames_.front(), playback_rate_);
305 283
306 // Sleep up to a maximum of our idle time until we're within the time to 284 // Sleep up to a maximum of our idle time until we're within the time to
307 // render the next frame. 285 // render the next frame.
308 if (remaining_time.InMicroseconds() > 0) { 286 if (remaining_time.InMicroseconds() > 0) {
309 remaining_time = std::min(remaining_time, kIdleTimeDelta); 287 remaining_time = std::min(remaining_time, kIdleTimeDelta);
310 frame_available_.TimedWait(remaining_time); 288 frame_available_.TimedWait(remaining_time);
311 continue; 289 continue;
312 } 290 }
313 291
292 // Deadline is defined as the midpoint between this frame and the next
scherkus (not reviewing) 2013/02/01 22:45:25 The old code's deadline was defined as: remaining_
scherkus (not reviewing) 2013/02/05 00:29:39 Expanded this comment w/ more ideas.
293 // frame, using the delta between this frame and the previous frame as the
294 // assumption for frame duration.
295 //
296 // TODO(scherkus): This can be vastly improved. Use a histogram to measure
297 // the accuracy of our frame timing code. http://crbug.com/149829
298 if (drop_frames_ && last_timestamp_ != kNoTimestamp()) {
299 base::TimeDelta now = get_time_cb_.Run();
300 base::TimeDelta deadline = ready_frames_.front()->GetTimestamp() +
301 (ready_frames_.front()->GetTimestamp() - last_timestamp_) / 2;
314 302
315 // We're almost there! 303 if (now > deadline) {
316 // 304 DropNextReadyFrame_Locked();
317 // At this point we've rendered |current_frame_| for the proper amount 305 continue;
318 // of time and also have the next frame that ready for rendering. 306 }
319
320
321 // If the next frame is end of stream then we are truly at the end of the
322 // video stream.
323 //
324 // TODO(scherkus): deduplicate this end of stream check after we get rid of
325 // |current_frame_|.
326 if (ready_frames_.front()->IsEndOfStream()) {
327 state_ = kEnded;
328 ended_cb_.Run();
329 ready_frames_.clear();
330
331 // No need to sleep here as we idle when |state_ != kPlaying|.
332 continue;
333 } 307 }
334 308
335 // We cannot update |current_frame_| until we've completed the pending
336 // paint. Furthermore, the pending paint might be really slow: check to
337 // see if we have any ready frames that we can drop if they've already
338 // expired.
339 if (pending_paint_) {
340 while (!ready_frames_.empty()) {
341 // Can't drop anything if we're at the end.
342 if (ready_frames_.front()->IsEndOfStream())
343 break;
344
345 base::TimeDelta remaining_time =
346 ready_frames_.front()->GetTimestamp() - get_time_cb_.Run();
347
348 // Still a chance we can render the frame!
349 if (remaining_time.InMicroseconds() > 0)
350 break;
351
352 if (!drop_frames_)
353 break;
354
355 // Frame dropped: read again.
356 ++frames_dropped;
357 ready_frames_.pop_front();
358 message_loop_->PostTask(FROM_HERE, base::Bind(
359 &VideoRendererBase::AttemptRead, this));
360 }
361 // Continue waiting for the current paint to finish.
362 frame_available_.TimedWait(kIdleTimeDelta);
363 continue;
364 }
365
366
367 // Congratulations! You've made it past the video frame timing gauntlet. 309 // Congratulations! You've made it past the video frame timing gauntlet.
368 // 310 //
369 // We can now safely update the current frame, request another frame, and 311 // At this point enough time has passed that the next frame that ready for
370 // signal to the client that a new frame is available. 312 // rendering.
371 DCHECK(!pending_paint_); 313 PaintNextReadyFrame_Locked();
372 DCHECK(!ready_frames_.empty());
373 SetCurrentFrameToNextReadyFrame();
374 message_loop_->PostTask(FROM_HERE, base::Bind(
375 &VideoRendererBase::AttemptRead, this));
376
377 base::AutoUnlock auto_unlock(lock_);
378 paint_cb_.Run();
379 } 314 }
380 } 315 }
381 316
382 void VideoRendererBase::SetCurrentFrameToNextReadyFrame() { 317 void VideoRendererBase::PaintNextReadyFrame_Locked() {
383 current_frame_ = ready_frames_.front(); 318 lock_.AssertAcquired();
319
320 scoped_refptr<VideoFrame> next_frame = ready_frames_.front();
384 ready_frames_.pop_front(); 321 ready_frames_.pop_front();
385 322
386 // Notify the pipeline of natural_size() changes. 323 last_timestamp_ = next_frame->GetTimestamp();
387 const gfx::Size& natural_size = current_frame_->natural_size(); 324
325 const gfx::Size& natural_size = next_frame->natural_size();
388 if (natural_size != last_natural_size_) { 326 if (natural_size != last_natural_size_) {
327 last_natural_size_ = natural_size;
389 size_changed_cb_.Run(natural_size); 328 size_changed_cb_.Run(natural_size);
390 last_natural_size_ = natural_size;
391 } 329 }
330
331 paint_cb_.Run(next_frame);
332
333 message_loop_->PostTask(FROM_HERE, base::Bind(
334 &VideoRendererBase::AttemptRead, this));
392 } 335 }
393 336
394 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { 337 void VideoRendererBase::DropNextReadyFrame_Locked() {
395 base::AutoLock auto_lock(lock_); 338 lock_.AssertAcquired();
396 DCHECK(!pending_paint_ && !pending_paint_with_last_available_);
397 339
398 if ((!current_frame_ || current_frame_->IsEndOfStream()) && 340 last_timestamp_ = ready_frames_.front()->GetTimestamp();
399 (!last_available_frame_ || last_available_frame_->IsEndOfStream())) { 341 ready_frames_.pop_front();
400 *frame_out = NULL;
401 return;
402 }
403 342
404 // We should have initialized and have the current frame. 343 PipelineStatistics statistics;
405 DCHECK_NE(state_, kUninitialized); 344 statistics.video_frames_dropped = 1;
406 DCHECK_NE(state_, kStopped); 345 statistics_cb_.Run(statistics);
407 DCHECK_NE(state_, kError);
408 346
409 if (current_frame_) { 347 message_loop_->PostTask(FROM_HERE, base::Bind(
410 *frame_out = current_frame_; 348 &VideoRendererBase::AttemptRead, this));
411 last_available_frame_ = current_frame_;
412 pending_paint_ = true;
413 } else {
414 DCHECK(last_available_frame_);
415 *frame_out = last_available_frame_;
416 pending_paint_with_last_available_ = true;
417 }
418 }
419
420 void VideoRendererBase::PutCurrentFrame(scoped_refptr<VideoFrame> frame) {
421 base::AutoLock auto_lock(lock_);
422
423 // Note that we do not claim |pending_paint_| when we return NULL frame, in
424 // that case, |current_frame_| could be changed before PutCurrentFrame.
425 if (pending_paint_) {
426 DCHECK_EQ(current_frame_, frame);
427 DCHECK(!pending_paint_with_last_available_);
428 pending_paint_ = false;
429 } else if (pending_paint_with_last_available_) {
430 DCHECK_EQ(last_available_frame_, frame);
431 DCHECK(!pending_paint_);
432 pending_paint_with_last_available_ = false;
433 } else {
434 DCHECK(!frame);
435 }
436
437 // We had cleared the |pending_paint_| flag, there are chances that current
438 // frame is timed-out. We will wake up our main thread to advance the current
439 // frame when this is true.
440 frame_available_.Signal();
441 if (state_ == kFlushingDecoder)
442 return;
443
444 if (state_ == kFlushing) {
445 AttemptFlush_Locked();
446 return;
447 }
448
449 if (state_ == kError || state_ == kStopped) {
450 DoStopOrError_Locked();
451 }
452 } 349 }
453 350
454 VideoRendererBase::~VideoRendererBase() { 351 VideoRendererBase::~VideoRendererBase() {
455 base::AutoLock auto_lock(lock_); 352 base::AutoLock auto_lock(lock_);
456 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; 353 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
457 } 354 }
458 355
459 void VideoRendererBase::FrameReady(VideoDecoder::Status status, 356 void VideoRendererBase::FrameReady(VideoDecoder::Status status,
460 const scoped_refptr<VideoFrame>& frame) { 357 const scoped_refptr<VideoFrame>& frame) {
461 base::AutoLock auto_lock(lock_); 358 base::AutoLock auto_lock(lock_);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 // purposes: 422 // purposes:
526 // 1) Prerolling while paused 423 // 1) Prerolling while paused
527 // 2) Keeps decoding going if video rendering thread starts falling behind 424 // 2) Keeps decoding going if video rendering thread starts falling behind
528 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) { 425 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) {
529 AttemptRead_Locked(); 426 AttemptRead_Locked();
530 return; 427 return;
531 } 428 }
532 429
533 // If we're at capacity or end of stream while prerolling we need to 430 // If we're at capacity or end of stream while prerolling we need to
534 // transition to prerolled. 431 // transition to prerolled.
535 if (state_ == kPrerolling) { 432 if (state_ != kPrerolling)
536 DCHECK(!current_frame_); 433 return;
537 state_ = kPrerolled;
538 434
539 // Because we might remain in the prerolled state for an undetermined amount 435 state_ = kPrerolled;
540 // of time (i.e., we were not playing before we started prerolling), we'll
541 // manually update the current frame and notify the subclass below.
542 if (!ready_frames_.front()->IsEndOfStream())
543 SetCurrentFrameToNextReadyFrame();
544 436
545 // ...and we're done prerolling! 437 // Because we might remain in the prerolled state for an undetermined amount
546 DCHECK(!preroll_cb_.is_null()); 438 // of time (e.g., we seeked while paused), we'll paint the first prerolled
547 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); 439 // frame.
440 if (!ready_frames_.front()->IsEndOfStream())
441 PaintNextReadyFrame_Locked();
548 442
549 base::AutoUnlock ul(lock_); 443 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
550 paint_cb_.Run();
551 }
552 } 444 }
553 445
554 void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) { 446 void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) {
555 // Adjust the incoming frame if its rendering stop time is past the duration 447 // Adjust the incoming frame if its rendering stop time is past the duration
556 // of the video itself. This is typically the last frame of the video and 448 // of the video itself. This is typically the last frame of the video and
557 // occurs if the container specifies a duration that isn't a multiple of the 449 // occurs if the container specifies a duration that isn't a multiple of the
558 // frame rate. Another way for this to happen is for the container to state a 450 // frame rate. Another way for this to happen is for the container to state a
559 // smaller duration than the largest packet timestamp. 451 // smaller duration than the largest packet timestamp.
560 base::TimeDelta duration = get_duration_cb_.Run(); 452 base::TimeDelta duration = get_duration_cb_.Run();
561 if (frame->IsEndOfStream()) { 453 if (frame->IsEndOfStream()) {
562 base::TimeDelta end_timestamp = kNoTimestamp(); 454 base::TimeDelta end_timestamp = kNoTimestamp();
563 if (!ready_frames_.empty()) { 455 if (!ready_frames_.empty()) {
564 end_timestamp = std::min( 456 end_timestamp = std::min(
565 duration, 457 duration,
566 ready_frames_.back()->GetTimestamp() + kMaxLastFrameDuration()); 458 ready_frames_.back()->GetTimestamp() + kMaxLastFrameDuration());
567 } else if (current_frame_) { 459 } else if (last_timestamp_ != kNoTimestamp()) {
568 end_timestamp = 460 end_timestamp =
569 std::min(duration, 461 std::min(duration, last_timestamp_ + kMaxLastFrameDuration());
570 current_frame_->GetTimestamp() + kMaxLastFrameDuration());
571 } 462 }
572 frame->SetTimestamp(end_timestamp); 463 frame->SetTimestamp(end_timestamp);
573 } else if (frame->GetTimestamp() > duration) { 464 } else if (frame->GetTimestamp() > duration) {
574 frame->SetTimestamp(duration); 465 frame->SetTimestamp(duration);
575 } 466 }
576 467
577 ready_frames_.push_back(frame); 468 ready_frames_.push_back(frame);
578 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames); 469 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames);
579 470
580 base::TimeDelta max_clock_time = 471 base::TimeDelta max_clock_time =
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 AttemptFlush_Locked(); 520 AttemptFlush_Locked();
630 } 521 }
631 522
632 void VideoRendererBase::AttemptFlush_Locked() { 523 void VideoRendererBase::AttemptFlush_Locked() {
633 lock_.AssertAcquired(); 524 lock_.AssertAcquired();
634 DCHECK_EQ(kFlushing, state_); 525 DCHECK_EQ(kFlushing, state_);
635 526
636 prerolling_delayed_frame_ = NULL; 527 prerolling_delayed_frame_ = NULL;
637 ready_frames_.clear(); 528 ready_frames_.clear();
638 529
639 if (!pending_paint_ && !pending_read_) { 530 if (pending_read_)
640 state_ = kFlushed; 531 return;
641 current_frame_ = NULL; 532
642 base::ResetAndReturn(&flush_cb_).Run(); 533 state_ = kFlushed;
643 } 534 last_timestamp_ = kNoTimestamp();
535 base::ResetAndReturn(&flush_cb_).Run();
644 } 536 }
645 537
646 base::TimeDelta VideoRendererBase::CalculateSleepDuration( 538 base::TimeDelta VideoRendererBase::CalculateSleepDuration(
647 const scoped_refptr<VideoFrame>& next_frame, 539 const scoped_refptr<VideoFrame>& next_frame,
648 float playback_rate) { 540 float playback_rate) {
649 // Determine the current and next presentation timestamps. 541 // Determine the current and next presentation timestamps.
650 base::TimeDelta now = get_time_cb_.Run(); 542 base::TimeDelta now = get_time_cb_.Run();
651 base::TimeDelta next_pts = next_frame->GetTimestamp(); 543 base::TimeDelta next_pts = next_frame->GetTimestamp();
652 544
653 // Scale our sleep based on the playback rate. 545 // Scale our sleep based on the playback rate.
654 base::TimeDelta sleep = next_pts - now; 546 base::TimeDelta sleep = next_pts - now;
655 return base::TimeDelta::FromMicroseconds( 547 return base::TimeDelta::FromMicroseconds(
656 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); 548 static_cast<int64>(sleep.InMicroseconds() / playback_rate));
657 } 549 }
658 550
659 void VideoRendererBase::DoStopOrError_Locked() { 551 void VideoRendererBase::DoStopOrError_Locked() {
660 DCHECK(!pending_paint_);
661 DCHECK(!pending_paint_with_last_available_);
662 lock_.AssertAcquired(); 552 lock_.AssertAcquired();
663 current_frame_ = NULL; 553 last_timestamp_ = kNoTimestamp();
664 last_available_frame_ = NULL;
665 ready_frames_.clear(); 554 ready_frames_.clear();
666 } 555 }
667 556
668 int VideoRendererBase::NumFrames_Locked() const { 557 int VideoRendererBase::NumFrames_Locked() const {
669 lock_.AssertAcquired(); 558 lock_.AssertAcquired();
670 int outstanding_frames = 559 return ready_frames_.size();
671 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) +
672 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0);
673 return ready_frames_.size() + outstanding_frames;
674 } 560 }
675 561
676 } // namespace media 562 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/video_renderer_base.h ('k') | media/filters/video_renderer_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698