| Index: media/filters/video_renderer_base.cc
|
| diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc
|
| index 00cf9dc9559566a837787c14f93d9ba11449dab9..166c99289deaaaaf3d9579e8c3c50edbed8df1c0 100644
|
| --- a/media/filters/video_renderer_base.cc
|
| +++ b/media/filters/video_renderer_base.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "base/callback.h"
|
| #include "media/base/buffers.h"
|
| +#include "media/base/callback.h"
|
| #include "media/base/filter_host.h"
|
| #include "media/base/video_frame.h"
|
| #include "media/filters/video_renderer_base.h"
|
| @@ -90,7 +91,7 @@ bool VideoRendererBase::ParseMediaFormat(
|
|
|
| void VideoRendererBase::Play(FilterCallback* callback) {
|
| AutoLock auto_lock(lock_);
|
| - DCHECK_EQ(kPaused, state_);
|
| + DCHECK(kPaused == state_ || kFlushing == state_);
|
| scoped_ptr<FilterCallback> c(callback);
|
| state_ = kPlaying;
|
| callback->Run();
|
| @@ -99,17 +100,24 @@ void VideoRendererBase::Play(FilterCallback* callback) {
|
| void VideoRendererBase::Pause(FilterCallback* callback) {
|
| AutoLock auto_lock(lock_);
|
| DCHECK(state_ == kPlaying || state_ == kEnded);
|
| - pause_callback_.reset(callback);
|
| + AutoCallbackRunner done_runner(callback);
|
| state_ = kPaused;
|
| +}
|
| +
|
| +void VideoRendererBase::Flush(FilterCallback* callback) {
|
| + DCHECK(state_ == kPaused);
|
| +
|
| + AutoLock auto_lock(lock_);
|
| + flush_callback_.reset(callback);
|
| + state_ = kFlushing;
|
|
|
| - // TODO(jiesun): currently we use Pause() to fulfill Flush().
|
| // Filter is considered paused when we've finished all pending reads, which
|
| // implies all buffers are returned to owner in Decoder/Renderer. Renderer
|
| // is considered paused with one more contingency that |pending_paint_| is
|
| // false, such that no client of us is holding any reference to VideoFrame.
|
| if (pending_reads_ == 0 && pending_paint_ == false) {
|
| - pause_callback_->Run();
|
| - pause_callback_.reset();
|
| + flush_callback_->Run();
|
| + flush_callback_.reset();
|
| FlushBuffers();
|
| }
|
| }
|
| @@ -147,7 +155,7 @@ void VideoRendererBase::SetPlaybackRate(float playback_rate) {
|
|
|
| void VideoRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) {
|
| AutoLock auto_lock(lock_);
|
| - DCHECK_EQ(kPaused, state_);
|
| + DCHECK(kPaused == state_ || kFlushing == state_);
|
| DCHECK_EQ(0u, pending_reads_) << "Pending reads should have completed";
|
| state_ = kSeeking;
|
| seek_callback_.reset(callback);
|
| @@ -242,8 +250,7 @@ void VideoRendererBase::ThreadMain() {
|
| if (state_ == kStopped)
|
| return;
|
|
|
| - if (state_ == kPaused || state_ == kSeeking || state_ == kEnded ||
|
| - playback_rate_ == 0) {
|
| + if (state_ != kPlaying || playback_rate_ == 0) {
|
| remaining_time = kIdleTimeDelta;
|
| } else if (frames_queue_ready_.empty() ||
|
| frames_queue_ready_.front()->IsEndOfStream()) {
|
| @@ -350,7 +357,7 @@ void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) {
|
|
|
| // We should have initialized and have the current frame.
|
| DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying ||
|
| - state_ == kEnded);
|
| + state_ == kFlushing || state_ == kEnded);
|
| *frame_out = current_frame_;
|
| pending_paint_ = true;
|
| }
|
| @@ -368,11 +375,11 @@ 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_ == kPaused && pending_reads_ == 0 && pause_callback_.get()) {
|
| + if (state_ == kFlushing && pending_reads_ == 0 && flush_callback_.get()) {
|
| // No more pending reads! We're now officially "paused".
|
| FlushBuffers();
|
| - pause_callback_->Run();
|
| - pause_callback_.reset();
|
| + flush_callback_->Run();
|
| + flush_callback_.reset();
|
| }
|
| }
|
|
|
| @@ -387,7 +394,7 @@ void VideoRendererBase::OnFillBufferDone(scoped_refptr<VideoFrame> frame) {
|
| }
|
|
|
| DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying ||
|
| - state_ == kEnded);
|
| + state_ == kFlushing || state_ == kEnded);
|
| DCHECK_GT(pending_reads_, 0u);
|
| --pending_reads_;
|
|
|
| @@ -405,7 +412,7 @@ void VideoRendererBase::OnFillBufferDone(scoped_refptr<VideoFrame> frame) {
|
| // Check for our preroll complete condition.
|
| if (state_ == kSeeking) {
|
| DCHECK(seek_callback_.get());
|
| - if (frames_queue_ready_.size() == kMaxFrames) {
|
| + if (frames_queue_ready_.size() == kMaxFrames || frame->IsEndOfStream()) {
|
| // We're paused, so make sure we update |current_frame_| to represent
|
| // our new location.
|
| state_ = kPaused;
|
| @@ -413,18 +420,22 @@ void VideoRendererBase::OnFillBufferDone(scoped_refptr<VideoFrame> frame) {
|
| // Because we might remain paused (i.e., we were not playing before we
|
| // received a seek), we can't rely on ThreadMain() to notify the subclass
|
| // the frame has been updated.
|
| - current_frame_ = frames_queue_ready_.front();
|
| - frames_queue_ready_.pop_front();
|
| + scoped_refptr<VideoFrame> first_frame;
|
| + first_frame = frames_queue_ready_.front();
|
| + if (!first_frame->IsEndOfStream()) {
|
| + frames_queue_ready_.pop_front();
|
| + current_frame_ = first_frame;
|
| + }
|
| OnFrameAvailable();
|
|
|
| seek_callback_->Run();
|
| seek_callback_.reset();
|
| }
|
| - } else if (state_ == kPaused && pending_reads_ == 0 && !pending_paint_) {
|
| + } else if (state_ == kFlushing && pending_reads_ == 0 && !pending_paint_) {
|
| // No more pending reads! We're now officially "paused".
|
| - if (pause_callback_.get()) {
|
| - pause_callback_->Run();
|
| - pause_callback_.reset();
|
| + if (flush_callback_.get()) {
|
| + flush_callback_->Run();
|
| + flush_callback_.reset();
|
| }
|
| }
|
| }
|
| @@ -450,7 +461,7 @@ void VideoRendererBase::FlushBuffers() {
|
| // We should never put EOF frame into "done queue".
|
| while (!frames_queue_ready_.empty()) {
|
| scoped_refptr<VideoFrame> video_frame = frames_queue_ready_.front();
|
| - if (video_frame->IsEndOfStream()) {
|
| + if (!video_frame->IsEndOfStream()) {
|
| frames_queue_done_.push_back(video_frame);
|
| }
|
| frames_queue_ready_.pop_front();
|
|
|