OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "webkit/renderer/media/webmediaplayer_ms.h" | |
6 | |
7 #include <limits> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/callback.h" | |
11 #include "base/message_loop.h" | |
12 #include "base/metrics/histogram.h" | |
13 #include "cc/layers/video_layer.h" | |
14 #include "media/base/media_log.h" | |
15 #include "media/base/video_frame.h" | |
16 #include "third_party/WebKit/public/platform/WebRect.h" | |
17 #include "third_party/WebKit/public/platform/WebSize.h" | |
18 #include "third_party/WebKit/public/platform/WebURL.h" | |
19 #include "third_party/WebKit/public/web/WebFrame.h" | |
20 #include "third_party/WebKit/public/web/WebMediaPlayerClient.h" | |
21 #include "third_party/WebKit/public/web/WebView.h" | |
22 #include "webkit/renderer/compositor_bindings/web_layer_impl.h" | |
23 #include "webkit/renderer/media/media_stream_audio_renderer.h" | |
24 #include "webkit/renderer/media/media_stream_client.h" | |
25 #include "webkit/renderer/media/video_frame_provider.h" | |
26 #include "webkit/renderer/media/webmediaplayer_delegate.h" | |
27 #include "webkit/renderer/media/webmediaplayer_util.h" | |
28 | |
29 using WebKit::WebCanvas; | |
30 using WebKit::WebMediaPlayer; | |
31 using WebKit::WebRect; | |
32 using WebKit::WebSize; | |
33 | |
34 namespace webkit_media { | |
35 | |
36 WebMediaPlayerMS::WebMediaPlayerMS( | |
37 WebKit::WebFrame* frame, | |
38 WebKit::WebMediaPlayerClient* client, | |
39 base::WeakPtr<WebMediaPlayerDelegate> delegate, | |
40 MediaStreamClient* media_stream_client, | |
41 media::MediaLog* media_log) | |
42 : frame_(frame), | |
43 network_state_(WebMediaPlayer::NetworkStateEmpty), | |
44 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), | |
45 buffered_(static_cast<size_t>(1)), | |
46 client_(client), | |
47 delegate_(delegate), | |
48 media_stream_client_(media_stream_client), | |
49 paused_(true), | |
50 current_frame_used_(false), | |
51 pending_repaint_(false), | |
52 video_frame_provider_client_(NULL), | |
53 received_first_frame_(false), | |
54 sequence_started_(false), | |
55 total_frame_count_(0), | |
56 dropped_frame_count_(0), | |
57 media_log_(media_log) { | |
58 DVLOG(1) << "WebMediaPlayerMS::ctor"; | |
59 DCHECK(media_stream_client); | |
60 media_log_->AddEvent( | |
61 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); | |
62 } | |
63 | |
64 WebMediaPlayerMS::~WebMediaPlayerMS() { | |
65 DVLOG(1) << "WebMediaPlayerMS::dtor"; | |
66 DCHECK(thread_checker_.CalledOnValidThread()); | |
67 | |
68 SetVideoFrameProviderClient(NULL); | |
69 GetClient()->setWebLayer(NULL); | |
70 | |
71 if (video_frame_provider_.get()) { | |
72 video_frame_provider_->Stop(); | |
73 } | |
74 | |
75 if (audio_renderer_.get()) { | |
76 if (audio_renderer_->IsLocalRenderer()) { | |
77 audio_renderer_->Stop(); | |
78 } else if (!paused_) { | |
79 // The |audio_renderer_| can be shared by multiple remote streams, and | |
80 // it will be stopped when WebRtcAudioDeviceImpl goes away. So we simply | |
81 // pause the |audio_renderer_| here to avoid re-creating the | |
82 // |audio_renderer_|. | |
83 audio_renderer_->Pause(); | |
84 } | |
85 } | |
86 | |
87 media_log_->AddEvent( | |
88 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); | |
89 | |
90 if (delegate_.get()) | |
91 delegate_->PlayerGone(this); | |
92 } | |
93 | |
94 void WebMediaPlayerMS::load(const WebKit::WebURL& url, CORSMode cors_mode) { | |
95 DVLOG(1) << "WebMediaPlayerMS::load"; | |
96 DCHECK(thread_checker_.CalledOnValidThread()); | |
97 | |
98 GURL gurl(url); | |
99 | |
100 setVolume(GetClient()->volume()); | |
101 SetNetworkState(WebMediaPlayer::NetworkStateLoading); | |
102 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing); | |
103 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec())); | |
104 | |
105 // Check if this url is media stream. | |
106 video_frame_provider_ = media_stream_client_->GetVideoFrameProvider( | |
107 url, | |
108 base::Bind(&WebMediaPlayerMS::OnSourceError, AsWeakPtr()), | |
109 base::Bind(&WebMediaPlayerMS::OnFrameAvailable, AsWeakPtr())); | |
110 | |
111 audio_renderer_ = media_stream_client_->GetAudioRenderer(url); | |
112 | |
113 if (video_frame_provider_.get() || audio_renderer_.get()) { | |
114 GetClient()->setOpaque(true); | |
115 if (audio_renderer_.get()) | |
116 audio_renderer_->Start(); | |
117 | |
118 if (video_frame_provider_.get()) { | |
119 video_frame_provider_->Start(); | |
120 } else { | |
121 // This is audio-only mode. | |
122 DCHECK(audio_renderer_.get()); | |
123 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); | |
124 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | |
125 } | |
126 } else { | |
127 SetNetworkState(WebMediaPlayer::NetworkStateNetworkError); | |
128 } | |
129 } | |
130 | |
131 void WebMediaPlayerMS::load(const WebKit::WebURL& url, | |
132 WebKit::WebMediaSource* media_source, | |
133 CORSMode cors_mode) { | |
134 NOTIMPLEMENTED(); | |
135 } | |
136 | |
137 void WebMediaPlayerMS::play() { | |
138 DVLOG(1) << "WebMediaPlayerMS::play"; | |
139 DCHECK(thread_checker_.CalledOnValidThread()); | |
140 | |
141 if (paused_) { | |
142 if (video_frame_provider_.get()) | |
143 video_frame_provider_->Play(); | |
144 | |
145 if (audio_renderer_.get()) | |
146 audio_renderer_->Play(); | |
147 | |
148 if (delegate_.get()) | |
149 delegate_->DidPlay(this); | |
150 } | |
151 | |
152 paused_ = false; | |
153 | |
154 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY)); | |
155 } | |
156 | |
157 void WebMediaPlayerMS::pause() { | |
158 DVLOG(1) << "WebMediaPlayerMS::pause"; | |
159 DCHECK(thread_checker_.CalledOnValidThread()); | |
160 | |
161 if (video_frame_provider_.get()) | |
162 video_frame_provider_->Pause(); | |
163 | |
164 if (!paused_) { | |
165 if (audio_renderer_.get()) | |
166 audio_renderer_->Pause(); | |
167 | |
168 if (delegate_.get()) | |
169 delegate_->DidPause(this); | |
170 } | |
171 | |
172 paused_ = true; | |
173 | |
174 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE)); | |
175 } | |
176 | |
177 bool WebMediaPlayerMS::supportsFullscreen() const { | |
178 DCHECK(thread_checker_.CalledOnValidThread()); | |
179 return true; | |
180 } | |
181 | |
182 bool WebMediaPlayerMS::supportsSave() const { | |
183 DCHECK(thread_checker_.CalledOnValidThread()); | |
184 return false; | |
185 } | |
186 | |
187 void WebMediaPlayerMS::seek(double seconds) { | |
188 DCHECK(thread_checker_.CalledOnValidThread()); | |
189 } | |
190 | |
191 void WebMediaPlayerMS::setRate(double rate) { | |
192 DCHECK(thread_checker_.CalledOnValidThread()); | |
193 } | |
194 | |
195 void WebMediaPlayerMS::setVolume(double volume) { | |
196 DCHECK(thread_checker_.CalledOnValidThread()); | |
197 if (!audio_renderer_.get()) | |
198 return; | |
199 DVLOG(1) << "WebMediaPlayerMS::setVolume(volume=" << volume << ")"; | |
200 audio_renderer_->SetVolume(volume); | |
201 } | |
202 | |
203 void WebMediaPlayerMS::setPreload(WebMediaPlayer::Preload preload) { | |
204 DCHECK(thread_checker_.CalledOnValidThread()); | |
205 } | |
206 | |
207 bool WebMediaPlayerMS::hasVideo() const { | |
208 DCHECK(thread_checker_.CalledOnValidThread()); | |
209 return (video_frame_provider_.get() != NULL); | |
210 } | |
211 | |
212 bool WebMediaPlayerMS::hasAudio() const { | |
213 DCHECK(thread_checker_.CalledOnValidThread()); | |
214 return (audio_renderer_.get() != NULL); | |
215 } | |
216 | |
217 WebKit::WebSize WebMediaPlayerMS::naturalSize() const { | |
218 DCHECK(thread_checker_.CalledOnValidThread()); | |
219 | |
220 gfx::Size size; | |
221 if (current_frame_.get()) | |
222 size = current_frame_->natural_size(); | |
223 DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size.ToString(); | |
224 return WebKit::WebSize(size); | |
225 } | |
226 | |
227 bool WebMediaPlayerMS::paused() const { | |
228 DCHECK(thread_checker_.CalledOnValidThread()); | |
229 return paused_; | |
230 } | |
231 | |
232 bool WebMediaPlayerMS::seeking() const { | |
233 DCHECK(thread_checker_.CalledOnValidThread()); | |
234 return false; | |
235 } | |
236 | |
237 double WebMediaPlayerMS::duration() const { | |
238 DCHECK(thread_checker_.CalledOnValidThread()); | |
239 return std::numeric_limits<double>::infinity(); | |
240 } | |
241 | |
242 double WebMediaPlayerMS::currentTime() const { | |
243 DCHECK(thread_checker_.CalledOnValidThread()); | |
244 if (current_frame_.get()) { | |
245 return current_frame_->GetTimestamp().InSecondsF(); | |
246 } else if (audio_renderer_.get()) { | |
247 return audio_renderer_->GetCurrentRenderTime().InSecondsF(); | |
248 } | |
249 return 0.0; | |
250 } | |
251 | |
252 WebMediaPlayer::NetworkState WebMediaPlayerMS::networkState() const { | |
253 DCHECK(thread_checker_.CalledOnValidThread()); | |
254 DVLOG(1) << "WebMediaPlayerMS::networkState, state:" << network_state_; | |
255 return network_state_; | |
256 } | |
257 | |
258 WebMediaPlayer::ReadyState WebMediaPlayerMS::readyState() const { | |
259 DCHECK(thread_checker_.CalledOnValidThread()); | |
260 DVLOG(1) << "WebMediaPlayerMS::readyState, state:" << ready_state_; | |
261 return ready_state_; | |
262 } | |
263 | |
264 const WebKit::WebTimeRanges& WebMediaPlayerMS::buffered() { | |
265 DCHECK(thread_checker_.CalledOnValidThread()); | |
266 return buffered_; | |
267 } | |
268 | |
269 double WebMediaPlayerMS::maxTimeSeekable() const { | |
270 DCHECK(thread_checker_.CalledOnValidThread()); | |
271 return 0.0; | |
272 } | |
273 | |
274 bool WebMediaPlayerMS::didLoadingProgress() const { | |
275 DCHECK(thread_checker_.CalledOnValidThread()); | |
276 return true; | |
277 } | |
278 | |
279 void WebMediaPlayerMS::paint(WebCanvas* canvas, | |
280 const WebRect& rect, | |
281 unsigned char alpha) { | |
282 DVLOG(3) << "WebMediaPlayerMS::paint"; | |
283 DCHECK(thread_checker_.CalledOnValidThread()); | |
284 | |
285 gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height); | |
286 video_renderer_.Paint(current_frame_.get(), canvas, dest_rect, alpha); | |
287 | |
288 { | |
289 base::AutoLock auto_lock(current_frame_lock_); | |
290 if (current_frame_.get()) | |
291 current_frame_used_ = true; | |
292 } | |
293 } | |
294 | |
295 bool WebMediaPlayerMS::hasSingleSecurityOrigin() const { | |
296 DCHECK(thread_checker_.CalledOnValidThread()); | |
297 return true; | |
298 } | |
299 | |
300 bool WebMediaPlayerMS::didPassCORSAccessCheck() const { | |
301 DCHECK(thread_checker_.CalledOnValidThread()); | |
302 return true; | |
303 } | |
304 | |
305 double WebMediaPlayerMS::mediaTimeForTimeValue(double timeValue) const { | |
306 return ConvertSecondsToTimestamp(timeValue).InSecondsF(); | |
307 } | |
308 | |
309 unsigned WebMediaPlayerMS::decodedFrameCount() const { | |
310 DCHECK(thread_checker_.CalledOnValidThread()); | |
311 DVLOG(1) << "WebMediaPlayerMS::decodedFrameCount, " << total_frame_count_; | |
312 return total_frame_count_; | |
313 } | |
314 | |
315 unsigned WebMediaPlayerMS::droppedFrameCount() const { | |
316 DCHECK(thread_checker_.CalledOnValidThread()); | |
317 DVLOG(1) << "WebMediaPlayerMS::droppedFrameCount, " << dropped_frame_count_; | |
318 return dropped_frame_count_; | |
319 } | |
320 | |
321 unsigned WebMediaPlayerMS::audioDecodedByteCount() const { | |
322 DCHECK(thread_checker_.CalledOnValidThread()); | |
323 NOTIMPLEMENTED(); | |
324 return 0; | |
325 } | |
326 | |
327 unsigned WebMediaPlayerMS::videoDecodedByteCount() const { | |
328 DCHECK(thread_checker_.CalledOnValidThread()); | |
329 NOTIMPLEMENTED(); | |
330 return 0; | |
331 } | |
332 | |
333 void WebMediaPlayerMS::SetVideoFrameProviderClient( | |
334 cc::VideoFrameProvider::Client* client) { | |
335 // This is called from both the main renderer thread and the compositor | |
336 // thread (when the main thread is blocked). | |
337 if (video_frame_provider_client_) | |
338 video_frame_provider_client_->StopUsingProvider(); | |
339 video_frame_provider_client_ = client; | |
340 } | |
341 | |
342 scoped_refptr<media::VideoFrame> WebMediaPlayerMS::GetCurrentFrame() { | |
343 DVLOG(3) << "WebMediaPlayerMS::GetCurrentFrame"; | |
344 base::AutoLock auto_lock(current_frame_lock_); | |
345 DCHECK(!pending_repaint_); | |
346 if (!current_frame_.get()) | |
347 return NULL; | |
348 pending_repaint_ = true; | |
349 current_frame_used_ = true; | |
350 return current_frame_; | |
351 } | |
352 | |
353 void WebMediaPlayerMS::PutCurrentFrame( | |
354 const scoped_refptr<media::VideoFrame>& frame) { | |
355 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame"; | |
356 DCHECK(pending_repaint_); | |
357 pending_repaint_ = false; | |
358 } | |
359 | |
360 void WebMediaPlayerMS::OnFrameAvailable( | |
361 const scoped_refptr<media::VideoFrame>& frame) { | |
362 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable"; | |
363 DCHECK(thread_checker_.CalledOnValidThread()); | |
364 ++total_frame_count_; | |
365 if (!received_first_frame_) { | |
366 received_first_frame_ = true; | |
367 { | |
368 base::AutoLock auto_lock(current_frame_lock_); | |
369 DCHECK(!current_frame_used_); | |
370 current_frame_ = | |
371 media::VideoFrame::CreateBlackFrame(frame->natural_size()); | |
372 } | |
373 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); | |
374 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | |
375 GetClient()->sizeChanged(); | |
376 | |
377 if (video_frame_provider_.get() && GetClient()->needsWebLayerForVideo()) { | |
378 video_weblayer_.reset( | |
379 new webkit::WebLayerImpl(cc::VideoLayer::Create(this))); | |
380 GetClient()->setWebLayer(video_weblayer_.get()); | |
381 } | |
382 } | |
383 | |
384 // Do not update |current_frame_| when paused. | |
385 if (paused_) | |
386 return; | |
387 | |
388 if (!sequence_started_) { | |
389 sequence_started_ = true; | |
390 start_time_ = frame->GetTimestamp(); | |
391 } | |
392 bool size_changed = !current_frame_.get() || | |
393 current_frame_->natural_size() != frame->natural_size(); | |
394 | |
395 { | |
396 base::AutoLock auto_lock(current_frame_lock_); | |
397 if (!current_frame_used_ && current_frame_.get()) | |
398 ++dropped_frame_count_; | |
399 current_frame_ = frame; | |
400 current_frame_->SetTimestamp(frame->GetTimestamp() - start_time_); | |
401 current_frame_used_ = false; | |
402 } | |
403 | |
404 if (size_changed) | |
405 GetClient()->sizeChanged(); | |
406 | |
407 GetClient()->repaint(); | |
408 } | |
409 | |
410 void WebMediaPlayerMS::RepaintInternal() { | |
411 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal"; | |
412 DCHECK(thread_checker_.CalledOnValidThread()); | |
413 GetClient()->repaint(); | |
414 } | |
415 | |
416 void WebMediaPlayerMS::OnSourceError() { | |
417 DVLOG(1) << "WebMediaPlayerMS::OnSourceError"; | |
418 DCHECK(thread_checker_.CalledOnValidThread()); | |
419 SetNetworkState(WebMediaPlayer::NetworkStateFormatError); | |
420 RepaintInternal(); | |
421 } | |
422 | |
423 void WebMediaPlayerMS::SetNetworkState(WebMediaPlayer::NetworkState state) { | |
424 DCHECK(thread_checker_.CalledOnValidThread()); | |
425 network_state_ = state; | |
426 // Always notify to ensure client has the latest value. | |
427 GetClient()->networkStateChanged(); | |
428 } | |
429 | |
430 void WebMediaPlayerMS::SetReadyState(WebMediaPlayer::ReadyState state) { | |
431 DCHECK(thread_checker_.CalledOnValidThread()); | |
432 ready_state_ = state; | |
433 // Always notify to ensure client has the latest value. | |
434 GetClient()->readyStateChanged(); | |
435 } | |
436 | |
437 WebKit::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() { | |
438 DCHECK(thread_checker_.CalledOnValidThread()); | |
439 DCHECK(client_); | |
440 return client_; | |
441 } | |
442 | |
443 } // namespace webkit_media | |
OLD | NEW |