Index: media/filters/video_renderer_base.cc |
diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc |
index 30b299593b1c956b2ce54d1c86abd18d02114572..51c51b03c7a018d1dd8440ccaa580261124e3f8b 100644 |
--- a/media/filters/video_renderer_base.cc |
+++ b/media/filters/video_renderer_base.cc |
@@ -54,9 +54,13 @@ void VideoRendererBase::Flush(const base::Closure& callback) { |
base::AutoLock auto_lock(lock_); |
DCHECK_EQ(state_, kPaused); |
flush_cb_ = callback; |
- state_ = kFlushing; |
+ state_ = kFlushingDecoder; |
- AttemptFlush_Locked(); |
+ // We must unlock here because the callback might run within the Flush() |
+ // call. |
+ // TODO: Remove this line when fixing http://crbug.com/125020 |
+ base::AutoUnlock auto_unlock(lock_); |
+ decoder_->Flush(base::Bind(&VideoRendererBase::OnDecoderFlushDone, this)); |
} |
void VideoRendererBase::Stop(const base::Closure& callback) { |
@@ -342,9 +346,15 @@ void VideoRendererBase::PutCurrentFrame(scoped_refptr<VideoFrame> frame) { |
// frame is timed-out. We will wake up our main thread to advance the current |
// frame when this is true. |
frame_available_.Signal(); |
+ if (state_ == kFlushingDecoder) |
+ return; |
+ |
if (state_ == kFlushing) { |
AttemptFlush_Locked(); |
- } else if (state_ == kError || state_ == kStopped) { |
+ return; |
+ } |
+ |
+ if (state_ == kError || state_ == kStopped) { |
DoStopOrError_Locked(); |
} |
} |
@@ -358,7 +368,8 @@ void VideoRendererBase::FrameReady(scoped_refptr<VideoFrame> frame) { |
// Already-queued Decoder ReadCB's can fire after various state transitions |
// have happened; in that case just drop those frames immediately. |
- if (state_ == kStopped || state_ == kError || state_ == kFlushed) |
+ if (state_ == kStopped || state_ == kError || state_ == kFlushed || |
+ state_ == kFlushingDecoder) |
return; |
if (state_ == kFlushing) { |
@@ -446,14 +457,25 @@ void VideoRendererBase::AttemptRead_Locked() { |
if (pending_read_ || |
NumFrames_Locked() == limits::kMaxVideoFrames || |
- (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream())) { |
- return; |
- } |
+ (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream()) || |
+ state_ == kFlushingDecoder || |
+ state_ == kFlushing) { |
+ return; |
+ } |
pending_read_ = true; |
decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this)); |
} |
+void VideoRendererBase::OnDecoderFlushDone() { |
+ base::AutoLock auto_lock(lock_); |
+ DCHECK_EQ(kFlushingDecoder, state_); |
+ DCHECK(!pending_read_); |
+ |
+ state_ = kFlushing; |
+ AttemptFlush_Locked(); |
+} |
+ |
void VideoRendererBase::AttemptFlush_Locked() { |
lock_.AssertAcquired(); |
DCHECK_EQ(kFlushing, state_); |
@@ -464,10 +486,7 @@ void VideoRendererBase::AttemptFlush_Locked() { |
if (!pending_paint_ && !pending_read_) { |
state_ = kFlushed; |
current_frame_ = NULL; |
- |
- base::Closure flush_cb = flush_cb_; |
- flush_cb_.Reset(); |
- decoder_->Flush(flush_cb); |
+ base::ResetAndReturn(&flush_cb_).Run(); |
} |
} |