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 <stddef.h> | 7 #include <stddef.h> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
(...skipping 24 matching lines...) Expand all Loading... |
35 #include "third_party/WebKit/public/platform/WebMediaPlayerSource.h" | 35 #include "third_party/WebKit/public/platform/WebMediaPlayerSource.h" |
36 #include "third_party/WebKit/public/platform/WebRect.h" | 36 #include "third_party/WebKit/public/platform/WebRect.h" |
37 #include "third_party/WebKit/public/platform/WebSize.h" | 37 #include "third_party/WebKit/public/platform/WebSize.h" |
38 | 38 |
39 namespace content { | 39 namespace content { |
40 | 40 |
41 // FrameDeliverer is responsible for delivering frames received on | 41 // FrameDeliverer is responsible for delivering frames received on |
42 // compositor thread by calling of EnqueueFrame() method of |compositor_|. | 42 // compositor thread by calling of EnqueueFrame() method of |compositor_|. |
43 // | 43 // |
44 // It is created on the main thread, but methods should be called and class | 44 // It is created on the main thread, but methods should be called and class |
45 // should be destructed on the compositor thread. | 45 // should be destructed on the media thread. |
46 class WebMediaPlayerMS::FrameDeliverer { | 46 class WebMediaPlayerMS::FrameDeliverer { |
47 public: | 47 public: |
48 typedef base::Callback<void(scoped_refptr<media::VideoFrame>)> | |
49 EnqueueFrameCallback; | |
50 | |
51 FrameDeliverer(const base::WeakPtr<WebMediaPlayerMS>& player, | 48 FrameDeliverer(const base::WeakPtr<WebMediaPlayerMS>& player, |
52 const EnqueueFrameCallback& enqueue_frame_cb) | 49 const MediaStreamVideoRenderer::RepaintCB& enqueue_frame_cb) |
53 : last_frame_opaque_(true), | 50 : last_frame_opaque_(true), |
54 last_frame_rotation_(media::VIDEO_ROTATION_0), | 51 last_frame_rotation_(media::VIDEO_ROTATION_0), |
55 received_first_frame_(false), | 52 received_first_frame_(false), |
56 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 53 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
57 player_(player), | 54 player_(player), |
58 enqueue_frame_cb_(enqueue_frame_cb), | 55 enqueue_frame_cb_(enqueue_frame_cb), |
59 weak_factory_for_compositor_(this) { | 56 weak_factory_(this) { |
60 compositor_thread_checker_.DetachFromThread(); | 57 media_thread_checker_.DetachFromThread(); |
61 } | 58 } |
62 | 59 |
63 ~FrameDeliverer() { | 60 ~FrameDeliverer() { DCHECK(media_thread_checker_.CalledOnValidThread()); } |
64 DCHECK(compositor_thread_checker_.CalledOnValidThread()); | |
65 } | |
66 | 61 |
67 void OnVideoFrame(scoped_refptr<media::VideoFrame> frame) { | 62 void OnVideoFrame(scoped_refptr<media::VideoFrame> frame) { |
68 DCHECK(compositor_thread_checker_.CalledOnValidThread()); | 63 DCHECK(media_thread_checker_.CalledOnValidThread()); |
69 | 64 |
70 #if defined(OS_ANDROID) | 65 #if defined(OS_ANDROID) |
71 if (render_frame_suspended_) | 66 if (render_frame_suspended_) |
72 return; | 67 return; |
73 #endif // defined(OS_ANDROID) | 68 #endif // defined(OS_ANDROID) |
74 | 69 |
75 base::TimeTicks render_time; | 70 base::TimeTicks render_time; |
76 if (frame->metadata()->GetTimeTicks( | 71 if (frame->metadata()->GetTimeTicks( |
77 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { | 72 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { |
78 TRACE_EVENT1("webrtc", "WebMediaPlayerMS::OnFrameAvailable", | 73 TRACE_EVENT1("webrtc", "WebMediaPlayerMS::OnFrameAvailable", |
(...skipping 27 matching lines...) Expand all Loading... |
106 FROM_HERE, base::Bind(&WebMediaPlayerMS::OnRotationChanged, player_, | 101 FROM_HERE, base::Bind(&WebMediaPlayerMS::OnRotationChanged, player_, |
107 video_rotation, is_opaque)); | 102 video_rotation, is_opaque)); |
108 } | 103 } |
109 } | 104 } |
110 | 105 |
111 enqueue_frame_cb_.Run(frame); | 106 enqueue_frame_cb_.Run(frame); |
112 } | 107 } |
113 | 108 |
114 #if defined(OS_ANDROID) | 109 #if defined(OS_ANDROID) |
115 void SetRenderFrameSuspended(bool render_frame_suspended) { | 110 void SetRenderFrameSuspended(bool render_frame_suspended) { |
116 DCHECK(compositor_thread_checker_.CalledOnValidThread()); | 111 DCHECK(media_thread_checker_.CalledOnValidThread()); |
117 render_frame_suspended_ = render_frame_suspended; | 112 render_frame_suspended_ = render_frame_suspended; |
118 } | 113 } |
119 #endif // defined(OS_ANDROID) | 114 #endif // defined(OS_ANDROID) |
120 | 115 |
121 MediaStreamVideoRenderer::RepaintCB GetRepaintCallback() { | 116 MediaStreamVideoRenderer::RepaintCB GetRepaintCallback() { |
122 return base::Bind(&FrameDeliverer::OnVideoFrame, | 117 return base::Bind(&FrameDeliverer::OnVideoFrame, |
123 weak_factory_for_compositor_.GetWeakPtr()); | 118 weak_factory_.GetWeakPtr()); |
124 } | 119 } |
125 | 120 |
126 private: | 121 private: |
127 bool last_frame_opaque_; | 122 bool last_frame_opaque_; |
128 media::VideoRotation last_frame_rotation_; | 123 media::VideoRotation last_frame_rotation_; |
129 bool received_first_frame_; | 124 bool received_first_frame_; |
130 | 125 |
131 #if defined(OS_ANDROID) | 126 #if defined(OS_ANDROID) |
132 bool render_frame_suspended_ = false; | 127 bool render_frame_suspended_ = false; |
133 #endif // defined(OS_ANDROID) | 128 #endif // defined(OS_ANDROID) |
134 | 129 |
135 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 130 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
136 const base::WeakPtr<WebMediaPlayerMS> player_; | 131 const base::WeakPtr<WebMediaPlayerMS> player_; |
137 const EnqueueFrameCallback enqueue_frame_cb_; | 132 const MediaStreamVideoRenderer::RepaintCB enqueue_frame_cb_; |
138 | 133 |
139 // Used for DCHECKs to ensure method calls executed on the correct thread, | 134 // Used for DCHECKs to ensure method calls executed on the correct thread, |
140 // i.e. compositor thread. | 135 // i.e. media thread. |
141 base::ThreadChecker compositor_thread_checker_; | 136 base::ThreadChecker media_thread_checker_; |
142 | 137 |
143 base::WeakPtrFactory<FrameDeliverer> weak_factory_for_compositor_; | 138 base::WeakPtrFactory<FrameDeliverer> weak_factory_; |
144 | 139 |
145 DISALLOW_COPY_AND_ASSIGN(FrameDeliverer); | 140 DISALLOW_COPY_AND_ASSIGN(FrameDeliverer); |
146 }; | 141 }; |
147 | 142 |
148 WebMediaPlayerMS::WebMediaPlayerMS( | 143 WebMediaPlayerMS::WebMediaPlayerMS( |
149 blink::WebFrame* frame, | 144 blink::WebFrame* frame, |
150 blink::WebMediaPlayerClient* client, | 145 blink::WebMediaPlayerClient* client, |
151 base::WeakPtr<media::WebMediaPlayerDelegate> delegate, | 146 base::WeakPtr<media::WebMediaPlayerDelegate> delegate, |
152 media::MediaLog* media_log, | 147 media::MediaLog* media_log, |
153 std::unique_ptr<MediaStreamRendererFactory> factory, | 148 std::unique_ptr<MediaStreamRendererFactory> factory, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 WebMediaPlayerMS::~WebMediaPlayerMS() { | 186 WebMediaPlayerMS::~WebMediaPlayerMS() { |
192 DVLOG(1) << __func__; | 187 DVLOG(1) << __func__; |
193 DCHECK(thread_checker_.CalledOnValidThread()); | 188 DCHECK(thread_checker_.CalledOnValidThread()); |
194 | 189 |
195 // Destruct compositor resources in the proper order. | 190 // Destruct compositor resources in the proper order. |
196 get_client()->setWebLayer(nullptr); | 191 get_client()->setWebLayer(nullptr); |
197 if (video_weblayer_) | 192 if (video_weblayer_) |
198 static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider(); | 193 static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider(); |
199 | 194 |
200 if (frame_deliverer_) | 195 if (frame_deliverer_) |
201 compositor_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release()); | 196 media_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release()); |
202 | 197 |
203 if (compositor_) | 198 if (compositor_) |
204 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_.release()); | 199 compositor_->StopUsingProvider(); |
205 | 200 |
206 if (video_frame_provider_) | 201 if (video_frame_provider_) |
207 video_frame_provider_->Stop(); | 202 video_frame_provider_->Stop(); |
208 | 203 |
209 if (audio_renderer_) | 204 if (audio_renderer_) |
210 audio_renderer_->Stop(); | 205 audio_renderer_->Stop(); |
211 | 206 |
212 media_log_->AddEvent( | 207 media_log_->AddEvent( |
213 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); | 208 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); |
214 | 209 |
215 if (delegate_) { | 210 if (delegate_) { |
216 delegate_->PlayerGone(delegate_id_); | 211 delegate_->PlayerGone(delegate_id_); |
217 delegate_->RemoveObserver(delegate_id_); | 212 delegate_->RemoveObserver(delegate_id_); |
218 } | 213 } |
219 } | 214 } |
220 | 215 |
221 void WebMediaPlayerMS::load(LoadType load_type, | 216 void WebMediaPlayerMS::load(LoadType load_type, |
222 const blink::WebMediaPlayerSource& source, | 217 const blink::WebMediaPlayerSource& source, |
223 CORSMode /*cors_mode*/) { | 218 CORSMode /*cors_mode*/) { |
224 DVLOG(1) << __func__; | 219 DVLOG(1) << __func__; |
225 DCHECK(thread_checker_.CalledOnValidThread()); | 220 DCHECK(thread_checker_.CalledOnValidThread()); |
226 | 221 |
227 // TODO(acolwell): Change this to DCHECK_EQ(load_type, LoadTypeMediaStream) | 222 // TODO(acolwell): Change this to DCHECK_EQ(load_type, LoadTypeMediaStream) |
228 // once Blink-side changes land. | 223 // once Blink-side changes land. |
229 DCHECK_NE(load_type, LoadTypeMediaSource); | 224 DCHECK_NE(load_type, LoadTypeMediaSource); |
230 blink::WebMediaStream web_stream = | 225 blink::WebMediaStream web_stream = |
231 GetWebMediaStreamFromWebMediaPlayerSource(source); | 226 GetWebMediaStreamFromWebMediaPlayerSource(source); |
232 | 227 |
233 compositor_.reset(new WebMediaPlayerMSCompositor(compositor_task_runner_, | 228 compositor_ = new WebMediaPlayerMSCompositor(compositor_task_runner_, |
234 web_stream, AsWeakPtr())); | 229 web_stream, AsWeakPtr()); |
235 | 230 |
236 SetNetworkState(WebMediaPlayer::NetworkStateLoading); | 231 SetNetworkState(WebMediaPlayer::NetworkStateLoading); |
237 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing); | 232 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing); |
238 std::string stream_id = | 233 std::string stream_id = |
239 web_stream.isNull() ? std::string() : web_stream.id().utf8(); | 234 web_stream.isNull() ? std::string() : web_stream.id().utf8(); |
240 media_log_->AddEvent(media_log_->CreateLoadEvent(stream_id)); | 235 media_log_->AddEvent(media_log_->CreateLoadEvent(stream_id)); |
241 | 236 |
242 // base::Unretained usage is safe here because |compositor_| is destroyed | |
243 // after |frame_deliverer_|. | |
244 frame_deliverer_.reset(new WebMediaPlayerMS::FrameDeliverer( | 237 frame_deliverer_.reset(new WebMediaPlayerMS::FrameDeliverer( |
245 AsWeakPtr(), base::Bind(&WebMediaPlayerMSCompositor::EnqueueFrame, | 238 AsWeakPtr(), |
246 base::Unretained(compositor_.get())))); | 239 base::Bind(&WebMediaPlayerMSCompositor::EnqueueFrame, compositor_))); |
247 video_frame_provider_ = renderer_factory_->GetVideoRenderer( | 240 video_frame_provider_ = renderer_factory_->GetVideoRenderer( |
248 web_stream, media::BindToCurrentLoop(base::Bind( | 241 web_stream, media::BindToCurrentLoop(base::Bind( |
249 &WebMediaPlayerMS::OnSourceError, AsWeakPtr())), | 242 &WebMediaPlayerMS::OnSourceError, AsWeakPtr())), |
250 frame_deliverer_->GetRepaintCallback(), compositor_task_runner_, | 243 frame_deliverer_->GetRepaintCallback(), media_task_runner_, |
251 media_task_runner_, worker_task_runner_, gpu_factories_); | 244 worker_task_runner_, gpu_factories_); |
252 | 245 |
253 RenderFrame* const frame = RenderFrame::FromWebFrame(frame_); | 246 RenderFrame* const frame = RenderFrame::FromWebFrame(frame_); |
254 | 247 |
255 if (frame) { | 248 if (frame) { |
256 // Report UMA and RAPPOR metrics. | 249 // Report UMA and RAPPOR metrics. |
257 GURL url = source.isURL() ? GURL(source.getAsURL()) : GURL(); | 250 GURL url = source.isURL() ? GURL(source.getAsURL()) : GURL(); |
258 media::ReportMetrics(load_type, url, frame_->getSecurityOrigin()); | 251 media::ReportMetrics(load_type, url, frame_->getSecurityOrigin()); |
259 | 252 |
260 audio_renderer_ = renderer_factory_->GetAudioRenderer( | 253 audio_renderer_ = renderer_factory_->GetAudioRenderer( |
261 web_stream, frame->GetRoutingID(), initial_audio_output_device_id_, | 254 web_stream, frame->GetRoutingID(), initial_audio_output_device_id_, |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 #if defined(OS_ANDROID) | 505 #if defined(OS_ANDROID) |
513 DCHECK(thread_checker_.CalledOnValidThread()); | 506 DCHECK(thread_checker_.CalledOnValidThread()); |
514 | 507 |
515 // Method called when the RenderFrame is sent to background and suspended | 508 // Method called when the RenderFrame is sent to background and suspended |
516 // (android). Substitute the displayed VideoFrame with a copy to avoid | 509 // (android). Substitute the displayed VideoFrame with a copy to avoid |
517 // holding on to it unnecessarily. | 510 // holding on to it unnecessarily. |
518 // | 511 // |
519 // During undoable tab closures OnHidden() may be called back to back, so we | 512 // During undoable tab closures OnHidden() may be called back to back, so we |
520 // can't rely on |render_frame_suspended_| being false here. | 513 // can't rely on |render_frame_suspended_| being false here. |
521 if (frame_deliverer_) { | 514 if (frame_deliverer_) { |
522 compositor_task_runner_->PostTask( | 515 media_task_runner_->PostTask( |
523 FROM_HERE, base::Bind(&FrameDeliverer::SetRenderFrameSuspended, | 516 FROM_HERE, base::Bind(&FrameDeliverer::SetRenderFrameSuspended, |
524 base::Unretained(frame_deliverer_.get()), true)); | 517 base::Unretained(frame_deliverer_.get()), true)); |
525 } | 518 } |
526 | 519 |
527 if (!paused_) | 520 if (!paused_) |
528 compositor_->ReplaceCurrentFrameWithACopy(); | 521 compositor_->ReplaceCurrentFrameWithACopy(); |
529 #endif // defined(OS_ANDROID) | 522 #endif // defined(OS_ANDROID) |
530 } | 523 } |
531 | 524 |
532 void WebMediaPlayerMS::OnShown() { | 525 void WebMediaPlayerMS::OnShown() { |
533 #if defined(OS_ANDROID) | 526 #if defined(OS_ANDROID) |
534 DCHECK(thread_checker_.CalledOnValidThread()); | 527 DCHECK(thread_checker_.CalledOnValidThread()); |
535 | 528 |
536 if (frame_deliverer_) { | 529 if (frame_deliverer_) { |
537 compositor_task_runner_->PostTask( | 530 media_task_runner_->PostTask( |
538 FROM_HERE, base::Bind(&FrameDeliverer::SetRenderFrameSuspended, | 531 FROM_HERE, base::Bind(&FrameDeliverer::SetRenderFrameSuspended, |
539 base::Unretained(frame_deliverer_.get()), false)); | 532 base::Unretained(frame_deliverer_.get()), false)); |
540 } | 533 } |
541 | 534 |
542 // Resume playback on visibility. play() clears |should_play_upon_shown_|. | 535 // Resume playback on visibility. play() clears |should_play_upon_shown_|. |
543 if (should_play_upon_shown_) | 536 if (should_play_upon_shown_) |
544 play(); | 537 play(); |
545 #endif // defined(OS_ANDROID) | 538 #endif // defined(OS_ANDROID) |
546 } | 539 } |
547 | 540 |
548 bool WebMediaPlayerMS::OnSuspendRequested(bool must_suspend) { | 541 bool WebMediaPlayerMS::OnSuspendRequested(bool must_suspend) { |
549 #if defined(OS_ANDROID) | 542 #if defined(OS_ANDROID) |
550 if (!must_suspend) | 543 if (!must_suspend) |
551 return false; | 544 return false; |
552 | 545 |
553 if (!paused_) { | 546 if (!paused_) { |
554 pause(); | 547 pause(); |
555 should_play_upon_shown_ = true; | 548 should_play_upon_shown_ = true; |
556 } | 549 } |
557 | 550 |
558 if (delegate_) | 551 if (delegate_) |
559 delegate_->PlayerGone(delegate_id_); | 552 delegate_->PlayerGone(delegate_id_); |
560 | 553 |
561 if (frame_deliverer_) { | 554 if (frame_deliverer_) { |
562 compositor_task_runner_->PostTask( | 555 media_task_runner_->PostTask( |
563 FROM_HERE, base::Bind(&FrameDeliverer::SetRenderFrameSuspended, | 556 FROM_HERE, base::Bind(&FrameDeliverer::SetRenderFrameSuspended, |
564 base::Unretained(frame_deliverer_.get()), true)); | 557 base::Unretained(frame_deliverer_.get()), true)); |
565 } | 558 } |
566 #endif // defined(OS_ANDROID) | 559 #endif // defined(OS_ANDROID) |
567 return true; | 560 return true; |
568 } | 561 } |
569 | 562 |
570 void WebMediaPlayerMS::OnPlay() { | 563 void WebMediaPlayerMS::OnPlay() { |
571 // TODO(perkj, magjed): It's not clear how WebRTC should work with an | 564 // TODO(perkj, magjed): It's not clear how WebRTC should work with an |
572 // MediaSession, until these issues are resolved, disable session controls. | 565 // MediaSession, until these issues are resolved, disable session controls. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 void WebMediaPlayerMS::ResetCanvasCache() { | 668 void WebMediaPlayerMS::ResetCanvasCache() { |
676 DCHECK(thread_checker_.CalledOnValidThread()); | 669 DCHECK(thread_checker_.CalledOnValidThread()); |
677 video_renderer_.ResetCache(); | 670 video_renderer_.ResetCache(); |
678 } | 671 } |
679 | 672 |
680 void WebMediaPlayerMS::TriggerResize() { | 673 void WebMediaPlayerMS::TriggerResize() { |
681 get_client()->sizeChanged(); | 674 get_client()->sizeChanged(); |
682 } | 675 } |
683 | 676 |
684 } // namespace content | 677 } // namespace content |
OLD | NEW |