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 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, | 127 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, |
128 const blink::WebMediaStream& web_stream, | 128 const blink::WebMediaStream& web_stream, |
129 const base::WeakPtr<WebMediaPlayerMS>& player) | 129 const base::WeakPtr<WebMediaPlayerMS>& player) |
130 : compositor_task_runner_(compositor_task_runner), | 130 : compositor_task_runner_(compositor_task_runner), |
131 player_(player), | 131 player_(player), |
132 video_frame_provider_client_(nullptr), | 132 video_frame_provider_client_(nullptr), |
133 current_frame_used_by_compositor_(false), | 133 current_frame_used_by_compositor_(false), |
134 last_render_length_(base::TimeDelta::FromSecondsD(1.0 / 60.0)), | 134 last_render_length_(base::TimeDelta::FromSecondsD(1.0 / 60.0)), |
135 total_frame_count_(0), | 135 total_frame_count_(0), |
136 dropped_frame_count_(0), | 136 dropped_frame_count_(0), |
137 stopped_(true), | 137 stopped_(true) { |
138 weak_ptr_factory_(this) { | |
139 main_message_loop_ = base::MessageLoop::current(); | 138 main_message_loop_ = base::MessageLoop::current(); |
| 139 io_thread_checker_.DetachFromThread(); |
140 | 140 |
141 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; | 141 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; |
142 if (!web_stream.isNull()) | 142 if (!web_stream.isNull()) |
143 web_stream.videoTracks(video_tracks); | 143 web_stream.videoTracks(video_tracks); |
144 | 144 |
145 const bool remote_video = | 145 const bool remote_video = |
146 video_tracks.size() && video_tracks[0].source().remote(); | 146 video_tracks.size() && video_tracks[0].source().remote(); |
147 | 147 |
148 if (remote_video && | 148 if (remote_video && |
149 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 149 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
150 switches::kDisableRTCSmoothnessAlgorithm)) { | 150 switches::kDisableRTCSmoothnessAlgorithm)) { |
151 base::AutoLock auto_lock(current_frame_lock_); | 151 base::AutoLock auto_lock(current_frame_lock_); |
152 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( | 152 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( |
153 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, | 153 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, |
154 base::Unretained(this)))); | 154 base::Unretained(this)))); |
155 } | 155 } |
156 | 156 |
157 // Just for logging purpose. | 157 // Just for logging purpose. |
158 std::string stream_id = | 158 std::string stream_id = |
159 web_stream.isNull() ? std::string() : web_stream.id().utf8(); | 159 web_stream.isNull() ? std::string() : web_stream.id().utf8(); |
160 const uint32_t hash_value = base::Hash(stream_id); | 160 const uint32_t hash_value = base::Hash(stream_id); |
161 serial_ = (hash_value << 1) | (remote_video ? 1 : 0); | 161 serial_ = (hash_value << 1) | (remote_video ? 1 : 0); |
162 } | 162 } |
163 | 163 |
164 WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() { | 164 WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() { |
165 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 165 DCHECK(!video_frame_provider_client_) |
166 if (video_frame_provider_client_) | 166 << "Must call StopUsingProvider() before dtor!"; |
167 video_frame_provider_client_->StopUsingProvider(); | |
168 } | 167 } |
169 | 168 |
170 gfx::Size WebMediaPlayerMSCompositor::GetCurrentSize() { | 169 gfx::Size WebMediaPlayerMSCompositor::GetCurrentSize() { |
171 DCHECK(thread_checker_.CalledOnValidThread()); | 170 DCHECK(thread_checker_.CalledOnValidThread()); |
172 base::AutoLock auto_lock(current_frame_lock_); | 171 base::AutoLock auto_lock(current_frame_lock_); |
173 return current_frame_ ? current_frame_->natural_size() : gfx::Size(); | 172 return current_frame_ ? current_frame_->natural_size() : gfx::Size(); |
174 } | 173 } |
175 | 174 |
176 base::TimeDelta WebMediaPlayerMSCompositor::GetCurrentTime() { | 175 base::TimeDelta WebMediaPlayerMSCompositor::GetCurrentTime() { |
177 DCHECK(thread_checker_.CalledOnValidThread()); | 176 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 19 matching lines...) Expand all Loading... |
197 if (video_frame_provider_client_) | 196 if (video_frame_provider_client_) |
198 video_frame_provider_client_->StopUsingProvider(); | 197 video_frame_provider_client_->StopUsingProvider(); |
199 | 198 |
200 video_frame_provider_client_ = client; | 199 video_frame_provider_client_ = client; |
201 if (video_frame_provider_client_ && !stopped_) | 200 if (video_frame_provider_client_ && !stopped_) |
202 video_frame_provider_client_->StartRendering(); | 201 video_frame_provider_client_->StartRendering(); |
203 } | 202 } |
204 | 203 |
205 void WebMediaPlayerMSCompositor::EnqueueFrame( | 204 void WebMediaPlayerMSCompositor::EnqueueFrame( |
206 scoped_refptr<media::VideoFrame> frame) { | 205 scoped_refptr<media::VideoFrame> frame) { |
207 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 206 DCHECK(io_thread_checker_.CalledOnValidThread()); |
208 base::AutoLock auto_lock(current_frame_lock_); | 207 base::AutoLock auto_lock(current_frame_lock_); |
209 ++total_frame_count_; | 208 ++total_frame_count_; |
210 | 209 |
211 // With algorithm off, just let |current_frame_| hold the incoming |frame|. | 210 // With algorithm off, just let |current_frame_| hold the incoming |frame|. |
212 if (!rendering_frame_buffer_) { | 211 if (!rendering_frame_buffer_) { |
213 SetCurrentFrame(frame); | 212 SetCurrentFrame(frame); |
214 return; | 213 return; |
215 } | 214 } |
216 | 215 |
217 // This is a signal frame saying that the stream is stopped. | 216 // This is a signal frame saying that the stream is stopped. |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 scoped_refptr<media::VideoFrame> | 309 scoped_refptr<media::VideoFrame> |
311 WebMediaPlayerMSCompositor::GetCurrentFrameWithoutUpdatingStatistics() { | 310 WebMediaPlayerMSCompositor::GetCurrentFrameWithoutUpdatingStatistics() { |
312 DVLOG(3) << __func__; | 311 DVLOG(3) << __func__; |
313 base::AutoLock auto_lock(current_frame_lock_); | 312 base::AutoLock auto_lock(current_frame_lock_); |
314 return current_frame_; | 313 return current_frame_; |
315 } | 314 } |
316 | 315 |
317 void WebMediaPlayerMSCompositor::StartRendering() { | 316 void WebMediaPlayerMSCompositor::StartRendering() { |
318 DCHECK(thread_checker_.CalledOnValidThread()); | 317 DCHECK(thread_checker_.CalledOnValidThread()); |
319 compositor_task_runner_->PostTask( | 318 compositor_task_runner_->PostTask( |
320 FROM_HERE, base::Bind(&WebMediaPlayerMSCompositor::StartRenderingInternal, | 319 FROM_HERE, |
321 weak_ptr_factory_.GetWeakPtr())); | 320 base::Bind(&WebMediaPlayerMSCompositor::StartRenderingInternal, this)); |
322 } | |
323 | |
324 void WebMediaPlayerMSCompositor::StartRenderingInternal() { | |
325 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
326 stopped_ = false; | |
327 | |
328 if (video_frame_provider_client_) | |
329 video_frame_provider_client_->StartRendering(); | |
330 } | 321 } |
331 | 322 |
332 void WebMediaPlayerMSCompositor::StopRendering() { | 323 void WebMediaPlayerMSCompositor::StopRendering() { |
333 DCHECK(thread_checker_.CalledOnValidThread()); | 324 DCHECK(thread_checker_.CalledOnValidThread()); |
334 compositor_task_runner_->PostTask( | 325 compositor_task_runner_->PostTask( |
335 FROM_HERE, base::Bind(&WebMediaPlayerMSCompositor::StopRenderingInternal, | 326 FROM_HERE, |
336 weak_ptr_factory_.GetWeakPtr())); | 327 base::Bind(&WebMediaPlayerMSCompositor::StopRenderingInternal, this)); |
337 } | |
338 | |
339 void WebMediaPlayerMSCompositor::StopRenderingInternal() { | |
340 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
341 stopped_ = true; | |
342 | |
343 // It is possible that the video gets paused and then resumed. We need to | |
344 // reset VideoRendererAlgorithm, otherwise, VideoRendererAlgorithm will think | |
345 // there is a very long frame in the queue and then make totally wrong | |
346 // frame selection. | |
347 { | |
348 base::AutoLock auto_lock(current_frame_lock_); | |
349 if (rendering_frame_buffer_) | |
350 rendering_frame_buffer_->Reset(); | |
351 } | |
352 | |
353 if (video_frame_provider_client_) | |
354 video_frame_provider_client_->StopRendering(); | |
355 } | 328 } |
356 | 329 |
357 void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() { | 330 void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() { |
358 DCHECK(thread_checker_.CalledOnValidThread()); | 331 DCHECK(thread_checker_.CalledOnValidThread()); |
359 base::AutoLock auto_lock(current_frame_lock_); | 332 base::AutoLock auto_lock(current_frame_lock_); |
360 if (!current_frame_.get() || !player_) | 333 if (!current_frame_.get() || !player_) |
361 return; | 334 return; |
362 | 335 |
363 // Copy the frame so that rendering can show the last received frame. | 336 // Copy the frame so that rendering can show the last received frame. |
364 // The original frame must not be referenced when the player is paused since | 337 // The original frame must not be referenced when the player is paused since |
365 // there might be a finite number of available buffers. E.g, video that | 338 // there might be a finite number of available buffers. E.g, video that |
366 // originates from a video camera. | 339 // originates from a video camera. |
367 current_frame_ = | 340 current_frame_ = |
368 CopyFrame(current_frame_, player_->GetSkCanvasVideoRenderer()); | 341 CopyFrame(current_frame_, player_->GetSkCanvasVideoRenderer()); |
369 } | 342 } |
370 | 343 |
| 344 void WebMediaPlayerMSCompositor::StopUsingProvider() { |
| 345 DCHECK(thread_checker_.CalledOnValidThread()); |
| 346 compositor_task_runner_->PostTask( |
| 347 FROM_HERE, |
| 348 base::Bind(&WebMediaPlayerMSCompositor::StopUsingProviderInternal, this)); |
| 349 } |
| 350 |
371 bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks( | 351 bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks( |
372 const std::vector<base::TimeDelta>& timestamps, | 352 const std::vector<base::TimeDelta>& timestamps, |
373 std::vector<base::TimeTicks>* wall_clock_times) { | 353 std::vector<base::TimeTicks>* wall_clock_times) { |
374 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || | 354 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || |
375 thread_checker_.CalledOnValidThread()); | 355 thread_checker_.CalledOnValidThread() || |
| 356 io_thread_checker_.CalledOnValidThread()); |
376 for (const base::TimeDelta& timestamp : timestamps) { | 357 for (const base::TimeDelta& timestamp : timestamps) { |
377 DCHECK(timestamps_to_clock_times_.count(timestamp)); | 358 DCHECK(timestamps_to_clock_times_.count(timestamp)); |
378 wall_clock_times->push_back(timestamps_to_clock_times_[timestamp]); | 359 wall_clock_times->push_back(timestamps_to_clock_times_[timestamp]); |
379 } | 360 } |
380 return true; | 361 return true; |
381 } | 362 } |
382 | 363 |
383 void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min, | 364 void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min, |
384 base::TimeTicks deadline_max) { | 365 base::TimeTicks deadline_max) { |
385 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || | 366 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 current_frame_->natural_size() != frame->natural_size(); | 404 current_frame_->natural_size() != frame->natural_size(); |
424 current_frame_ = frame; | 405 current_frame_ = frame; |
425 if (size_changed) { | 406 if (size_changed) { |
426 main_message_loop_->task_runner()->PostTask( | 407 main_message_loop_->task_runner()->PostTask( |
427 FROM_HERE, base::Bind(&WebMediaPlayerMS::TriggerResize, player_)); | 408 FROM_HERE, base::Bind(&WebMediaPlayerMS::TriggerResize, player_)); |
428 } | 409 } |
429 main_message_loop_->task_runner()->PostTask( | 410 main_message_loop_->task_runner()->PostTask( |
430 FROM_HERE, base::Bind(&WebMediaPlayerMS::ResetCanvasCache, player_)); | 411 FROM_HERE, base::Bind(&WebMediaPlayerMS::ResetCanvasCache, player_)); |
431 } | 412 } |
432 | 413 |
| 414 void WebMediaPlayerMSCompositor::StartRenderingInternal() { |
| 415 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); |
| 416 stopped_ = false; |
| 417 |
| 418 if (video_frame_provider_client_) |
| 419 video_frame_provider_client_->StartRendering(); |
| 420 } |
| 421 |
| 422 void WebMediaPlayerMSCompositor::StopRenderingInternal() { |
| 423 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); |
| 424 stopped_ = true; |
| 425 |
| 426 // It is possible that the video gets paused and then resumed. We need to |
| 427 // reset VideoRendererAlgorithm, otherwise, VideoRendererAlgorithm will think |
| 428 // there is a very long frame in the queue and then make totally wrong |
| 429 // frame selection. |
| 430 { |
| 431 base::AutoLock auto_lock(current_frame_lock_); |
| 432 if (rendering_frame_buffer_) |
| 433 rendering_frame_buffer_->Reset(); |
| 434 } |
| 435 |
| 436 if (video_frame_provider_client_) |
| 437 video_frame_provider_client_->StopRendering(); |
| 438 } |
| 439 |
| 440 void WebMediaPlayerMSCompositor::StopUsingProviderInternal() { |
| 441 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); |
| 442 if (video_frame_provider_client_) |
| 443 video_frame_provider_client_->StopUsingProvider(); |
| 444 video_frame_provider_client_ = nullptr; |
| 445 } |
| 446 |
433 void WebMediaPlayerMSCompositor::SetAlgorithmEnabledForTesting( | 447 void WebMediaPlayerMSCompositor::SetAlgorithmEnabledForTesting( |
434 bool algorithm_enabled) { | 448 bool algorithm_enabled) { |
435 if (!algorithm_enabled) { | 449 if (!algorithm_enabled) { |
436 rendering_frame_buffer_.reset(); | 450 rendering_frame_buffer_.reset(); |
437 return; | 451 return; |
438 } | 452 } |
439 | 453 |
440 if (!rendering_frame_buffer_) { | 454 if (!rendering_frame_buffer_) { |
441 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( | 455 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( |
442 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, | 456 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, |
443 base::Unretained(this)))); | 457 base::Unretained(this)))); |
444 } | 458 } |
445 } | 459 } |
446 | 460 |
447 } // namespace content | 461 } // namespace content |
OLD | NEW |