Chromium Code Reviews| 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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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) { | 138 provider_in_use_(false) { |
| 139 main_message_loop_ = base::MessageLoop::current(); | 139 main_message_loop_ = base::MessageLoop::current(); |
| 140 media_thread_checker_.DetachFromThread(); | |
| 140 | 141 |
| 141 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; | 142 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; |
| 142 if (!web_stream.isNull()) | 143 if (!web_stream.isNull()) |
| 143 web_stream.videoTracks(video_tracks); | 144 web_stream.videoTracks(video_tracks); |
| 144 | 145 |
| 145 const bool remote_video = | 146 const bool remote_video = |
| 146 video_tracks.size() && video_tracks[0].source().remote(); | 147 video_tracks.size() && video_tracks[0].source().remote(); |
| 147 | 148 |
| 148 if (remote_video && | 149 if (remote_video && |
| 149 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 150 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 150 switches::kDisableRTCSmoothnessAlgorithm)) { | 151 switches::kDisableRTCSmoothnessAlgorithm)) { |
| 151 base::AutoLock auto_lock(current_frame_lock_); | 152 base::AutoLock auto_lock(current_frame_lock_); |
| 152 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( | 153 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( |
| 153 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, | 154 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, |
| 154 base::Unretained(this)))); | 155 base::Unretained(this)))); |
| 155 } | 156 } |
| 156 | 157 |
| 157 // Just for logging purpose. | 158 // Just for logging purpose. |
| 158 std::string stream_id = | 159 std::string stream_id = |
| 159 web_stream.isNull() ? std::string() : web_stream.id().utf8(); | 160 web_stream.isNull() ? std::string() : web_stream.id().utf8(); |
| 160 const uint32_t hash_value = base::Hash(stream_id); | 161 const uint32_t hash_value = base::Hash(stream_id); |
| 161 serial_ = (hash_value << 1) | (remote_video ? 1 : 0); | 162 serial_ = (hash_value << 1) | (remote_video ? 1 : 0); |
| 162 } | 163 } |
| 163 | 164 |
| 164 WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() { | 165 WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() { |
| 165 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 166 DCHECK(!provider_in_use_) << "Must call StopUsingProvider() before dtor!"; |
| 166 if (video_frame_provider_client_) | |
| 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 15 matching lines...) Expand all Loading... | |
| 193 | 192 |
| 194 void WebMediaPlayerMSCompositor::SetVideoFrameProviderClient( | 193 void WebMediaPlayerMSCompositor::SetVideoFrameProviderClient( |
| 195 cc::VideoFrameProvider::Client* client) { | 194 cc::VideoFrameProvider::Client* client) { |
| 196 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 195 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); |
| 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(); |
| 202 provider_in_use_ = true; | |
| 203 } | 203 } |
| 204 | 204 |
| 205 void WebMediaPlayerMSCompositor::EnqueueFrame( | 205 void WebMediaPlayerMSCompositor::EnqueueFrame( |
| 206 scoped_refptr<media::VideoFrame> frame) { | 206 scoped_refptr<media::VideoFrame> frame) { |
| 207 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | 207 DCHECK(media_thread_checker_.CalledOnValidThread()); |
| 208 base::AutoLock auto_lock(current_frame_lock_); | 208 base::AutoLock auto_lock(current_frame_lock_); |
| 209 ++total_frame_count_; | 209 ++total_frame_count_; |
| 210 | 210 |
| 211 // With algorithm off, just let |current_frame_| hold the incoming |frame|. | 211 // With algorithm off, just let |current_frame_| hold the incoming |frame|. |
| 212 if (!rendering_frame_buffer_) { | 212 if (!rendering_frame_buffer_) { |
| 213 SetCurrentFrame(frame); | 213 SetCurrentFrame(frame); |
| 214 return; | 214 return; |
| 215 } | 215 } |
| 216 | 216 |
| 217 // This is a signal frame saying that the stream is stopped. | 217 // 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> | 310 scoped_refptr<media::VideoFrame> |
| 311 WebMediaPlayerMSCompositor::GetCurrentFrameWithoutUpdatingStatistics() { | 311 WebMediaPlayerMSCompositor::GetCurrentFrameWithoutUpdatingStatistics() { |
| 312 DVLOG(3) << __func__; | 312 DVLOG(3) << __func__; |
| 313 base::AutoLock auto_lock(current_frame_lock_); | 313 base::AutoLock auto_lock(current_frame_lock_); |
| 314 return current_frame_; | 314 return current_frame_; |
| 315 } | 315 } |
| 316 | 316 |
| 317 void WebMediaPlayerMSCompositor::StartRendering() { | 317 void WebMediaPlayerMSCompositor::StartRendering() { |
| 318 DCHECK(thread_checker_.CalledOnValidThread()); | 318 DCHECK(thread_checker_.CalledOnValidThread()); |
| 319 compositor_task_runner_->PostTask( | 319 compositor_task_runner_->PostTask( |
| 320 FROM_HERE, base::Bind(&WebMediaPlayerMSCompositor::StartRenderingInternal, | 320 FROM_HERE, |
| 321 weak_ptr_factory_.GetWeakPtr())); | 321 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 } | 322 } |
| 331 | 323 |
| 332 void WebMediaPlayerMSCompositor::StopRendering() { | 324 void WebMediaPlayerMSCompositor::StopRendering() { |
| 333 DCHECK(thread_checker_.CalledOnValidThread()); | 325 DCHECK(thread_checker_.CalledOnValidThread()); |
| 334 compositor_task_runner_->PostTask( | 326 compositor_task_runner_->PostTask( |
| 335 FROM_HERE, base::Bind(&WebMediaPlayerMSCompositor::StopRenderingInternal, | 327 FROM_HERE, |
| 336 weak_ptr_factory_.GetWeakPtr())); | 328 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 } | 329 } |
| 356 | 330 |
| 357 void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() { | 331 void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() { |
| 358 DCHECK(thread_checker_.CalledOnValidThread()); | 332 DCHECK(thread_checker_.CalledOnValidThread()); |
| 359 base::AutoLock auto_lock(current_frame_lock_); | 333 base::AutoLock auto_lock(current_frame_lock_); |
| 360 if (!current_frame_.get() || !player_) | 334 if (!current_frame_.get() || !player_) |
| 361 return; | 335 return; |
| 362 | 336 |
| 363 // Copy the frame so that rendering can show the last received frame. | 337 // 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 | 338 // 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 | 339 // there might be a finite number of available buffers. E.g, video that |
| 366 // originates from a video camera. | 340 // originates from a video camera. |
| 367 current_frame_ = | 341 current_frame_ = |
| 368 CopyFrame(current_frame_, player_->GetSkCanvasVideoRenderer()); | 342 CopyFrame(current_frame_, player_->GetSkCanvasVideoRenderer()); |
| 369 } | 343 } |
| 370 | 344 |
| 345 void WebMediaPlayerMSCompositor::StopUsingProvider() { | |
| 346 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 347 compositor_task_runner_->PostTask( | |
| 348 FROM_HERE, | |
| 349 base::Bind(&WebMediaPlayerMSCompositor::StopUsingProviderInternal, this)); | |
| 350 } | |
| 351 | |
| 371 bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks( | 352 bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks( |
| 372 const std::vector<base::TimeDelta>& timestamps, | 353 const std::vector<base::TimeDelta>& timestamps, |
| 373 std::vector<base::TimeTicks>* wall_clock_times) { | 354 std::vector<base::TimeTicks>* wall_clock_times) { |
| 374 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || | 355 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || |
| 375 thread_checker_.CalledOnValidThread()); | 356 thread_checker_.CalledOnValidThread() || |
| 357 media_thread_checker_.CalledOnValidThread()); | |
| 376 for (const base::TimeDelta& timestamp : timestamps) { | 358 for (const base::TimeDelta& timestamp : timestamps) { |
| 377 DCHECK(timestamps_to_clock_times_.count(timestamp)); | 359 DCHECK(timestamps_to_clock_times_.count(timestamp)); |
| 378 wall_clock_times->push_back(timestamps_to_clock_times_[timestamp]); | 360 wall_clock_times->push_back(timestamps_to_clock_times_[timestamp]); |
| 379 } | 361 } |
| 380 return true; | 362 return true; |
| 381 } | 363 } |
| 382 | 364 |
| 383 void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min, | 365 void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min, |
| 384 base::TimeTicks deadline_max) { | 366 base::TimeTicks deadline_max) { |
| 385 DCHECK(compositor_task_runner_->BelongsToCurrentThread() || | 367 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(); | 405 current_frame_->natural_size() != frame->natural_size(); |
| 424 current_frame_ = frame; | 406 current_frame_ = frame; |
| 425 if (size_changed) { | 407 if (size_changed) { |
| 426 main_message_loop_->task_runner()->PostTask( | 408 main_message_loop_->task_runner()->PostTask( |
| 427 FROM_HERE, base::Bind(&WebMediaPlayerMS::TriggerResize, player_)); | 409 FROM_HERE, base::Bind(&WebMediaPlayerMS::TriggerResize, player_)); |
| 428 } | 410 } |
| 429 main_message_loop_->task_runner()->PostTask( | 411 main_message_loop_->task_runner()->PostTask( |
| 430 FROM_HERE, base::Bind(&WebMediaPlayerMS::ResetCanvasCache, player_)); | 412 FROM_HERE, base::Bind(&WebMediaPlayerMS::ResetCanvasCache, player_)); |
| 431 } | 413 } |
| 432 | 414 |
| 415 void WebMediaPlayerMSCompositor::StartRenderingInternal() { | |
|
qiangchen
2016/12/05 18:54:57
I think it is better to put these two functions wh
qiangchen
2016/12/06 17:48:17
Acknowledged.
| |
| 416 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
| 417 stopped_ = false; | |
| 418 | |
| 419 if (video_frame_provider_client_) | |
| 420 video_frame_provider_client_->StartRendering(); | |
| 421 } | |
| 422 | |
| 423 void WebMediaPlayerMSCompositor::StopRenderingInternal() { | |
| 424 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
| 425 stopped_ = true; | |
| 426 | |
| 427 // It is possible that the video gets paused and then resumed. We need to | |
| 428 // reset VideoRendererAlgorithm, otherwise, VideoRendererAlgorithm will think | |
| 429 // there is a very long frame in the queue and then make totally wrong | |
| 430 // frame selection. | |
| 431 { | |
| 432 base::AutoLock auto_lock(current_frame_lock_); | |
| 433 if (rendering_frame_buffer_) | |
| 434 rendering_frame_buffer_->Reset(); | |
| 435 } | |
| 436 | |
| 437 if (video_frame_provider_client_) | |
| 438 video_frame_provider_client_->StopRendering(); | |
| 439 } | |
| 440 | |
| 441 void WebMediaPlayerMSCompositor::StopUsingProviderInternal() { | |
| 442 DCHECK(compositor_task_runner_->BelongsToCurrentThread()); | |
| 443 provider_in_use_ = false; | |
| 444 if (video_frame_provider_client_) | |
| 445 video_frame_provider_client_->StopUsingProvider(); | |
| 446 } | |
| 447 | |
| 433 void WebMediaPlayerMSCompositor::SetAlgorithmEnabledForTesting( | 448 void WebMediaPlayerMSCompositor::SetAlgorithmEnabledForTesting( |
| 434 bool algorithm_enabled) { | 449 bool algorithm_enabled) { |
| 435 if (!algorithm_enabled) { | 450 if (!algorithm_enabled) { |
| 436 rendering_frame_buffer_.reset(); | 451 rendering_frame_buffer_.reset(); |
| 437 return; | 452 return; |
| 438 } | 453 } |
| 439 | 454 |
| 440 if (!rendering_frame_buffer_) { | 455 if (!rendering_frame_buffer_) { |
| 441 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( | 456 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( |
| 442 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, | 457 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, |
| 443 base::Unretained(this)))); | 458 base::Unretained(this)))); |
| 444 } | 459 } |
| 445 } | 460 } |
| 446 | 461 |
| 447 } // namespace content | 462 } // namespace content |
| OLD | NEW |