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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 start_timestamp_ = timestamp; | 119 start_timestamp_ = timestamp; |
120 AttemptRead_Locked(); | 120 AttemptRead_Locked(); |
121 } | 121 } |
122 | 122 |
123 void VideoRendererImpl::Initialize( | 123 void VideoRendererImpl::Initialize( |
124 DemuxerStream* stream, | 124 DemuxerStream* stream, |
125 const PipelineStatusCB& init_cb, | 125 const PipelineStatusCB& init_cb, |
126 CdmContext* cdm_context, | 126 CdmContext* cdm_context, |
127 const StatisticsCB& statistics_cb, | 127 const StatisticsCB& statistics_cb, |
128 const BufferingStateCB& buffering_state_cb, | 128 const BufferingStateCB& buffering_state_cb, |
| 129 const NaturalSizeChangedCB& natural_size_changed_cb, |
129 const base::Closure& ended_cb, | 130 const base::Closure& ended_cb, |
130 const PipelineStatusCB& error_cb, | 131 const PipelineStatusCB& error_cb, |
131 const TimeSource::WallClockTimeCB& wall_clock_time_cb, | 132 const TimeSource::WallClockTimeCB& wall_clock_time_cb, |
132 const base::Closure& waiting_for_decryption_key_cb) { | 133 const base::Closure& waiting_for_decryption_key_cb) { |
133 DCHECK(task_runner_->BelongsToCurrentThread()); | 134 DCHECK(task_runner_->BelongsToCurrentThread()); |
134 base::AutoLock auto_lock(lock_); | 135 base::AutoLock auto_lock(lock_); |
135 DCHECK(stream); | 136 DCHECK(stream); |
136 DCHECK_EQ(stream->type(), DemuxerStream::VIDEO); | 137 DCHECK_EQ(stream->type(), DemuxerStream::VIDEO); |
137 DCHECK(!init_cb.is_null()); | 138 DCHECK(!init_cb.is_null()); |
138 DCHECK(!statistics_cb.is_null()); | 139 DCHECK(!statistics_cb.is_null()); |
(...skipping 12 matching lines...) Expand all Loading... |
151 MEDIA_LOG(DEBUG, media_log_) << "Video rendering in low delay mode."; | 152 MEDIA_LOG(DEBUG, media_log_) << "Video rendering in low delay mode."; |
152 | 153 |
153 // Always post |init_cb_| because |this| could be destroyed if initialization | 154 // Always post |init_cb_| because |this| could be destroyed if initialization |
154 // failed. | 155 // failed. |
155 init_cb_ = BindToCurrentLoop(init_cb); | 156 init_cb_ = BindToCurrentLoop(init_cb); |
156 | 157 |
157 // Always post |buffering_state_cb_| because it may otherwise invoke reentrant | 158 // Always post |buffering_state_cb_| because it may otherwise invoke reentrant |
158 // calls to OnTimeStateChanged() under lock, which can deadlock the compositor | 159 // calls to OnTimeStateChanged() under lock, which can deadlock the compositor |
159 // and media threads. | 160 // and media threads. |
160 buffering_state_cb_ = BindToCurrentLoop(buffering_state_cb); | 161 buffering_state_cb_ = BindToCurrentLoop(buffering_state_cb); |
161 | 162 natural_size_changed_cb_ = natural_size_changed_cb; |
162 statistics_cb_ = statistics_cb; | 163 statistics_cb_ = statistics_cb; |
163 ended_cb_ = ended_cb; | 164 ended_cb_ = ended_cb; |
164 error_cb_ = error_cb; | 165 error_cb_ = error_cb; |
165 wall_clock_time_cb_ = wall_clock_time_cb; | 166 wall_clock_time_cb_ = wall_clock_time_cb; |
166 state_ = kInitializing; | 167 state_ = kInitializing; |
167 | 168 |
168 video_frame_stream_->Initialize( | 169 video_frame_stream_->Initialize( |
169 stream, base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized, | 170 stream, base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized, |
170 weak_factory_.GetWeakPtr()), | 171 weak_factory_.GetWeakPtr()), |
171 cdm_context, statistics_cb, waiting_for_decryption_key_cb); | 172 cdm_context, statistics_cb, waiting_for_decryption_key_cb); |
172 } | 173 } |
173 | 174 |
174 scoped_refptr<VideoFrame> VideoRendererImpl::Render( | 175 scoped_refptr<VideoFrame> VideoRendererImpl::Render( |
175 base::TimeTicks deadline_min, | 176 base::TimeTicks deadline_min, |
176 base::TimeTicks deadline_max, | 177 base::TimeTicks deadline_max, |
177 bool background_rendering) { | 178 bool background_rendering) { |
178 base::AutoLock auto_lock(lock_); | 179 base::AutoLock auto_lock(lock_); |
179 DCHECK_EQ(state_, kPlaying); | 180 DCHECK_EQ(state_, kPlaying); |
180 | 181 |
181 size_t frames_dropped = 0; | 182 size_t frames_dropped = 0; |
182 scoped_refptr<VideoFrame> result = | 183 scoped_refptr<VideoFrame> result = |
183 algorithm_->Render(deadline_min, deadline_max, &frames_dropped); | 184 algorithm_->Render(deadline_min, deadline_max, &frames_dropped); |
184 | 185 |
185 // Due to how the |algorithm_| holds frames, this should never be null if | 186 // Due to how the |algorithm_| holds frames, this should never be null if |
186 // we've had a proper startup sequence. | 187 // we've had a proper startup sequence. |
187 DCHECK(result); | 188 DCHECK(result); |
188 | 189 |
| 190 if (last_frame_natural_size_ != result->natural_size()) { |
| 191 last_frame_natural_size_ = result->natural_size(); |
| 192 task_runner_->PostTask(FROM_HERE, base::Bind(natural_size_changed_cb_, |
| 193 last_frame_natural_size_)); |
| 194 } |
| 195 |
189 // Declare HAVE_NOTHING if we reach a state where we can't progress playback | 196 // Declare HAVE_NOTHING if we reach a state where we can't progress playback |
190 // any further. We don't want to do this if we've already done so, reached | 197 // any further. We don't want to do this if we've already done so, reached |
191 // end of stream, or have frames available. We also don't want to do this in | 198 // end of stream, or have frames available. We also don't want to do this in |
192 // background rendering mode unless this isn't the first background render | 199 // background rendering mode unless this isn't the first background render |
193 // tick and we haven't seen any decoded frames since the last one. | 200 // tick and we haven't seen any decoded frames since the last one. |
194 // | 201 // |
195 // We use the inverse of |render_first_frame_and_stop_| as a proxy for the | 202 // We use the inverse of |render_first_frame_and_stop_| as a proxy for the |
196 // value of |time_progressing_| here since we can't access it from the | 203 // value of |time_progressing_| here since we can't access it from the |
197 // compositor thread. If we're here (in Render()) the sink must have been | 204 // compositor thread. If we're here (in Render()) the sink must have been |
198 // started -- but if it was started only to render the first frame and stop, | 205 // started -- but if it was started only to render the first frame and stop, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 FROM_HERE, base::Bind(&VideoRendererImpl::MaybeStopSinkAfterFirstPaint, | 243 FROM_HERE, base::Bind(&VideoRendererImpl::MaybeStopSinkAfterFirstPaint, |
237 weak_factory_.GetWeakPtr()), | 244 weak_factory_.GetWeakPtr()), |
238 base::TimeDelta::FromMilliseconds(250)); | 245 base::TimeDelta::FromMilliseconds(250)); |
239 } | 246 } |
240 | 247 |
241 // Always post this task, it will acquire new frames if necessary and since it | 248 // Always post this task, it will acquire new frames if necessary and since it |
242 // happens on another thread, even if we don't have room in the queue now, by | 249 // happens on another thread, even if we don't have room in the queue now, by |
243 // the time it runs (may be delayed up to 50ms for complex decodes!) we might. | 250 // the time it runs (may be delayed up to 50ms for complex decodes!) we might. |
244 task_runner_->PostTask(FROM_HERE, base::Bind(&VideoRendererImpl::AttemptRead, | 251 task_runner_->PostTask(FROM_HERE, base::Bind(&VideoRendererImpl::AttemptRead, |
245 weak_factory_.GetWeakPtr())); | 252 weak_factory_.GetWeakPtr())); |
246 | |
247 return result; | 253 return result; |
248 } | 254 } |
249 | 255 |
250 void VideoRendererImpl::OnFrameDropped() { | 256 void VideoRendererImpl::OnFrameDropped() { |
251 base::AutoLock auto_lock(lock_); | 257 base::AutoLock auto_lock(lock_); |
252 algorithm_->OnLastFrameDropped(); | 258 algorithm_->OnLastFrameDropped(); |
253 } | 259 } |
254 | 260 |
255 void VideoRendererImpl::OnVideoFrameStreamInitialized(bool success) { | 261 void VideoRendererImpl::OnVideoFrameStreamInitialized(bool success) { |
256 DCHECK(task_runner_->BelongsToCurrentThread()); | 262 DCHECK(task_runner_->BelongsToCurrentThread()); |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 std::vector<base::TimeTicks> current_time; | 639 std::vector<base::TimeTicks> current_time; |
634 wall_clock_time_cb_.Run(std::vector<base::TimeDelta>(), ¤t_time); | 640 wall_clock_time_cb_.Run(std::vector<base::TimeDelta>(), ¤t_time); |
635 return current_time[0]; | 641 return current_time[0]; |
636 } | 642 } |
637 | 643 |
638 bool VideoRendererImpl::IsBeforeStartTime(base::TimeDelta timestamp) { | 644 bool VideoRendererImpl::IsBeforeStartTime(base::TimeDelta timestamp) { |
639 return timestamp + video_frame_stream_->AverageDuration() < start_timestamp_; | 645 return timestamp + video_frame_stream_->AverageDuration() < start_timestamp_; |
640 } | 646 } |
641 | 647 |
642 } // namespace media | 648 } // namespace media |
OLD | NEW |