OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/renderer/media/webmediaplayer_ms_compositor.h" | 5 #include "content/renderer/media/webmediaplayer_ms_compositor.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/hash.h" | 10 #include "base/hash.h" |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 if (video_frame_provider_client_ && !stopped_) | 178 if (video_frame_provider_client_ && !stopped_) |
179 video_frame_provider_client_->StartRendering(); | 179 video_frame_provider_client_->StartRendering(); |
180 } | 180 } |
181 | 181 |
182 void WebMediaPlayerMSCompositor::EnqueueFrame( | 182 void WebMediaPlayerMSCompositor::EnqueueFrame( |
183 const scoped_refptr<media::VideoFrame>& frame) { | 183 const scoped_refptr<media::VideoFrame>& frame) { |
184 DCHECK(thread_checker_.CalledOnValidThread()); | 184 DCHECK(thread_checker_.CalledOnValidThread()); |
185 base::AutoLock auto_lock(current_frame_lock_); | 185 base::AutoLock auto_lock(current_frame_lock_); |
186 ++total_frame_count_; | 186 ++total_frame_count_; |
187 | 187 |
| 188 // With algorithm off, just let |current_frame_| hold the incoming |frame|. |
188 if (!rendering_frame_buffer_) { | 189 if (!rendering_frame_buffer_) { |
189 SetCurrentFrame(frame); | 190 SetCurrentFrame(frame); |
190 return; | 191 return; |
191 } | 192 } |
192 | 193 |
193 // This is a signal frame saying that the stream is stopped. | 194 // This is a signal frame saying that the stream is stopped. |
194 bool end_of_stream = false; | 195 bool end_of_stream = false; |
195 if (frame->metadata()->GetBoolean(media::VideoFrameMetadata::END_OF_STREAM, | 196 if (frame->metadata()->GetBoolean(media::VideoFrameMetadata::END_OF_STREAM, |
196 &end_of_stream) && | 197 &end_of_stream) && |
197 end_of_stream) { | 198 end_of_stream) { |
198 rendering_frame_buffer_.reset(); | 199 rendering_frame_buffer_.reset(); |
199 SetCurrentFrame(frame); | 200 SetCurrentFrame(frame); |
200 return; | 201 return; |
201 } | 202 } |
202 | 203 |
| 204 // If we detect a bad frame without |render_time|, we switch off algorithm, |
| 205 // because without |render_time|, algorithm cannot work. |
| 206 // In general, this should not happen. |
203 base::TimeTicks render_time; | 207 base::TimeTicks render_time; |
204 if (!frame->metadata()->GetTimeTicks( | 208 if (!frame->metadata()->GetTimeTicks( |
205 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { | 209 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { |
206 DLOG(WARNING) | 210 DLOG(WARNING) |
207 << "Incoming VideoFrames have no REFERENCE_TIME, switching off super " | 211 << "Incoming VideoFrames have no REFERENCE_TIME, switching off super " |
208 "sophisticated rendering algorithm"; | 212 "sophisticated rendering algorithm"; |
209 rendering_frame_buffer_.reset(); | 213 rendering_frame_buffer_.reset(); |
210 SetCurrentFrame(frame); | 214 SetCurrentFrame(frame); |
211 return; | 215 return; |
212 } | 216 } |
213 | 217 |
| 218 // The code below handles the case where UpdateCurrentFrame() callbacks stop. |
| 219 // These callbacks can stop when the tab is hidden or the page area containing |
| 220 // the video frame is scrolled out of view. |
| 221 // Since some hardware decoders only have a limited number of output frames, |
| 222 // we must aggressively release frames in this case. |
| 223 const base::TimeTicks now = base::TimeTicks::Now(); |
| 224 if (now > last_deadline_max_) { |
| 225 // Note: the frame in |rendering_frame_buffer_| with lowest index is the |
| 226 // same as |current_frame_|. Function SetCurrentFrame() handles whether |
| 227 // to increase |dropped_frame_count_| for that frame, so here we should |
| 228 // increase |dropped_frame_count_| by the count of all other frames. |
| 229 dropped_frame_count_ += rendering_frame_buffer_->frames_queued() - 1; |
| 230 rendering_frame_buffer_->Reset(); |
| 231 timestamps_to_clock_times_.clear(); |
| 232 SetCurrentFrame(frame); |
| 233 } |
| 234 |
214 timestamps_to_clock_times_[frame->timestamp()] = render_time; | 235 timestamps_to_clock_times_[frame->timestamp()] = render_time; |
215 | |
216 rendering_frame_buffer_->EnqueueFrame(frame); | 236 rendering_frame_buffer_->EnqueueFrame(frame); |
217 | |
218 const base::TimeTicks now = base::TimeTicks::Now(); | |
219 if (now <= last_deadline_max_) | |
220 return; | |
221 | |
222 // This shows vsyncs stops rendering frames. A probable cause is that the | |
223 // tab is not in the front. But we still have to let old frames go. | |
224 const base::TimeTicks deadline_max = | |
225 std::max(now, last_deadline_max_ + last_render_length_); | |
226 | |
227 Render(deadline_max - last_render_length_, deadline_max); | |
228 } | 237 } |
229 | 238 |
230 bool WebMediaPlayerMSCompositor::UpdateCurrentFrame( | 239 bool WebMediaPlayerMSCompositor::UpdateCurrentFrame( |
231 base::TimeTicks deadline_min, | 240 base::TimeTicks deadline_min, |
232 base::TimeTicks deadline_max) { | 241 base::TimeTicks deadline_max) { |
233 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 242 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); |
234 | 243 |
235 TRACE_EVENT_BEGIN2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame", | 244 TRACE_EVENT_BEGIN2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame", |
236 "Actual Render Begin", deadline_min.ToInternalValue(), | 245 "Actual Render Begin", deadline_min.ToInternalValue(), |
237 "Actual Render End", deadline_max.ToInternalValue()); | 246 "Actual Render End", deadline_max.ToInternalValue()); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 } | 400 } |
392 | 401 |
393 if (!rendering_frame_buffer_) { | 402 if (!rendering_frame_buffer_) { |
394 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( | 403 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( |
395 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, | 404 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, |
396 base::Unretained(this)))); | 405 base::Unretained(this)))); |
397 } | 406 } |
398 } | 407 } |
399 | 408 |
400 } // namespace content | 409 } // namespace content |
OLD | NEW |