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

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
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());
86 if (state_ == kUninitialized || state_ == kStopped) { 85 if (state_ == kUninitialized || state_ == kStopped) {
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 I'm pretty sure these checks should be done under
scherkus (not reviewing) 2013/02/01 22:45:25 Done.
87 callback.Run(); 86 callback.Run();
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 message_loop_->PostTask(FROM_HERE, callback) ?
scherkus (not reviewing) 2013/02/01 22:45:25 I'm going to hold off on cleaning up VRB threading
88 return; 87 return;
89 } 88 }
90 89
91 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; 90 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle;
92 { 91 {
93 base::AutoLock auto_lock(lock_); 92 base::AutoLock auto_lock(lock_);
94 state_ = kStopped; 93 state_ = kStopped;
95 94
96 statistics_cb_.Reset(); 95 statistics_cb_.Reset();
97 max_time_cb_.Reset(); 96 max_time_cb_.Reset();
98 if (!pending_paint_ && !pending_paint_with_last_available_) 97 DoStopOrError_Locked();
99 DoStopOrError_Locked();
100 98
101 // Clean up our thread if present. 99 // Clean up our thread if present.
102 if (thread_ != base::kNullThreadHandle) { 100 if (thread_ != base::kNullThreadHandle) {
103 // Signal the thread since it's possible to get stopped with the video 101 // Signal the thread since it's possible to get stopped with the video
104 // thread waiting for a read to complete. 102 // thread waiting for a read to complete.
105 frame_available_.Signal(); 103 frame_available_.Signal();
106 thread_to_join = thread_; 104 thread_to_join = thread_;
107 thread_ = base::kNullThreadHandle; 105 thread_ = base::kNullThreadHandle;
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 nit: std::swap(thread_to_join, thread_)
scherkus (not reviewing) 2013/02/01 22:45:25 Done.
108 } 106 }
109 } 107 }
110 if (thread_to_join != base::kNullThreadHandle) 108 if (thread_to_join != base::kNullThreadHandle)
111 base::PlatformThread::Join(thread_to_join); 109 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 }
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 frame_available_.TimedWait(kIdleTimeDelta); 272 frame_available_.TimedWait(kIdleTimeDelta);
275 continue; 273 continue;
276 } 274 }
277 275
278 // Remain idle until we have the next frame ready for rendering. 276 // Remain idle until we have the next frame ready for rendering.
279 if (ready_frames_.empty()) { 277 if (ready_frames_.empty()) {
280 frame_available_.TimedWait(kIdleTimeDelta); 278 frame_available_.TimedWait(kIdleTimeDelta);
281 continue; 279 continue;
282 } 280 }
283 281
284 // Remain idle until we've initialized |current_frame_| via prerolling. 282 // This can happen if our preroll only contains end of stream frames.
285 if (!current_frame_) { 283 if (ready_frames_.front()->IsEndOfStream()) {
286 // This can happen if our preroll only contains end of stream frames. 284 state_ = kEnded;
287 if (ready_frames_.front()->IsEndOfStream()) { 285 ended_cb_.Run();
288 state_ = kEnded; 286 ready_frames_.clear();
289 ended_cb_.Run();
290 ready_frames_.clear();
291 287
292 // No need to sleep here as we idle when |state_ != kPlaying|. 288 // No need to sleep here as we idle when |state_ != kPlaying|.
293 continue;
294 }
295
296 frame_available_.TimedWait(kIdleTimeDelta);
297 continue; 289 continue;
298 } 290 }
299 291
300 // Calculate how long until we should advance the frame, which is 292 // Calculate how long until we should advance the frame, which is
301 // typically negative but for playback rates < 1.0f may be long enough 293 // typically negative but for playback rates < 1.0f may be long enough
302 // that it makes more sense to idle and check again. 294 // that it makes more sense to idle and check again.
303 base::TimeDelta remaining_time = 295 base::TimeDelta remaining_time =
304 CalculateSleepDuration(ready_frames_.front(), playback_rate_); 296 CalculateSleepDuration(ready_frames_.front(), playback_rate_);
305 297
306 // Sleep up to a maximum of our idle time until we're within the time to 298 // Sleep up to a maximum of our idle time until we're within the time to
307 // render the next frame. 299 // render the next frame.
308 if (remaining_time.InMicroseconds() > 0) { 300 if (remaining_time.InMicroseconds() > 0) {
309 remaining_time = std::min(remaining_time, kIdleTimeDelta); 301 remaining_time = std::min(remaining_time, kIdleTimeDelta);
310 frame_available_.TimedWait(remaining_time); 302 frame_available_.TimedWait(remaining_time);
311 continue; 303 continue;
312 } 304 }
313 305
314
315 // We're almost there!
316 //
317 // At this point we've rendered |current_frame_| for the proper amount
318 // of time and also have the next frame that ready for rendering.
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 }
334
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. 306 // Congratulations! You've made it past the video frame timing gauntlet.
368 // 307 //
369 // We can now safely update the current frame, request another frame, and 308 // 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. 309 // rendering.
371 DCHECK(!pending_paint_); 310 PaintWithNextReadyFrame();
372 DCHECK(!ready_frames_.empty());
373 SetCurrentFrameToNextReadyFrame();
374 message_loop_->PostTask(FROM_HERE, base::Bind( 311 message_loop_->PostTask(FROM_HERE, base::Bind(
375 &VideoRendererBase::AttemptRead, this)); 312 &VideoRendererBase::AttemptRead, this));
376
377 base::AutoUnlock auto_unlock(lock_);
378 paint_cb_.Run();
379 } 313 }
380 } 314 }
381 315
382 void VideoRendererBase::SetCurrentFrameToNextReadyFrame() { 316 void VideoRendererBase::PaintWithNextReadyFrame() {
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 nit: Add _Locked() & corresponding assert since th
scherkus (not reviewing) 2013/02/01 22:45:25 Done.
383 current_frame_ = ready_frames_.front(); 317 scoped_refptr<VideoFrame> next_frame = ready_frames_.front();
384 ready_frames_.pop_front(); 318 ready_frames_.pop_front();
385 319
386 // Notify the pipeline of natural_size() changes. 320 // Notify the pipeline of natural_size() changes.
387 const gfx::Size& natural_size = current_frame_->natural_size(); 321 const gfx::Size& natural_size = next_frame->natural_size();
388 if (natural_size != last_natural_size_) { 322 if (natural_size != last_natural_size_) {
389 size_changed_cb_.Run(natural_size); 323 size_changed_cb_.Run(natural_size);
390 last_natural_size_ = natural_size; 324 last_natural_size_ = natural_size;
391 } 325 }
392 }
393 326
394 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { 327 paint_cb_.Run(next_frame);
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 This calls the callback under lock now. Are you su
scherkus (not reviewing) 2013/02/01 22:45:25 Yes. Previously it was terrifying because the most
395 base::AutoLock auto_lock(lock_);
396 DCHECK(!pending_paint_ && !pending_paint_with_last_available_);
397
398 if ((!current_frame_ || current_frame_->IsEndOfStream()) &&
399 (!last_available_frame_ || last_available_frame_->IsEndOfStream())) {
400 *frame_out = NULL;
401 return;
402 }
403
404 // We should have initialized and have the current frame.
405 DCHECK_NE(state_, kUninitialized);
406 DCHECK_NE(state_, kStopped);
407 DCHECK_NE(state_, kError);
408
409 if (current_frame_) {
410 *frame_out = current_frame_;
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 } 328 }
453 329
454 VideoRendererBase::~VideoRendererBase() { 330 VideoRendererBase::~VideoRendererBase() {
455 base::AutoLock auto_lock(lock_); 331 base::AutoLock auto_lock(lock_);
456 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; 332 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
457 } 333 }
458 334
459 void VideoRendererBase::FrameReady(VideoDecoder::Status status, 335 void VideoRendererBase::FrameReady(VideoDecoder::Status status,
460 const scoped_refptr<VideoFrame>& frame) { 336 const scoped_refptr<VideoFrame>& frame) {
461 base::AutoLock auto_lock(lock_); 337 base::AutoLock auto_lock(lock_);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 // purposes: 401 // purposes:
526 // 1) Prerolling while paused 402 // 1) Prerolling while paused
527 // 2) Keeps decoding going if video rendering thread starts falling behind 403 // 2) Keeps decoding going if video rendering thread starts falling behind
528 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) { 404 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) {
529 AttemptRead_Locked(); 405 AttemptRead_Locked();
530 return; 406 return;
531 } 407 }
532 408
533 // If we're at capacity or end of stream while prerolling we need to 409 // If we're at capacity or end of stream while prerolling we need to
534 // transition to prerolled. 410 // transition to prerolled.
535 if (state_ == kPrerolling) { 411 if (state_ == kPrerolling) {
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 nit: reverse check and unindent?
scherkus (not reviewing) 2013/02/01 22:45:25 Done.
536 DCHECK(!current_frame_);
537 state_ = kPrerolled; 412 state_ = kPrerolled;
538 413
539 // Because we might remain in the prerolled state for an undetermined amount 414 // Because we might remain in the prerolled state for an undetermined amount
540 // of time (i.e., we were not playing before we started prerolling), we'll 415 // 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. 416 // manually update the current frame and notify the subclass below.
542 if (!ready_frames_.front()->IsEndOfStream()) 417 if (!ready_frames_.front()->IsEndOfStream())
543 SetCurrentFrameToNextReadyFrame(); 418 PaintWithNextReadyFrame();
544 419
545 // ...and we're done prerolling! 420 // ...and we're done prerolling!
546 DCHECK(!preroll_cb_.is_null());
547 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); 421 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
548 422
423 #if 0
424 // XXX do we still need this!?
scherkus (not reviewing) 2013/01/31 17:54:05 PWNRF() fires the paint_cb_ ... I suppose this mig
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 Not sure. What did we use to paint in the case whe
scherkus (not reviewing) 2013/02/01 22:45:25 current_frame_ would have been null, so SkCanvasVi
549 base::AutoUnlock ul(lock_); 425 base::AutoUnlock ul(lock_);
550 paint_cb_.Run(); 426 paint_cb_.Run();
427 #endif
551 } 428 }
552 } 429 }
553 430
554 void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) { 431 void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) {
555 // Adjust the incoming frame if its rendering stop time is past the duration 432 // 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 433 // 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 434 // 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 435 // frame rate. Another way for this to happen is for the container to state a
559 // smaller duration than the largest packet timestamp. 436 // smaller duration than the largest packet timestamp.
560 base::TimeDelta duration = get_duration_cb_.Run(); 437 base::TimeDelta duration = get_duration_cb_.Run();
561 if (frame->IsEndOfStream()) { 438 if (frame->IsEndOfStream()) {
562 base::TimeDelta end_timestamp = kNoTimestamp(); 439 base::TimeDelta end_timestamp = kNoTimestamp();
563 if (!ready_frames_.empty()) { 440 if (!ready_frames_.empty()) {
564 end_timestamp = std::min( 441 end_timestamp = std::min(
565 duration, 442 duration,
566 ready_frames_.back()->GetTimestamp() + kMaxLastFrameDuration()); 443 ready_frames_.back()->GetTimestamp() + kMaxLastFrameDuration());
567 } else if (current_frame_) { 444 } else if (last_timestamp_ != kNoTimestamp()) {
568 end_timestamp = 445 end_timestamp =
569 std::min(duration, 446 std::min(duration, last_timestamp_ + kMaxLastFrameDuration());
570 current_frame_->GetTimestamp() + kMaxLastFrameDuration());
571 } 447 }
572 frame->SetTimestamp(end_timestamp); 448 frame->SetTimestamp(end_timestamp);
573 } else if (frame->GetTimestamp() > duration) { 449 } else if (frame->GetTimestamp() > duration) {
574 frame->SetTimestamp(duration); 450 frame->SetTimestamp(duration);
575 } 451 }
576 452
577 ready_frames_.push_back(frame); 453 ready_frames_.push_back(frame);
578 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames); 454 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames);
579 455
580 base::TimeDelta max_clock_time = 456 base::TimeDelta max_clock_time =
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 AttemptFlush_Locked(); 505 AttemptFlush_Locked();
630 } 506 }
631 507
632 void VideoRendererBase::AttemptFlush_Locked() { 508 void VideoRendererBase::AttemptFlush_Locked() {
633 lock_.AssertAcquired(); 509 lock_.AssertAcquired();
634 DCHECK_EQ(kFlushing, state_); 510 DCHECK_EQ(kFlushing, state_);
635 511
636 prerolling_delayed_frame_ = NULL; 512 prerolling_delayed_frame_ = NULL;
637 ready_frames_.clear(); 513 ready_frames_.clear();
638 514
639 if (!pending_paint_ && !pending_read_) { 515 if (!pending_read_) {
640 state_ = kFlushed; 516 state_ = kFlushed;
641 current_frame_ = NULL; 517 last_timestamp_ = kNoTimestamp();
642 base::ResetAndReturn(&flush_cb_).Run(); 518 base::ResetAndReturn(&flush_cb_).Run();
643 } 519 }
644 } 520 }
645 521
646 base::TimeDelta VideoRendererBase::CalculateSleepDuration( 522 base::TimeDelta VideoRendererBase::CalculateSleepDuration(
647 const scoped_refptr<VideoFrame>& next_frame, 523 const scoped_refptr<VideoFrame>& next_frame,
648 float playback_rate) { 524 float playback_rate) {
649 // Determine the current and next presentation timestamps. 525 // Determine the current and next presentation timestamps.
650 base::TimeDelta now = get_time_cb_.Run(); 526 base::TimeDelta now = get_time_cb_.Run();
651 base::TimeDelta next_pts = next_frame->GetTimestamp(); 527 base::TimeDelta next_pts = next_frame->GetTimestamp();
652 528
653 // Scale our sleep based on the playback rate. 529 // Scale our sleep based on the playback rate.
654 base::TimeDelta sleep = next_pts - now; 530 base::TimeDelta sleep = next_pts - now;
655 return base::TimeDelta::FromMicroseconds( 531 return base::TimeDelta::FromMicroseconds(
656 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); 532 static_cast<int64>(sleep.InMicroseconds() / playback_rate));
657 } 533 }
658 534
659 void VideoRendererBase::DoStopOrError_Locked() { 535 void VideoRendererBase::DoStopOrError_Locked() {
660 DCHECK(!pending_paint_);
661 DCHECK(!pending_paint_with_last_available_);
662 lock_.AssertAcquired(); 536 lock_.AssertAcquired();
663 current_frame_ = NULL; 537 last_timestamp_ = kNoTimestamp();
664 last_available_frame_ = NULL;
665 ready_frames_.clear(); 538 ready_frames_.clear();
666 } 539 }
667 540
668 int VideoRendererBase::NumFrames_Locked() const { 541 int VideoRendererBase::NumFrames_Locked() const {
669 lock_.AssertAcquired(); 542 lock_.AssertAcquired();
670 int outstanding_frames = 543 return ready_frames_.size();
671 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) +
672 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0);
acolwell GONE FROM CHROMIUM 2013/02/01 00:24:34 o.O I'm not going to miss this.
673 return ready_frames_.size() + outstanding_frames;
674 } 544 }
675 545
676 } // namespace media 546 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698