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

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

Issue 10173012: Fix VideoRendererBase to allow the decoder to be flushed with a pending read. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/callback.h" 6 #include "base/callback.h"
7 #include "base/callback_helpers.h" 7 #include "base/callback_helpers.h"
8 #include "base/threading/platform_thread.h" 8 #include "base/threading/platform_thread.h"
9 #include "media/base/buffers.h" 9 #include "media/base/buffers.h"
10 #include "media/base/filter_host.h" 10 #include "media/base/filter_host.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 base::AutoLock auto_lock(lock_); 47 base::AutoLock auto_lock(lock_);
48 DCHECK(state_ != kUninitialized || state_ == kError); 48 DCHECK(state_ != kUninitialized || state_ == kError);
49 state_ = kPaused; 49 state_ = kPaused;
50 callback.Run(); 50 callback.Run();
51 } 51 }
52 52
53 void VideoRendererBase::Flush(const base::Closure& callback) { 53 void VideoRendererBase::Flush(const base::Closure& callback) {
54 base::AutoLock auto_lock(lock_); 54 base::AutoLock auto_lock(lock_);
55 DCHECK_EQ(state_, kPaused); 55 DCHECK_EQ(state_, kPaused);
56 flush_cb_ = callback; 56 flush_cb_ = callback;
57 state_ = kFlushing; 57 state_ = kFlushingDecoder;
58 58
59 AttemptFlush_Locked(); 59 // We must unlock here because the callback might run within the Flush()
60 // call.
scherkus (not reviewing) 2012/04/25 03:33:58 should we have semantics similar to VideoDecoder::
acolwell GONE FROM CHROMIUM 2012/04/25 17:41:44 Yes. I think that is a good idea. I created a bug
61 base::AutoUnlock auto_unlock(lock_);
62 decoder_->Flush(base::Bind(&VideoRendererBase::OnDecoderFlushDone, this));
60 } 63 }
61 64
62 void VideoRendererBase::Stop(const base::Closure& callback) { 65 void VideoRendererBase::Stop(const base::Closure& callback) {
63 if (state_ == kStopped) { 66 if (state_ == kStopped) {
64 callback.Run(); 67 callback.Run();
65 return; 68 return;
66 } 69 }
67 70
68 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; 71 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle;
69 { 72 {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 DCHECK(!pending_paint_); 338 DCHECK(!pending_paint_);
336 pending_paint_with_last_available_ = false; 339 pending_paint_with_last_available_ = false;
337 } else { 340 } else {
338 DCHECK(!frame); 341 DCHECK(!frame);
339 } 342 }
340 343
341 // We had cleared the |pending_paint_| flag, there are chances that current 344 // We had cleared the |pending_paint_| flag, there are chances that current
342 // frame is timed-out. We will wake up our main thread to advance the current 345 // frame is timed-out. We will wake up our main thread to advance the current
343 // frame when this is true. 346 // frame when this is true.
344 frame_available_.Signal(); 347 frame_available_.Signal();
348 if (state_ == kFlushingDecoder)
349 return;
350
345 if (state_ == kFlushing) { 351 if (state_ == kFlushing) {
346 AttemptFlush_Locked(); 352 AttemptFlush_Locked();
347 } else if (state_ == kError || state_ == kStopped) { 353 return;
354 }
355
356 if (state_ == kError || state_ == kStopped) {
348 DoStopOrError_Locked(); 357 DoStopOrError_Locked();
349 } 358 }
350 } 359 }
351 360
352 void VideoRendererBase::FrameReady(scoped_refptr<VideoFrame> frame) { 361 void VideoRendererBase::FrameReady(scoped_refptr<VideoFrame> frame) {
353 base::AutoLock auto_lock(lock_); 362 base::AutoLock auto_lock(lock_);
354 DCHECK_NE(state_, kUninitialized); 363 DCHECK_NE(state_, kUninitialized);
355 364
356 CHECK(pending_read_); 365 CHECK(pending_read_);
357 pending_read_ = false; 366 pending_read_ = false;
358 367
359 // Already-queued Decoder ReadCB's can fire after various state transitions 368 // Already-queued Decoder ReadCB's can fire after various state transitions
360 // have happened; in that case just drop those frames immediately. 369 // have happened; in that case just drop those frames immediately.
361 if (state_ == kStopped || state_ == kError || state_ == kFlushed) 370 if (state_ == kStopped || state_ == kError || state_ == kFlushed ||
371 state_ == kFlushingDecoder)
362 return; 372 return;
363 373
364 if (state_ == kFlushing) { 374 if (state_ == kFlushing) {
365 AttemptFlush_Locked(); 375 AttemptFlush_Locked();
366 return; 376 return;
367 } 377 }
368 378
369 if (!frame) { 379 if (!frame) {
370 if (state_ != kSeeking) 380 if (state_ != kSeeking)
371 return; 381 return;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 paint_cb_.Run(); 449 paint_cb_.Run();
440 } 450 }
441 } 451 }
442 452
443 void VideoRendererBase::AttemptRead_Locked() { 453 void VideoRendererBase::AttemptRead_Locked() {
444 lock_.AssertAcquired(); 454 lock_.AssertAcquired();
445 DCHECK_NE(kEnded, state_); 455 DCHECK_NE(kEnded, state_);
446 456
447 if (pending_read_ || 457 if (pending_read_ ||
448 NumFrames_Locked() == limits::kMaxVideoFrames || 458 NumFrames_Locked() == limits::kMaxVideoFrames ||
449 (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream())) { 459 (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream()) ||
450 return; 460 state_ == kFlushingDecoder ||
451 } 461 state_ == kFlushing) {
462 return;
463 }
452 464
453 pending_read_ = true; 465 pending_read_ = true;
454 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this)); 466 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this));
455 } 467 }
456 468
469 void VideoRendererBase::OnDecoderFlushDone() {
470 base::AutoLock auto_lock(lock_);
471 DCHECK_EQ(kFlushingDecoder, state_);
472 DCHECK(!pending_read_);
473
474 state_ = kFlushing;
475 AttemptFlush_Locked();
476 }
477
457 void VideoRendererBase::AttemptFlush_Locked() { 478 void VideoRendererBase::AttemptFlush_Locked() {
458 lock_.AssertAcquired(); 479 lock_.AssertAcquired();
459 DCHECK_EQ(kFlushing, state_); 480 DCHECK_EQ(kFlushing, state_);
460 481
461 // Get rid of any ready frames. 482 // Get rid of any ready frames.
462 ready_frames_.clear(); 483 ready_frames_.clear();
463 484
464 if (!pending_paint_ && !pending_read_) { 485 if (!pending_paint_ && !pending_read_) {
465 state_ = kFlushed; 486 state_ = kFlushed;
466 current_frame_ = NULL; 487 current_frame_ = NULL;
467 488 base::ResetAndReturn(&flush_cb_).Run();
468 base::Closure flush_cb = flush_cb_;
469 flush_cb_.Reset();
470 decoder_->Flush(flush_cb);
471 } 489 }
472 } 490 }
473 491
474 base::TimeDelta VideoRendererBase::CalculateSleepDuration( 492 base::TimeDelta VideoRendererBase::CalculateSleepDuration(
475 const scoped_refptr<VideoFrame>& next_frame, 493 const scoped_refptr<VideoFrame>& next_frame,
476 float playback_rate) { 494 float playback_rate) {
477 // Determine the current and next presentation timestamps. 495 // Determine the current and next presentation timestamps.
478 base::TimeDelta now = host()->GetTime(); 496 base::TimeDelta now = host()->GetTime();
479 base::TimeDelta this_pts = current_frame_->GetTimestamp(); 497 base::TimeDelta this_pts = current_frame_->GetTimestamp();
480 base::TimeDelta next_pts; 498 base::TimeDelta next_pts;
(...skipping 20 matching lines...) Expand all
501 519
502 int VideoRendererBase::NumFrames_Locked() const { 520 int VideoRendererBase::NumFrames_Locked() const {
503 lock_.AssertAcquired(); 521 lock_.AssertAcquired();
504 int outstanding_frames = 522 int outstanding_frames =
505 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + 523 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) +
506 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); 524 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0);
507 return ready_frames_.size() + outstanding_frames; 525 return ready_frames_.size() + outstanding_frames;
508 } 526 }
509 527
510 } // namespace media 528 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698