| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/renderers/video_renderer_impl.h" | 5 #include "media/renderers/video_renderer_impl.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 DCHECK(task_runner_->BelongsToCurrentThread()); | 86 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 87 | 87 |
| 88 if (sink_started_) | 88 if (sink_started_) |
| 89 StopSink(); | 89 StopSink(); |
| 90 | 90 |
| 91 base::AutoLock auto_lock(lock_); | 91 base::AutoLock auto_lock(lock_); |
| 92 DCHECK_EQ(state_, kPlaying); | 92 DCHECK_EQ(state_, kPlaying); |
| 93 flush_cb_ = callback; | 93 flush_cb_ = callback; |
| 94 state_ = kFlushing; | 94 state_ = kFlushing; |
| 95 | 95 |
| 96 // This is necessary if the |video_frame_stream_| has already seen an end of | |
| 97 // stream and needs to drain it before flushing it. | |
| 98 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { | 96 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { |
| 99 buffering_state_ = BUFFERING_HAVE_NOTHING; | 97 buffering_state_ = BUFFERING_HAVE_NOTHING; |
| 100 task_runner_->PostTask( | 98 task_runner_->PostTask( |
| 101 FROM_HERE, base::Bind(&VideoRendererImpl::OnBufferingStateChange, | 99 FROM_HERE, base::Bind(&VideoRendererImpl::OnBufferingStateChange, |
| 102 weak_factory_.GetWeakPtr(), buffering_state_)); | 100 weak_factory_.GetWeakPtr(), buffering_state_)); |
| 103 } | 101 } |
| 104 received_end_of_stream_ = false; | 102 received_end_of_stream_ = false; |
| 105 rendered_end_of_stream_ = false; | 103 rendered_end_of_stream_ = false; |
| 106 | 104 |
| 107 algorithm_->Reset(); | 105 // Reset |video_frame_stream_| and drop any pending read callbacks from it. |
| 108 | 106 pending_read_ = false; |
| 107 frame_callback_weak_factory_.InvalidateWeakPtrs(); |
| 109 video_frame_stream_->Reset( | 108 video_frame_stream_->Reset( |
| 110 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone, | 109 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone, |
| 111 weak_factory_.GetWeakPtr())); | 110 weak_factory_.GetWeakPtr())); |
| 111 |
| 112 // To avoid unnecessary work by VDAs, only delete queued frames after |
| 113 // resetting |video_frame_stream_|. If this is done in the opposite order VDAs |
| 114 // will get a bunch of ReusePictureBuffer() calls before the Reset(), which |
| 115 // they may use to output more frames that won't be used. |
| 116 algorithm_->Reset(); |
| 112 } | 117 } |
| 113 | 118 |
| 114 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { | 119 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { |
| 115 DVLOG(1) << __func__ << "(" << timestamp.InMicroseconds() << ")"; | 120 DVLOG(1) << __func__ << "(" << timestamp.InMicroseconds() << ")"; |
| 116 DCHECK(task_runner_->BelongsToCurrentThread()); | 121 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 117 base::AutoLock auto_lock(lock_); | 122 base::AutoLock auto_lock(lock_); |
| 118 DCHECK_EQ(state_, kFlushed); | 123 DCHECK_EQ(state_, kFlushed); |
| 119 DCHECK(!pending_read_); | 124 DCHECK(!pending_read_); |
| 120 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 125 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
| 121 | 126 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 gpu_memory_buffer_pool_->MaybeCreateHardwareFrame( | 335 gpu_memory_buffer_pool_->MaybeCreateHardwareFrame( |
| 331 frame, base::Bind(&VideoRendererImpl::FrameReady, | 336 frame, base::Bind(&VideoRendererImpl::FrameReady, |
| 332 frame_callback_weak_factory_.GetWeakPtr(), status)); | 337 frame_callback_weak_factory_.GetWeakPtr(), status)); |
| 333 } | 338 } |
| 334 | 339 |
| 335 void VideoRendererImpl::FrameReady(VideoFrameStream::Status status, | 340 void VideoRendererImpl::FrameReady(VideoFrameStream::Status status, |
| 336 const scoped_refptr<VideoFrame>& frame) { | 341 const scoped_refptr<VideoFrame>& frame) { |
| 337 DCHECK(task_runner_->BelongsToCurrentThread()); | 342 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 338 base::AutoLock auto_lock(lock_); | 343 base::AutoLock auto_lock(lock_); |
| 339 | 344 |
| 340 DCHECK_NE(state_, kUninitialized); | 345 DCHECK_EQ(state_, kPlaying); |
| 341 DCHECK_NE(state_, kFlushed); | |
| 342 | |
| 343 CHECK(pending_read_); | 346 CHECK(pending_read_); |
| 344 pending_read_ = false; | 347 pending_read_ = false; |
| 345 | 348 |
| 346 if (status == VideoFrameStream::DECODE_ERROR) { | 349 if (status == VideoFrameStream::DECODE_ERROR) { |
| 347 DCHECK(!frame); | 350 DCHECK(!frame); |
| 348 task_runner_->PostTask( | 351 task_runner_->PostTask( |
| 349 FROM_HERE, | 352 FROM_HERE, |
| 350 base::Bind(&VideoRendererImpl::OnPlaybackError, | 353 base::Bind(&VideoRendererImpl::OnPlaybackError, |
| 351 weak_factory_.GetWeakPtr(), PIPELINE_ERROR_DECODE)); | 354 weak_factory_.GetWeakPtr(), PIPELINE_ERROR_DECODE)); |
| 352 return; | 355 return; |
| 353 } | 356 } |
| 354 | 357 |
| 355 // Already-queued VideoFrameStream ReadCB's can fire after various state | |
| 356 // transitions have happened; in that case just drop those frames | |
| 357 // immediately. | |
| 358 if (state_ == kFlushing) | |
| 359 return; | |
| 360 | |
| 361 DCHECK_EQ(state_, kPlaying); | |
| 362 | |
| 363 // Can happen when demuxers are preparing for a new Seek(). | 358 // Can happen when demuxers are preparing for a new Seek(). |
| 364 if (!frame) { | 359 if (!frame) { |
| 365 DCHECK_EQ(status, VideoFrameStream::DEMUXER_READ_ABORTED); | 360 DCHECK_EQ(status, VideoFrameStream::DEMUXER_READ_ABORTED); |
| 366 return; | 361 return; |
| 367 } | 362 } |
| 368 | 363 |
| 369 if (frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)) { | 364 if (frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)) { |
| 370 DCHECK(!received_end_of_stream_); | 365 DCHECK(!received_end_of_stream_); |
| 371 received_end_of_stream_ = true; | 366 received_end_of_stream_ = true; |
| 372 } else if ((low_delay_ || !video_frame_stream_->CanReadWithoutStalling()) && | 367 } else if ((low_delay_ || !video_frame_stream_->CanReadWithoutStalling()) && |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 void VideoRendererImpl::OnVideoFrameStreamResetDone() { | 508 void VideoRendererImpl::OnVideoFrameStreamResetDone() { |
| 514 // We don't need to acquire the |lock_| here, because we can only get here | 509 // We don't need to acquire the |lock_| here, because we can only get here |
| 515 // when Flush is in progress, so rendering and video sink must be stopped. | 510 // when Flush is in progress, so rendering and video sink must be stopped. |
| 516 DCHECK(task_runner_->BelongsToCurrentThread()); | 511 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 517 DCHECK(!sink_started_); | 512 DCHECK(!sink_started_); |
| 518 DCHECK_EQ(kFlushing, state_); | 513 DCHECK_EQ(kFlushing, state_); |
| 519 DCHECK(!received_end_of_stream_); | 514 DCHECK(!received_end_of_stream_); |
| 520 DCHECK(!rendered_end_of_stream_); | 515 DCHECK(!rendered_end_of_stream_); |
| 521 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 516 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
| 522 | 517 |
| 523 // Pending read might be true if an async video frame copy is in flight. | |
| 524 pending_read_ = false; | |
| 525 // Drop any pending calls to FrameReady() and | |
| 526 // FrameReadyForCopyingToGpuMemoryBuffers() | |
| 527 frame_callback_weak_factory_.InvalidateWeakPtrs(); | |
| 528 state_ = kFlushed; | 518 state_ = kFlushed; |
| 529 base::ResetAndReturn(&flush_cb_).Run(); | 519 base::ResetAndReturn(&flush_cb_).Run(); |
| 530 } | 520 } |
| 531 | 521 |
| 532 void VideoRendererImpl::UpdateStats_Locked() { | 522 void VideoRendererImpl::UpdateStats_Locked() { |
| 533 lock_.AssertAcquired(); | 523 lock_.AssertAcquired(); |
| 534 DCHECK_GE(frames_decoded_, 0); | 524 DCHECK_GE(frames_decoded_, 0); |
| 535 DCHECK_GE(frames_dropped_, 0); | 525 DCHECK_GE(frames_dropped_, 0); |
| 536 | 526 |
| 537 if (frames_decoded_ || frames_dropped_) { | 527 if (frames_decoded_ || frames_dropped_) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 | 680 |
| 691 void VideoRendererImpl::AttemptReadAndCheckForMetadataChanges( | 681 void VideoRendererImpl::AttemptReadAndCheckForMetadataChanges( |
| 692 VideoPixelFormat pixel_format, | 682 VideoPixelFormat pixel_format, |
| 693 const gfx::Size& natural_size) { | 683 const gfx::Size& natural_size) { |
| 694 base::AutoLock auto_lock(lock_); | 684 base::AutoLock auto_lock(lock_); |
| 695 CheckForMetadataChanges(pixel_format, natural_size); | 685 CheckForMetadataChanges(pixel_format, natural_size); |
| 696 AttemptRead_Locked(); | 686 AttemptRead_Locked(); |
| 697 } | 687 } |
| 698 | 688 |
| 699 } // namespace media | 689 } // namespace media |
| OLD | NEW |