| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 drop_frames_(drop_frames), | 52 drop_frames_(drop_frames), |
| 53 buffering_state_(BUFFERING_HAVE_NOTHING), | 53 buffering_state_(BUFFERING_HAVE_NOTHING), |
| 54 frames_decoded_(0), | 54 frames_decoded_(0), |
| 55 frames_dropped_(0), | 55 frames_dropped_(0), |
| 56 tick_clock_(new base::DefaultTickClock()), | 56 tick_clock_(new base::DefaultTickClock()), |
| 57 was_background_rendering_(false), | 57 was_background_rendering_(false), |
| 58 time_progressing_(false), | 58 time_progressing_(false), |
| 59 last_video_memory_usage_(0), | 59 last_video_memory_usage_(0), |
| 60 have_renderered_frames_(false), | 60 have_renderered_frames_(false), |
| 61 last_frame_opaque_(false), | 61 last_frame_opaque_(false), |
| 62 painted_first_frame_(false), |
| 62 weak_factory_(this), | 63 weak_factory_(this), |
| 63 frame_callback_weak_factory_(this) { | 64 frame_callback_weak_factory_(this) { |
| 64 if (gpu_factories && | 65 if (gpu_factories && |
| 65 gpu_factories->ShouldUseGpuMemoryBuffersForVideoFrames()) { | 66 gpu_factories->ShouldUseGpuMemoryBuffersForVideoFrames()) { |
| 66 gpu_memory_buffer_pool_.reset(new GpuMemoryBufferVideoFramePool( | 67 gpu_memory_buffer_pool_.reset(new GpuMemoryBufferVideoFramePool( |
| 67 media_task_runner, worker_task_runner, gpu_factories)); | 68 media_task_runner, worker_task_runner, gpu_factories)); |
| 68 } | 69 } |
| 69 } | 70 } |
| 70 | 71 |
| 71 VideoRendererImpl::~VideoRendererImpl() { | 72 VideoRendererImpl::~VideoRendererImpl() { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 frame_callback_weak_factory_.InvalidateWeakPtrs(); | 108 frame_callback_weak_factory_.InvalidateWeakPtrs(); |
| 108 video_frame_stream_->Reset( | 109 video_frame_stream_->Reset( |
| 109 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone, | 110 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone, |
| 110 weak_factory_.GetWeakPtr())); | 111 weak_factory_.GetWeakPtr())); |
| 111 | 112 |
| 112 // To avoid unnecessary work by VDAs, only delete queued frames after | 113 // 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 // 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 // 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 // they may use to output more frames that won't be used. |
| 116 algorithm_->Reset(); | 117 algorithm_->Reset(); |
| 118 painted_first_frame_ = false; |
| 117 } | 119 } |
| 118 | 120 |
| 119 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { | 121 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { |
| 120 DVLOG(1) << __func__ << "(" << timestamp.InMicroseconds() << ")"; | 122 DVLOG(1) << __func__ << "(" << timestamp.InMicroseconds() << ")"; |
| 121 DCHECK(task_runner_->BelongsToCurrentThread()); | 123 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 122 base::AutoLock auto_lock(lock_); | 124 base::AutoLock auto_lock(lock_); |
| 123 DCHECK_EQ(state_, kFlushed); | 125 DCHECK_EQ(state_, kFlushed); |
| 124 DCHECK(!pending_read_); | 126 DCHECK(!pending_read_); |
| 125 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 127 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
| 126 | 128 |
| 127 state_ = kPlaying; | 129 state_ = kPlaying; |
| 128 start_timestamp_ = timestamp; | 130 start_timestamp_ = timestamp; |
| 131 painted_first_frame_ = false; |
| 129 AttemptRead_Locked(); | 132 AttemptRead_Locked(); |
| 130 } | 133 } |
| 131 | 134 |
| 132 void VideoRendererImpl::Initialize( | 135 void VideoRendererImpl::Initialize( |
| 133 DemuxerStream* stream, | 136 DemuxerStream* stream, |
| 134 CdmContext* cdm_context, | 137 CdmContext* cdm_context, |
| 135 RendererClient* client, | 138 RendererClient* client, |
| 136 const TimeSource::WallClockTimeCB& wall_clock_time_cb, | 139 const TimeSource::WallClockTimeCB& wall_clock_time_cb, |
| 137 const PipelineStatusCB& init_cb) { | 140 const PipelineStatusCB& init_cb) { |
| 138 DCHECK(task_runner_->BelongsToCurrentThread()); | 141 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 // Attempt to purge bad frames in case of underflow or backgrounding. | 396 // Attempt to purge bad frames in case of underflow or backgrounding. |
| 394 RemoveFramesForUnderflowOrBackgroundRendering(); | 397 RemoveFramesForUnderflowOrBackgroundRendering(); |
| 395 | 398 |
| 396 // We may have removed all frames above and have reached end of stream. | 399 // We may have removed all frames above and have reached end of stream. |
| 397 MaybeFireEndedCallback_Locked(time_progressing_); | 400 MaybeFireEndedCallback_Locked(time_progressing_); |
| 398 | 401 |
| 399 // Update statistics here instead of during Render() when the sink is stopped. | 402 // Update statistics here instead of during Render() when the sink is stopped. |
| 400 if (!sink_started_) | 403 if (!sink_started_) |
| 401 UpdateStats_Locked(); | 404 UpdateStats_Locked(); |
| 402 | 405 |
| 403 // Paint the first frame if possible and necessary. PaintSingleFrame() will | 406 // Paint the first frame if possible and necessary. Paint ahead of |
| 404 // ignore repeated calls for the same frame. Paint ahead of HAVE_ENOUGH_DATA | 407 // HAVE_ENOUGH_DATA to ensure the user sees the frame as early as possible. |
| 405 // to ensure the user sees the frame as early as possible. | 408 if (!sink_started_ && algorithm_->frames_queued() && !painted_first_frame_) { |
| 406 if (!sink_started_ && algorithm_->frames_queued()) { | |
| 407 // We want to paint the first frame under two conditions: Either (1) we have | 409 // We want to paint the first frame under two conditions: Either (1) we have |
| 408 // enough frames to know it's definitely the first frame or (2) there may be | 410 // enough frames to know it's definitely the first frame or (2) there may be |
| 409 // no more frames coming (sometimes unless we paint one of them). | 411 // no more frames coming (sometimes unless we paint one of them). |
| 410 // | 412 // |
| 411 // For the first condition, we need at least two frames or the first frame | 413 // For the first condition, we need at least two frames or the first frame |
| 412 // must have a timestamp >= |start_timestamp_|, since otherwise we may be | 414 // must have a timestamp >= |start_timestamp_|, since otherwise we may be |
| 413 // prerolling frames before the actual start time that will be dropped. | 415 // prerolling frames before the actual start time that will be dropped. |
| 414 if (algorithm_->frames_queued() > 1 || received_end_of_stream_ || | 416 if (algorithm_->frames_queued() > 1 || received_end_of_stream_ || |
| 415 algorithm_->first_frame()->timestamp() >= start_timestamp_ || | 417 frame->timestamp() >= start_timestamp_ || low_delay_ || |
| 416 low_delay_ || !video_frame_stream_->CanReadWithoutStalling()) { | 418 !video_frame_stream_->CanReadWithoutStalling()) { |
| 417 scoped_refptr<VideoFrame> frame = algorithm_->first_frame(); | 419 scoped_refptr<VideoFrame> first_frame = |
| 418 CheckForMetadataChanges(frame->format(), frame->natural_size()); | 420 algorithm_->Render(base::TimeTicks(), base::TimeTicks(), nullptr); |
| 419 sink_->PaintSingleFrame(frame); | 421 CheckForMetadataChanges(first_frame->format(), |
| 422 first_frame->natural_size()); |
| 423 sink_->PaintSingleFrame(first_frame); |
| 424 painted_first_frame_ = true; |
| 420 } | 425 } |
| 421 } | 426 } |
| 422 | 427 |
| 423 // Signal buffering state if we've met our conditions. | 428 // Signal buffering state if we've met our conditions. |
| 424 if (buffering_state_ == BUFFERING_HAVE_NOTHING && HaveEnoughData_Locked()) | 429 if (buffering_state_ == BUFFERING_HAVE_NOTHING && HaveEnoughData_Locked()) |
| 425 TransitionToHaveEnough_Locked(); | 430 TransitionToHaveEnough_Locked(); |
| 426 | 431 |
| 427 // Always request more decoded video if we have capacity. | 432 // Always request more decoded video if we have capacity. |
| 428 AttemptRead_Locked(); | 433 AttemptRead_Locked(); |
| 429 } | 434 } |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 frames_dropped_ += algorithm_->RemoveExpiredFrames( | 671 frames_dropped_ += algorithm_->RemoveExpiredFrames( |
| 667 current_time + algorithm_->average_frame_duration()); | 672 current_time + algorithm_->average_frame_duration()); |
| 668 | 673 |
| 669 // If we've paused for underflow, and still have no effective frames, clear | 674 // If we've paused for underflow, and still have no effective frames, clear |
| 670 // the entire queue. Note: this may cause slight inaccuracies in the number | 675 // the entire queue. Note: this may cause slight inaccuracies in the number |
| 671 // of dropped frames since the frame may have been rendered before. | 676 // of dropped frames since the frame may have been rendered before. |
| 672 if (!sink_started_ && !algorithm_->effective_frames_queued()) { | 677 if (!sink_started_ && !algorithm_->effective_frames_queued()) { |
| 673 frames_dropped_ += algorithm_->frames_queued(); | 678 frames_dropped_ += algorithm_->frames_queued(); |
| 674 algorithm_->Reset( | 679 algorithm_->Reset( |
| 675 VideoRendererAlgorithm::ResetFlag::kPreserveNextFrameEstimates); | 680 VideoRendererAlgorithm::ResetFlag::kPreserveNextFrameEstimates); |
| 681 painted_first_frame_ = false; |
| 676 | 682 |
| 677 // It's possible in the background rendering case for us to expire enough | 683 // It's possible in the background rendering case for us to expire enough |
| 678 // frames that we need to transition from HAVE_ENOUGH => HAVE_NOTHING. Just | 684 // frames that we need to transition from HAVE_ENOUGH => HAVE_NOTHING. Just |
| 679 // calling this function will check if we need to transition or not. | 685 // calling this function will check if we need to transition or not. |
| 680 if (buffering_state_ == BUFFERING_HAVE_ENOUGH) | 686 if (buffering_state_ == BUFFERING_HAVE_ENOUGH) |
| 681 TransitionToHaveNothing_Locked(); | 687 TransitionToHaveNothing_Locked(); |
| 682 } | 688 } |
| 683 } | 689 } |
| 684 | 690 |
| 685 void VideoRendererImpl::CheckForMetadataChanges(VideoPixelFormat pixel_format, | 691 void VideoRendererImpl::CheckForMetadataChanges(VideoPixelFormat pixel_format, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 704 | 710 |
| 705 void VideoRendererImpl::AttemptReadAndCheckForMetadataChanges( | 711 void VideoRendererImpl::AttemptReadAndCheckForMetadataChanges( |
| 706 VideoPixelFormat pixel_format, | 712 VideoPixelFormat pixel_format, |
| 707 const gfx::Size& natural_size) { | 713 const gfx::Size& natural_size) { |
| 708 base::AutoLock auto_lock(lock_); | 714 base::AutoLock auto_lock(lock_); |
| 709 CheckForMetadataChanges(pixel_format, natural_size); | 715 CheckForMetadataChanges(pixel_format, natural_size); |
| 710 AttemptRead_Locked(); | 716 AttemptRead_Locked(); |
| 711 } | 717 } |
| 712 | 718 |
| 713 } // namespace media | 719 } // namespace media |
| OLD | NEW |