Chromium Code Reviews| Index: media/filters/video_renderer_base.cc |
| diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc |
| index 5a17940771120c543902274a13cf15f3011e43c5..178cbc7ccdb8f5c7ca32ef89e79e1559c7d44a6b 100644 |
| --- a/media/filters/video_renderer_base.cc |
| +++ b/media/filters/video_renderer_base.cc |
| @@ -25,7 +25,7 @@ base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { |
| VideoRendererBase::VideoRendererBase( |
| const scoped_refptr<base::MessageLoopProxy>& message_loop, |
| const SetDecryptorReadyCB& set_decryptor_ready_cb, |
| - const base::Closure& paint_cb, |
| + const PaintCB& paint_cb, |
| const SetOpaqueCB& set_opaque_cb, |
| bool drop_frames) |
| : message_loop_(message_loop), |
| @@ -34,12 +34,11 @@ VideoRendererBase::VideoRendererBase( |
| state_(kUninitialized), |
| thread_(base::kNullThreadHandle), |
| pending_read_(false), |
| - pending_paint_(false), |
| - pending_paint_with_last_available_(false), |
| drop_frames_(drop_frames), |
| playback_rate_(0), |
| paint_cb_(paint_cb), |
| - set_opaque_cb_(set_opaque_cb) { |
| + set_opaque_cb_(set_opaque_cb), |
| + last_timestamp_(kNoTimestamp()) { |
| DCHECK(!paint_cb_.is_null()); |
| } |
| @@ -95,8 +94,7 @@ void VideoRendererBase::Stop(const base::Closure& callback) { |
| statistics_cb_.Reset(); |
| max_time_cb_.Reset(); |
| - if (!pending_paint_ && !pending_paint_with_last_available_) |
| - DoStopOrError_Locked(); |
| + DoStopOrError_Locked(); |
| // Clean up our thread if present. |
| if (thread_ != base::kNullThreadHandle) { |
| @@ -281,19 +279,13 @@ void VideoRendererBase::ThreadMain() { |
| continue; |
| } |
| - // Remain idle until we've initialized |current_frame_| via prerolling. |
| - if (!current_frame_) { |
| - // This can happen if our preroll only contains end of stream frames. |
| - if (ready_frames_.front()->IsEndOfStream()) { |
| - state_ = kEnded; |
| - ended_cb_.Run(); |
| - ready_frames_.clear(); |
| - |
| - // No need to sleep here as we idle when |state_ != kPlaying|. |
| - continue; |
| - } |
| + // This can happen if our preroll only contains end of stream frames. |
| + if (ready_frames_.front()->IsEndOfStream()) { |
| + state_ = kEnded; |
| + ended_cb_.Run(); |
| + ready_frames_.clear(); |
| - frame_available_.TimedWait(kIdleTimeDelta); |
| + // No need to sleep here as we idle when |state_ != kPlaying|. |
| continue; |
| } |
| @@ -311,144 +303,28 @@ void VideoRendererBase::ThreadMain() { |
| continue; |
| } |
| - |
| - // We're almost there! |
| - // |
| - // At this point we've rendered |current_frame_| for the proper amount |
| - // of time and also have the next frame that ready for rendering. |
| - |
| - |
| - // If the next frame is end of stream then we are truly at the end of the |
| - // video stream. |
| - // |
| - // TODO(scherkus): deduplicate this end of stream check after we get rid of |
| - // |current_frame_|. |
| - if (ready_frames_.front()->IsEndOfStream()) { |
| - state_ = kEnded; |
| - ended_cb_.Run(); |
| - ready_frames_.clear(); |
| - |
| - // No need to sleep here as we idle when |state_ != kPlaying|. |
| - continue; |
| - } |
| - |
| - // We cannot update |current_frame_| until we've completed the pending |
| - // paint. Furthermore, the pending paint might be really slow: check to |
| - // see if we have any ready frames that we can drop if they've already |
| - // expired. |
| - if (pending_paint_) { |
| - while (!ready_frames_.empty()) { |
| - // Can't drop anything if we're at the end. |
| - if (ready_frames_.front()->IsEndOfStream()) |
| - break; |
| - |
| - base::TimeDelta remaining_time = |
| - ready_frames_.front()->GetTimestamp() - get_time_cb_.Run(); |
| - |
| - // Still a chance we can render the frame! |
| - if (remaining_time.InMicroseconds() > 0) |
| - break; |
| - |
| - if (!drop_frames_) |
| - break; |
| - |
| - // Frame dropped: read again. |
| - ++frames_dropped; |
| - ready_frames_.pop_front(); |
| - message_loop_->PostTask(FROM_HERE, base::Bind( |
| - &VideoRendererBase::AttemptRead, this)); |
| - } |
| - // Continue waiting for the current paint to finish. |
| - frame_available_.TimedWait(kIdleTimeDelta); |
| - continue; |
| - } |
| - |
| - |
| // Congratulations! You've made it past the video frame timing gauntlet. |
| // |
| - // We can now safely update the current frame, request another frame, and |
| - // signal to the client that a new frame is available. |
| - DCHECK(!pending_paint_); |
| - DCHECK(!ready_frames_.empty()); |
| - SetCurrentFrameToNextReadyFrame(); |
| + // At this point enough time has passed that the next frame that ready for |
| + // rendering. |
| + PaintWithNextReadyFrame(); |
| message_loop_->PostTask(FROM_HERE, base::Bind( |
| &VideoRendererBase::AttemptRead, this)); |
| - |
| - base::AutoUnlock auto_unlock(lock_); |
| - paint_cb_.Run(); |
| } |
| } |
| -void VideoRendererBase::SetCurrentFrameToNextReadyFrame() { |
| - current_frame_ = ready_frames_.front(); |
| +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.
|
| + scoped_refptr<VideoFrame> next_frame = ready_frames_.front(); |
| ready_frames_.pop_front(); |
| // Notify the pipeline of natural_size() changes. |
| - const gfx::Size& natural_size = current_frame_->natural_size(); |
| + const gfx::Size& natural_size = next_frame->natural_size(); |
| if (natural_size != last_natural_size_) { |
| size_changed_cb_.Run(natural_size); |
| last_natural_size_ = natural_size; |
| } |
| -} |
| - |
| -void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { |
| - base::AutoLock auto_lock(lock_); |
| - DCHECK(!pending_paint_ && !pending_paint_with_last_available_); |
| - |
| - if ((!current_frame_ || current_frame_->IsEndOfStream()) && |
| - (!last_available_frame_ || last_available_frame_->IsEndOfStream())) { |
| - *frame_out = NULL; |
| - return; |
| - } |
| - |
| - // We should have initialized and have the current frame. |
| - DCHECK_NE(state_, kUninitialized); |
| - DCHECK_NE(state_, kStopped); |
| - DCHECK_NE(state_, kError); |
| - |
| - if (current_frame_) { |
| - *frame_out = current_frame_; |
| - last_available_frame_ = current_frame_; |
| - pending_paint_ = true; |
| - } else { |
| - DCHECK(last_available_frame_); |
| - *frame_out = last_available_frame_; |
| - pending_paint_with_last_available_ = true; |
| - } |
| -} |
| - |
| -void VideoRendererBase::PutCurrentFrame(scoped_refptr<VideoFrame> frame) { |
| - base::AutoLock auto_lock(lock_); |
| - // Note that we do not claim |pending_paint_| when we return NULL frame, in |
| - // that case, |current_frame_| could be changed before PutCurrentFrame. |
| - if (pending_paint_) { |
| - DCHECK_EQ(current_frame_, frame); |
| - DCHECK(!pending_paint_with_last_available_); |
| - pending_paint_ = false; |
| - } else if (pending_paint_with_last_available_) { |
| - DCHECK_EQ(last_available_frame_, frame); |
| - DCHECK(!pending_paint_); |
| - pending_paint_with_last_available_ = false; |
| - } else { |
| - DCHECK(!frame); |
| - } |
| - |
| - // We had cleared the |pending_paint_| flag, there are chances that current |
| - // 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(); |
| - return; |
| - } |
| - |
| - if (state_ == kError || state_ == kStopped) { |
| - DoStopOrError_Locked(); |
| - } |
| + 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
|
| } |
| VideoRendererBase::~VideoRendererBase() { |
| @@ -533,21 +409,22 @@ void VideoRendererBase::FrameReady(VideoDecoder::Status status, |
| // If we're at capacity or end of stream while prerolling we need to |
| // transition to prerolled. |
| 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.
|
| - DCHECK(!current_frame_); |
| state_ = kPrerolled; |
| // Because we might remain in the prerolled state for an undetermined amount |
| // of time (i.e., we were not playing before we started prerolling), we'll |
| // manually update the current frame and notify the subclass below. |
| if (!ready_frames_.front()->IsEndOfStream()) |
| - SetCurrentFrameToNextReadyFrame(); |
| + PaintWithNextReadyFrame(); |
| // ...and we're done prerolling! |
| - DCHECK(!preroll_cb_.is_null()); |
| base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); |
| +#if 0 |
| + // 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
|
| base::AutoUnlock ul(lock_); |
| paint_cb_.Run(); |
| +#endif |
| } |
| } |
| @@ -564,10 +441,9 @@ void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) { |
| end_timestamp = std::min( |
| duration, |
| ready_frames_.back()->GetTimestamp() + kMaxLastFrameDuration()); |
| - } else if (current_frame_) { |
| + } else if (last_timestamp_ != kNoTimestamp()) { |
| end_timestamp = |
| - std::min(duration, |
| - current_frame_->GetTimestamp() + kMaxLastFrameDuration()); |
| + std::min(duration, last_timestamp_ + kMaxLastFrameDuration()); |
| } |
| frame->SetTimestamp(end_timestamp); |
| } else if (frame->GetTimestamp() > duration) { |
| @@ -636,9 +512,9 @@ void VideoRendererBase::AttemptFlush_Locked() { |
| prerolling_delayed_frame_ = NULL; |
| ready_frames_.clear(); |
| - if (!pending_paint_ && !pending_read_) { |
| + if (!pending_read_) { |
| state_ = kFlushed; |
| - current_frame_ = NULL; |
| + last_timestamp_ = kNoTimestamp(); |
| base::ResetAndReturn(&flush_cb_).Run(); |
| } |
| } |
| @@ -657,20 +533,14 @@ base::TimeDelta VideoRendererBase::CalculateSleepDuration( |
| } |
| void VideoRendererBase::DoStopOrError_Locked() { |
| - DCHECK(!pending_paint_); |
| - DCHECK(!pending_paint_with_last_available_); |
| lock_.AssertAcquired(); |
| - current_frame_ = NULL; |
| - last_available_frame_ = NULL; |
| + last_timestamp_ = kNoTimestamp(); |
| ready_frames_.clear(); |
| } |
| int VideoRendererBase::NumFrames_Locked() const { |
| lock_.AssertAcquired(); |
| - int outstanding_frames = |
| - (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + |
| - (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.
|
| - return ready_frames_.size() + outstanding_frames; |
| + return ready_frames_.size(); |
| } |
| } // namespace media |