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 |