| 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" |
| 11 #include "base/hash.h" | 11 #include "base/hash.h" |
| 12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "cc/paint/skia_paint_canvas.h" | 14 #include "cc/paint/skia_paint_canvas.h" |
| 15 #include "content/renderer/media/webmediaplayer_ms.h" | 15 #include "content/renderer/media/webmediaplayer_ms.h" |
| 16 #include "content/renderer/render_thread_impl.h" | 16 #include "content/renderer/render_thread_impl.h" |
| 17 #include "media/base/bind_to_current_loop.h" |
| 17 #include "media/base/media_switches.h" | 18 #include "media/base/media_switches.h" |
| 18 #include "media/base/video_frame.h" | 19 #include "media/base/video_frame.h" |
| 19 #include "media/base/video_util.h" | 20 #include "media/base/video_util.h" |
| 20 #include "media/filters/video_renderer_algorithm.h" | 21 #include "media/filters/video_renderer_algorithm.h" |
| 21 #include "media/renderers/skcanvas_video_renderer.h" | 22 #include "media/renderers/skcanvas_video_renderer.h" |
| 22 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" | 23 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" |
| 23 #include "skia/ext/platform_canvas.h" | 24 #include "skia/ext/platform_canvas.h" |
| 24 #include "third_party/WebKit/public/platform/WebMediaStream.h" | 25 #include "third_party/WebKit/public/platform/WebMediaStream.h" |
| 25 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" | 26 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" |
| 26 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" | 27 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 } | 121 } |
| 121 | 122 |
| 122 // Transfer metadata keys. | 123 // Transfer metadata keys. |
| 123 new_frame->metadata()->MergeMetadataFrom(frame->metadata()); | 124 new_frame->metadata()->MergeMetadataFrom(frame->metadata()); |
| 124 return new_frame; | 125 return new_frame; |
| 125 } | 126 } |
| 126 | 127 |
| 127 } // anonymous namespace | 128 } // anonymous namespace |
| 128 | 129 |
| 129 WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor( | 130 WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor( |
| 130 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, | 131 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, |
| 132 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
| 131 const blink::WebMediaStream& web_stream, | 133 const blink::WebMediaStream& web_stream, |
| 132 const base::WeakPtr<WebMediaPlayerMS>& player) | 134 const base::WeakPtr<WebMediaPlayerMS>& player) |
| 133 : compositor_task_runner_(compositor_task_runner), | 135 : compositor_task_runner_(compositor_task_runner), |
| 136 io_task_runner_(io_task_runner), |
| 134 player_(player), | 137 player_(player), |
| 135 video_frame_provider_client_(nullptr), | 138 video_frame_provider_client_(nullptr), |
| 136 current_frame_used_by_compositor_(false), | 139 current_frame_used_by_compositor_(false), |
| 137 last_render_length_(base::TimeDelta::FromSecondsD(1.0 / 60.0)), | 140 last_render_length_(base::TimeDelta::FromSecondsD(1.0 / 60.0)), |
| 138 total_frame_count_(0), | 141 total_frame_count_(0), |
| 139 dropped_frame_count_(0), | 142 dropped_frame_count_(0), |
| 140 stopped_(true) { | 143 stopped_(true) { |
| 141 main_message_loop_ = base::MessageLoop::current(); | 144 main_message_loop_ = base::MessageLoop::current(); |
| 142 io_thread_checker_.DetachFromThread(); | |
| 143 | 145 |
| 144 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; | 146 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; |
| 145 if (!web_stream.IsNull()) | 147 if (!web_stream.IsNull()) |
| 146 web_stream.VideoTracks(video_tracks); | 148 web_stream.VideoTracks(video_tracks); |
| 147 | 149 |
| 148 const bool remote_video = | 150 const bool remote_video = |
| 149 video_tracks.size() && video_tracks[0].Source().Remote(); | 151 video_tracks.size() && video_tracks[0].Source().Remote(); |
| 150 | 152 |
| 151 if (remote_video && !base::CommandLine::ForCurrentProcess()->HasSwitch( | 153 if (remote_video && !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 152 switches::kDisableRTCSmoothnessAlgorithm)) { | 154 switches::kDisableRTCSmoothnessAlgorithm)) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 if (video_frame_provider_client_) | 203 if (video_frame_provider_client_) |
| 202 video_frame_provider_client_->StopUsingProvider(); | 204 video_frame_provider_client_->StopUsingProvider(); |
| 203 | 205 |
| 204 video_frame_provider_client_ = client; | 206 video_frame_provider_client_ = client; |
| 205 if (video_frame_provider_client_ && !stopped_) | 207 if (video_frame_provider_client_ && !stopped_) |
| 206 video_frame_provider_client_->StartRendering(); | 208 video_frame_provider_client_->StartRendering(); |
| 207 } | 209 } |
| 208 | 210 |
| 209 void WebMediaPlayerMSCompositor::EnqueueFrame( | 211 void WebMediaPlayerMSCompositor::EnqueueFrame( |
| 210 scoped_refptr<media::VideoFrame> frame) { | 212 scoped_refptr<media::VideoFrame> frame) { |
| 211 DCHECK(io_thread_checker_.CalledOnValidThread()); | 213 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 212 base::AutoLock auto_lock(current_frame_lock_); | 214 base::AutoLock auto_lock(current_frame_lock_); |
| 213 ++total_frame_count_; | 215 ++total_frame_count_; |
| 214 | 216 |
| 215 // With algorithm off, just let |current_frame_| hold the incoming |frame|. | 217 // With algorithm off, just let |current_frame_| hold the incoming |frame|. |
| 216 if (!rendering_frame_buffer_) { | 218 if (!rendering_frame_buffer_) { |
| 217 SetCurrentFrame(frame); | 219 SetCurrentFrame(frame); |
| 218 return; | 220 return; |
| 219 } | 221 } |
| 220 | 222 |
| 221 // This is a signal frame saying that the stream is stopped. | 223 // This is a signal frame saying that the stream is stopped. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 | 329 |
| 328 void WebMediaPlayerMSCompositor::StopRendering() { | 330 void WebMediaPlayerMSCompositor::StopRendering() { |
| 329 DCHECK(thread_checker_.CalledOnValidThread()); | 331 DCHECK(thread_checker_.CalledOnValidThread()); |
| 330 compositor_task_runner_->PostTask( | 332 compositor_task_runner_->PostTask( |
| 331 FROM_HERE, | 333 FROM_HERE, |
| 332 base::Bind(&WebMediaPlayerMSCompositor::StopRenderingInternal, this)); | 334 base::Bind(&WebMediaPlayerMSCompositor::StopRenderingInternal, this)); |
| 333 } | 335 } |
| 334 | 336 |
| 335 void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() { | 337 void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() { |
| 336 DCHECK(thread_checker_.CalledOnValidThread()); | 338 DCHECK(thread_checker_.CalledOnValidThread()); |
| 337 base::AutoLock auto_lock(current_frame_lock_); | 339 // Bounce this call off of IO thread to since there might still be frames |
| 338 if (!current_frame_.get() || !player_) | 340 // passed on IO thread. |
| 339 return; | 341 io_task_runner_->PostTask( |
| 340 | 342 FROM_HERE, |
| 341 // Copy the frame so that rendering can show the last received frame. | 343 media::BindToCurrentLoop(base::Bind( |
| 342 // The original frame must not be referenced when the player is paused since | 344 &WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal, |
| 343 // there might be a finite number of available buffers. E.g, video that | 345 this))); |
| 344 // originates from a video camera. | |
| 345 current_frame_ = | |
| 346 CopyFrame(current_frame_, player_->GetSkCanvasVideoRenderer()); | |
| 347 } | 346 } |
| 348 | 347 |
| 349 void WebMediaPlayerMSCompositor::StopUsingProvider() { | 348 void WebMediaPlayerMSCompositor::StopUsingProvider() { |
| 350 DCHECK(thread_checker_.CalledOnValidThread()); | 349 DCHECK(thread_checker_.CalledOnValidThread()); |
| 351 compositor_task_runner_->PostTask( | 350 compositor_task_runner_->PostTask( |
| 352 FROM_HERE, | 351 FROM_HERE, |
| 353 base::Bind(&WebMediaPlayerMSCompositor::StopUsingProviderInternal, this)); | 352 base::Bind(&WebMediaPlayerMSCompositor::StopUsingProviderInternal, this)); |
| 354 } | 353 } |
| 355 | 354 |
| 356 bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks( | 355 bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks( |
| 357 const std::vector<base::TimeDelta>& timestamps, | 356 const std::vector<base::TimeDelta>& timestamps, |
| 358 std::vector<base::TimeTicks>* wall_clock_times) { | 357 std::vector<base::TimeTicks>* wall_clock_times) { |
| 359 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || | 358 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || |
| 360 thread_checker_.CalledOnValidThread() || | 359 thread_checker_.CalledOnValidThread() || |
| 361 io_thread_checker_.CalledOnValidThread()); | 360 io_task_runner_->BelongsToCurrentThread()); |
| 362 for (const base::TimeDelta& timestamp : timestamps) { | 361 for (const base::TimeDelta& timestamp : timestamps) { |
| 363 DCHECK(timestamps_to_clock_times_.count(timestamp)); | 362 DCHECK(timestamps_to_clock_times_.count(timestamp)); |
| 364 wall_clock_times->push_back(timestamps_to_clock_times_[timestamp]); | 363 wall_clock_times->push_back(timestamps_to_clock_times_[timestamp]); |
| 365 } | 364 } |
| 366 return true; | 365 return true; |
| 367 } | 366 } |
| 368 | 367 |
| 369 void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min, | 368 void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min, |
| 370 base::TimeTicks deadline_max) { | 369 base::TimeTicks deadline_max) { |
| 371 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || | 370 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 video_frame_provider_client_->StopRendering(); | 441 video_frame_provider_client_->StopRendering(); |
| 443 } | 442 } |
| 444 | 443 |
| 445 void WebMediaPlayerMSCompositor::StopUsingProviderInternal() { | 444 void WebMediaPlayerMSCompositor::StopUsingProviderInternal() { |
| 446 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 445 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); |
| 447 if (video_frame_provider_client_) | 446 if (video_frame_provider_client_) |
| 448 video_frame_provider_client_->StopUsingProvider(); | 447 video_frame_provider_client_->StopUsingProvider(); |
| 449 video_frame_provider_client_ = nullptr; | 448 video_frame_provider_client_ = nullptr; |
| 450 } | 449 } |
| 451 | 450 |
| 451 void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal() { |
| 452 DCHECK(thread_checker_.CalledOnValidThread()); |
| 453 base::AutoLock auto_lock(current_frame_lock_); |
| 454 if (!current_frame_.get() || !player_) |
| 455 return; |
| 456 |
| 457 // Copy the frame so that rendering can show the last received frame. |
| 458 // The original frame must not be referenced when the player is paused since |
| 459 // there might be a finite number of available buffers. E.g, video that |
| 460 // originates from a video camera, HW decoded frames. |
| 461 current_frame_ = |
| 462 CopyFrame(current_frame_, player_->GetSkCanvasVideoRenderer()); |
| 463 } |
| 464 |
| 452 void WebMediaPlayerMSCompositor::SetAlgorithmEnabledForTesting( | 465 void WebMediaPlayerMSCompositor::SetAlgorithmEnabledForTesting( |
| 453 bool algorithm_enabled) { | 466 bool algorithm_enabled) { |
| 454 if (!algorithm_enabled) { | 467 if (!algorithm_enabled) { |
| 455 rendering_frame_buffer_.reset(); | 468 rendering_frame_buffer_.reset(); |
| 456 return; | 469 return; |
| 457 } | 470 } |
| 458 | 471 |
| 459 if (!rendering_frame_buffer_) { | 472 if (!rendering_frame_buffer_) { |
| 460 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( | 473 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( |
| 461 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, | 474 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, |
| 462 base::Unretained(this)), | 475 base::Unretained(this)), |
| 463 &media_log_)); | 476 &media_log_)); |
| 464 } | 477 } |
| 465 } | 478 } |
| 466 | 479 |
| 467 } // namespace content | 480 } // namespace content |
| OLD | NEW |