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 "content/renderer/media/webmediaplayer_ms.h" | 5 #include "content/renderer/media/webmediaplayer_ms.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "cc/blink/context_provider_web_context.h" | 13 #include "cc/blink/context_provider_web_context.h" |
14 #include "cc/blink/web_layer_impl.h" | 14 #include "cc/blink/web_layer_impl.h" |
15 #include "cc/layers/video_frame_provider_client_impl.h" | |
15 #include "cc/layers/video_layer.h" | 16 #include "cc/layers/video_layer.h" |
16 #include "content/public/renderer/media_stream_audio_renderer.h" | 17 #include "content/public/renderer/media_stream_audio_renderer.h" |
17 #include "content/public/renderer/media_stream_renderer_factory.h" | 18 #include "content/public/renderer/media_stream_renderer_factory.h" |
18 #include "content/public/renderer/render_view.h" | 19 #include "content/public/renderer/render_view.h" |
19 #include "content/public/renderer/video_frame_provider.h" | 20 #include "content/public/renderer/video_frame_provider.h" |
20 #include "content/renderer/render_frame_impl.h" | 21 #include "content/renderer/render_frame_impl.h" |
21 #include "content/renderer/render_thread_impl.h" | 22 #include "content/renderer/render_thread_impl.h" |
22 #include "gpu/blink/webgraphicscontext3d_impl.h" | 23 #include "gpu/blink/webgraphicscontext3d_impl.h" |
23 #include "media/base/media_log.h" | 24 #include "media/base/media_log.h" |
24 #include "media/base/video_frame.h" | 25 #include "media/base/video_frame.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 return new_frame; | 87 return new_frame; |
87 } | 88 } |
88 | 89 |
89 } // anonymous namespace | 90 } // anonymous namespace |
90 | 91 |
91 WebMediaPlayerMS::WebMediaPlayerMS( | 92 WebMediaPlayerMS::WebMediaPlayerMS( |
92 blink::WebFrame* frame, | 93 blink::WebFrame* frame, |
93 blink::WebMediaPlayerClient* client, | 94 blink::WebMediaPlayerClient* client, |
94 base::WeakPtr<media::WebMediaPlayerDelegate> delegate, | 95 base::WeakPtr<media::WebMediaPlayerDelegate> delegate, |
95 media::MediaLog* media_log, | 96 media::MediaLog* media_log, |
96 scoped_ptr<MediaStreamRendererFactory> factory) | 97 scoped_ptr<MediaStreamRendererFactory> factory, |
98 scoped_refptr<base::SingleThreadTaskRunner> compositor_thread) | |
97 : frame_(frame), | 99 : frame_(frame), |
98 network_state_(WebMediaPlayer::NetworkStateEmpty), | 100 network_state_(WebMediaPlayer::NetworkStateEmpty), |
99 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), | 101 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), |
100 buffered_(static_cast<size_t>(0)), | 102 buffered_(static_cast<size_t>(0)), |
101 volume_(1.0f), | 103 volume_(1.0f), |
102 client_(client), | 104 client_(client), |
103 delegate_(delegate), | 105 delegate_(delegate), |
104 paused_(true), | 106 paused_(true), |
105 current_frame_used_(false), | 107 current_frame_used_(false), |
106 video_frame_provider_client_(NULL), | 108 video_frame_provider_client_(NULL), |
107 received_first_frame_(false), | 109 received_first_frame_(false), |
108 total_frame_count_(0), | 110 total_frame_count_(0), |
109 dropped_frame_count_(0), | 111 dropped_frame_count_(0), |
110 media_log_(media_log), | 112 media_log_(media_log), |
111 renderer_factory_(factory.Pass()) { | 113 renderer_factory_(factory.Pass()), |
114 compositor_thread_(compositor_thread), | |
115 wait_event_(false,false) { | |
112 DVLOG(1) << "WebMediaPlayerMS::ctor"; | 116 DVLOG(1) << "WebMediaPlayerMS::ctor"; |
113 media_log_->AddEvent( | 117 media_log_->AddEvent( |
114 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); | 118 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); |
115 } | 119 } |
116 | 120 |
117 WebMediaPlayerMS::~WebMediaPlayerMS() { | 121 WebMediaPlayerMS::~WebMediaPlayerMS() { |
118 DVLOG(1) << "WebMediaPlayerMS::dtor"; | 122 DVLOG(1) << "WebMediaPlayerMS::dtor"; |
119 DCHECK(thread_checker_.CalledOnValidThread()); | 123 DCHECK(thread_checker_.CalledOnValidThread()); |
120 | 124 |
121 SetVideoFrameProviderClient(NULL); | 125 // Wait till stop procedure finishes to avoid the case that after |
126 // WebMediaPlayerMS is destroyed, VideoFrameProvider is still trying to access | |
127 // it. | |
128 | |
129 if (video_frame_provider_client_){ | |
130 compositor_thread_->PostTask( | |
131 FROM_HERE, | |
132 base::Bind( | |
133 &WebMediaPlayerMS::StopVideoFrameProviderAndWakeUpHelper, | |
134 video_frame_provider_client_, | |
135 &wait_event_)); | |
136 wait_event_.Wait(); | |
DaleCurtis
2015/08/13 18:06:53
Hmm, this is unfortunate. Typically you'd use Comp
qiangchen
2015/08/14 16:52:50
Done.
| |
137 } | |
138 | |
122 GetClient()->setWebLayer(NULL); | 139 GetClient()->setWebLayer(NULL); |
123 | 140 |
124 if (video_frame_provider_.get()) | 141 if (video_frame_provider_.get()) |
125 video_frame_provider_->Stop(); | 142 video_frame_provider_->Stop(); |
126 | 143 |
127 if (audio_renderer_.get()) | 144 if (audio_renderer_.get()) |
128 audio_renderer_->Stop(); | 145 audio_renderer_->Stop(); |
129 | 146 |
130 media_log_->AddEvent( | 147 media_log_->AddEvent( |
131 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); | 148 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 } | 197 } |
181 | 198 |
182 void WebMediaPlayerMS::play() { | 199 void WebMediaPlayerMS::play() { |
183 DVLOG(1) << "WebMediaPlayerMS::play"; | 200 DVLOG(1) << "WebMediaPlayerMS::play"; |
184 DCHECK(thread_checker_.CalledOnValidThread()); | 201 DCHECK(thread_checker_.CalledOnValidThread()); |
185 | 202 |
186 if (paused_) { | 203 if (paused_) { |
187 if (video_frame_provider_.get()) | 204 if (video_frame_provider_.get()) |
188 video_frame_provider_->Play(); | 205 video_frame_provider_->Play(); |
189 | 206 |
207 if (video_frame_provider_client_){ | |
208 compositor_thread_->PostTask( | |
209 FROM_HERE, | |
210 base::Bind(&WebMediaPlayerMS::StartRenderingHelper, | |
211 video_frame_provider_client_)); | |
212 } | |
213 | |
190 if (audio_renderer_.get()) | 214 if (audio_renderer_.get()) |
191 audio_renderer_->Play(); | 215 audio_renderer_->Play(); |
192 | 216 |
193 if (delegate_.get()) | 217 if (delegate_.get()) |
194 delegate_->DidPlay(this); | 218 delegate_->DidPlay(this); |
195 } | 219 } |
196 | 220 |
197 paused_ = false; | 221 paused_ = false; |
198 | 222 |
199 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY)); | 223 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY)); |
200 } | 224 } |
201 | 225 |
202 void WebMediaPlayerMS::pause() { | 226 void WebMediaPlayerMS::pause() { |
203 DVLOG(1) << "WebMediaPlayerMS::pause"; | 227 DVLOG(1) << "WebMediaPlayerMS::pause"; |
204 DCHECK(thread_checker_.CalledOnValidThread()); | 228 DCHECK(thread_checker_.CalledOnValidThread()); |
205 | 229 |
206 if (video_frame_provider_.get()) | 230 if (video_frame_provider_.get()) |
207 video_frame_provider_->Pause(); | 231 video_frame_provider_->Pause(); |
208 | 232 |
233 if (video_frame_provider_client_){ | |
234 compositor_thread_->PostTask( | |
235 FROM_HERE, | |
236 base::Bind(&WebMediaPlayerMS::StopRenderingHelper, | |
237 video_frame_provider_client_)); | |
238 } | |
239 | |
209 if (!paused_) { | 240 if (!paused_) { |
210 if (audio_renderer_.get()) | 241 if (audio_renderer_.get()) |
211 audio_renderer_->Pause(); | 242 audio_renderer_->Pause(); |
212 | 243 |
213 if (delegate_.get()) | 244 if (delegate_.get()) |
214 delegate_->DidPause(this); | 245 delegate_->DidPause(this); |
215 } | 246 } |
216 | 247 |
217 paused_ = true; | 248 paused_ = true; |
218 | 249 |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha, | 473 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha, |
443 flip_y); | 474 flip_y); |
444 return true; | 475 return true; |
445 } | 476 } |
446 | 477 |
447 void WebMediaPlayerMS::SetVideoFrameProviderClient( | 478 void WebMediaPlayerMS::SetVideoFrameProviderClient( |
448 cc::VideoFrameProvider::Client* client) { | 479 cc::VideoFrameProvider::Client* client) { |
449 // This is called from both the main renderer thread and the compositor | 480 // This is called from both the main renderer thread and the compositor |
450 // thread (when the main thread is blocked). | 481 // thread (when the main thread is blocked). |
451 if (video_frame_provider_client_) | 482 if (video_frame_provider_client_) |
452 video_frame_provider_client_->StopUsingProvider(); | 483 compositor_thread_->PostTask( |
484 FROM_HERE, | |
485 base::Bind( | |
486 &WebMediaPlayerMS::StopVideoFrameProviderHelper, | |
487 video_frame_provider_client_)); | |
488 | |
453 video_frame_provider_client_ = client; | 489 video_frame_provider_client_ = client; |
490 if (client && !paused_) | |
491 compositor_thread_->PostTask( | |
492 FROM_HERE, | |
493 base::Bind(&WebMediaPlayerMS::StartRenderingHelper, | |
494 video_frame_provider_client_)); | |
495 } | |
496 | |
497 void WebMediaPlayerMS::StopVideoFrameProviderAndWakeUpHelper( | |
498 cc::VideoFrameProvider::Client* client, | |
499 base::WaitableEvent* event) { | |
500 client->StopUsingProvider(); | |
501 event->Signal(); | |
502 } | |
503 | |
504 void WebMediaPlayerMS::StopVideoFrameProviderHelper( | |
505 cc::VideoFrameProvider::Client* client) { | |
506 client->StopUsingProvider(); | |
507 } | |
508 | |
509 void WebMediaPlayerMS::StartRenderingHelper( | |
510 cc::VideoFrameProvider::Client* client) { | |
511 client->StartRendering(); | |
512 } | |
513 | |
514 void WebMediaPlayerMS::StopRenderingHelper( | |
515 cc::VideoFrameProvider::Client* client) { | |
516 client->StopRendering(); | |
454 } | 517 } |
455 | 518 |
456 bool WebMediaPlayerMS::UpdateCurrentFrame(base::TimeTicks deadline_min, | 519 bool WebMediaPlayerMS::UpdateCurrentFrame(base::TimeTicks deadline_min, |
457 base::TimeTicks deadline_max) { | 520 base::TimeTicks deadline_max) { |
521 TRACE_EVENT_BEGIN2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame", | |
522 "Actual Render Begin", deadline_min.ToInternalValue(), | |
523 "Actual Render End", deadline_max.ToInternalValue()); | |
524 last_deadline_max_ = deadline_max; | |
525 | |
458 // TODO(dalecurtis): This should make use of the deadline interval to ensure | 526 // TODO(dalecurtis): This should make use of the deadline interval to ensure |
459 // the painted frame is correct for the given interval. | 527 // the painted frame is correct for the given interval. |
460 NOTREACHED(); | 528 |
461 return false; | 529 base::TimeTicks render_time; |
530 if (!current_frame_->metadata()->GetTimeTicks( | |
531 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { | |
532 render_time = base::TimeTicks(); | |
533 } | |
534 TRACE_EVENT_END1("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame", | |
535 "Ideal Render Instant", render_time.ToInternalValue()); | |
536 return !current_frame_used_; | |
462 } | 537 } |
463 | 538 |
464 bool WebMediaPlayerMS::HasCurrentFrame() { | 539 bool WebMediaPlayerMS::HasCurrentFrame() { |
465 base::AutoLock auto_lock(current_frame_lock_); | 540 base::AutoLock auto_lock(current_frame_lock_); |
466 return current_frame_; | 541 return current_frame_; |
467 } | 542 } |
468 | 543 |
469 scoped_refptr<media::VideoFrame> WebMediaPlayerMS::GetCurrentFrame() { | 544 scoped_refptr<media::VideoFrame> WebMediaPlayerMS::GetCurrentFrame() { |
470 DVLOG(3) << "WebMediaPlayerMS::GetCurrentFrame"; | 545 DVLOG(3) << "WebMediaPlayerMS::GetCurrentFrame"; |
471 base::AutoLock auto_lock(current_frame_lock_); | 546 base::AutoLock auto_lock(current_frame_lock_); |
472 if (!current_frame_.get()) | 547 if (!current_frame_.get()) |
473 return NULL; | 548 return NULL; |
474 current_frame_used_ = true; | 549 current_frame_used_ = true; |
475 return current_frame_; | 550 return current_frame_; |
476 } | 551 } |
477 | 552 |
478 void WebMediaPlayerMS::PutCurrentFrame() { | 553 void WebMediaPlayerMS::PutCurrentFrame() { |
479 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame"; | 554 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame"; |
480 } | 555 } |
481 | 556 |
482 void WebMediaPlayerMS::OnFrameAvailable( | 557 void WebMediaPlayerMS::OnFrameAvailable( |
483 const scoped_refptr<media::VideoFrame>& frame) { | 558 const scoped_refptr<media::VideoFrame>& frame) { |
484 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable"; | 559 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable"; |
485 DCHECK(thread_checker_.CalledOnValidThread()); | 560 DCHECK(thread_checker_.CalledOnValidThread()); |
561 | |
562 base::TimeTicks render_time; | |
563 if (!frame->metadata()->GetTimeTicks( | |
564 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { | |
565 render_time = base::TimeTicks(); | |
566 } | |
567 TRACE_EVENT1("webrtc", "WebMediaPlayerMS::OnFrameAvailable", | |
568 "Ideal Render Instant", render_time.ToInternalValue()); | |
569 | |
486 ++total_frame_count_; | 570 ++total_frame_count_; |
487 if (!received_first_frame_) { | 571 if (!received_first_frame_) { |
488 received_first_frame_ = true; | 572 received_first_frame_ = true; |
489 { | 573 { |
490 base::AutoLock auto_lock(current_frame_lock_); | 574 base::AutoLock auto_lock(current_frame_lock_); |
491 DCHECK(!current_frame_used_); | 575 DCHECK(!current_frame_used_); |
492 current_frame_ = frame; | 576 current_frame_ = frame; |
493 } | 577 } |
494 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); | 578 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); |
495 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | 579 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); |
496 GetClient()->sizeChanged(); | 580 GetClient()->sizeChanged(); |
497 | 581 |
498 if (video_frame_provider_.get()) { | 582 if (video_frame_provider_.get()) { |
499 video_weblayer_.reset(new cc_blink::WebLayerImpl( | 583 video_weblayer_.reset(new cc_blink::WebLayerImpl( |
500 cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(), this, | 584 cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(), this, |
501 media::VIDEO_ROTATION_0))); | 585 media::VIDEO_ROTATION_0))); |
502 video_weblayer_->setOpaque(true); | 586 video_weblayer_->setOpaque(true); |
503 GetClient()->setWebLayer(video_weblayer_.get()); | 587 GetClient()->setWebLayer(video_weblayer_.get()); |
504 } | 588 } |
505 } | 589 } |
506 | 590 |
507 // Do not update |current_frame_| when paused. | 591 // Do not update |current_frame_| when paused. |
508 if (paused_) | 592 if (paused_) |
509 return; | 593 return; |
510 | 594 |
595 if (base::TimeTicks::Now() > last_deadline_max_){ | |
596 // TODO(qiangchen): Theoretically Now is between | |
597 // [last_deadline_min_ - vsync_duration, last_deadline_min]. If Now is later | |
598 // than last_deadline_max, it means UpdateCurrentFrame does not get called | |
599 // for 2 vsyncs. A probable cause is that the video tag is invisible, but we | |
600 // have to let old frames go (VRA::RemoveExpiredFrames), otherwise frames | |
601 // will pile up, and when we use up all frame buffers, decoder will be | |
602 // stuck. | |
603 } | |
604 | |
511 bool size_changed = !current_frame_.get() || | 605 bool size_changed = !current_frame_.get() || |
512 current_frame_->natural_size() != frame->natural_size(); | 606 current_frame_->natural_size() != frame->natural_size(); |
513 | 607 |
514 { | 608 { |
515 base::AutoLock auto_lock(current_frame_lock_); | 609 base::AutoLock auto_lock(current_frame_lock_); |
516 if (!current_frame_used_ && current_frame_.get()) | 610 if (!current_frame_used_ && current_frame_.get()) |
517 ++dropped_frame_count_; | 611 ++dropped_frame_count_; |
518 current_frame_ = frame; | 612 current_frame_ = frame; |
519 current_time_ = frame->timestamp(); | 613 current_time_ = frame->timestamp(); |
520 current_frame_used_ = false; | 614 current_frame_used_ = false; |
521 } | 615 } |
522 | 616 |
523 if (size_changed) | 617 if (size_changed) |
524 GetClient()->sizeChanged(); | 618 GetClient()->sizeChanged(); |
525 | |
526 GetClient()->repaint(); | |
527 } | 619 } |
528 | 620 |
529 void WebMediaPlayerMS::RepaintInternal() { | 621 void WebMediaPlayerMS::RepaintInternal() { |
530 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal"; | 622 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal"; |
531 DCHECK(thread_checker_.CalledOnValidThread()); | 623 DCHECK(thread_checker_.CalledOnValidThread()); |
532 GetClient()->repaint(); | 624 GetClient()->repaint(); |
533 } | 625 } |
534 | 626 |
535 void WebMediaPlayerMS::OnSourceError() { | 627 void WebMediaPlayerMS::OnSourceError() { |
536 DVLOG(1) << "WebMediaPlayerMS::OnSourceError"; | 628 DVLOG(1) << "WebMediaPlayerMS::OnSourceError"; |
(...skipping 16 matching lines...) Expand all Loading... | |
553 GetClient()->readyStateChanged(); | 645 GetClient()->readyStateChanged(); |
554 } | 646 } |
555 | 647 |
556 blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() { | 648 blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() { |
557 DCHECK(thread_checker_.CalledOnValidThread()); | 649 DCHECK(thread_checker_.CalledOnValidThread()); |
558 DCHECK(client_); | 650 DCHECK(client_); |
559 return client_; | 651 return client_; |
560 } | 652 } |
561 | 653 |
562 } // namespace content | 654 } // namespace content |
OLD | NEW |