1 // Copyright (c) 2012 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.
5 #include "webkit/media/webmediaplayer_ms.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/Source/Platform/chromium/public/WebRect.h"
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
18 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
22 #include "webkit/compositor_bindings/web_layer_impl.h"
23 #include "webkit/media/media_stream_audio_renderer.h"
24 #include "webkit/media/media_stream_client.h"
25 #include "webkit/media/video_frame_provider.h"
26 #include "webkit/media/webmediaplayer_delegate.h"
27 #include "webkit/media/webmediaplayer_util.h"
29 using WebKit::WebCanvas
;
30 using WebKit::WebMediaPlayer
;
31 using WebKit::WebRect
;
32 using WebKit::WebSize
;
34 namespace webkit_media
{
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
)
43 network_state_(WebMediaPlayer::NetworkStateEmpty
),
44 ready_state_(WebMediaPlayer::ReadyStateHaveNothing
),
45 buffered_(static_cast<size_t>(1)),
48 media_stream_client_(media_stream_client
),
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
);
61 media_log_
->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED
));
64 WebMediaPlayerMS::~WebMediaPlayerMS() {
65 DVLOG(1) << "WebMediaPlayerMS::dtor";
66 DCHECK(thread_checker_
.CalledOnValidThread());
68 SetVideoFrameProviderClient(NULL
);
69 GetClient()->setWebLayer(NULL
);
71 if (video_frame_provider_
) {
72 video_frame_provider_
->Stop();
75 if (audio_renderer_
) {
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
83 audio_renderer_
->Pause();
88 media_log_
->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED
));
91 delegate_
->PlayerGone(this);
94 void WebMediaPlayerMS::load(const WebKit::WebURL
& url
, CORSMode cors_mode
) {
95 DVLOG(1) << "WebMediaPlayerMS::load";
96 DCHECK(thread_checker_
.CalledOnValidThread());
100 setVolume(GetClient()->volume());
101 SetNetworkState(WebMediaPlayer::NetworkStateLoading
);
102 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing
);
103 media_log_
->AddEvent(media_log_
->CreateLoadEvent(url
.spec()));
105 // Check if this url is media stream.
106 video_frame_provider_
= media_stream_client_
->GetVideoFrameProvider(
108 base::Bind(&WebMediaPlayerMS::OnSourceError
, AsWeakPtr()),
109 base::Bind(&WebMediaPlayerMS::OnFrameAvailable
, AsWeakPtr()));
111 audio_renderer_
= media_stream_client_
->GetAudioRenderer(url
);
113 if (video_frame_provider_
|| audio_renderer_
) {
114 GetClient()->setOpaque(true);
116 audio_renderer_
->Start();
118 if (video_frame_provider_
) {
119 video_frame_provider_
->Start();
121 // This is audio-only mode.
122 DCHECK(audio_renderer_
);
123 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata
);
124 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData
);
127 SetNetworkState(WebMediaPlayer::NetworkStateNetworkError
);
131 void WebMediaPlayerMS::load(const WebKit::WebURL
& url
,
132 WebKit::WebMediaSource
* media_source
,
133 CORSMode cors_mode
) {
137 void WebMediaPlayerMS::cancelLoad() {
138 DCHECK(thread_checker_
.CalledOnValidThread());
141 void WebMediaPlayerMS::play() {
142 DVLOG(1) << "WebMediaPlayerMS::play";
143 DCHECK(thread_checker_
.CalledOnValidThread());
145 if (video_frame_provider_
&& paused_
)
146 video_frame_provider_
->Play();
148 if (audio_renderer_
&& paused_
)
149 audio_renderer_
->Play();
153 media_log_
->AddEvent(media_log_
->CreateEvent(media::MediaLogEvent::PLAY
));
156 delegate_
->DidPlay(this);
159 void WebMediaPlayerMS::pause() {
160 DVLOG(1) << "WebMediaPlayerMS::pause";
161 DCHECK(thread_checker_
.CalledOnValidThread());
163 if (video_frame_provider_
)
164 video_frame_provider_
->Pause();
166 if (audio_renderer_
&& !paused_
)
167 audio_renderer_
->Pause();
171 media_log_
->AddEvent(media_log_
->CreateEvent(media::MediaLogEvent::PAUSE
));
174 delegate_
->DidPause(this);
177 bool WebMediaPlayerMS::supportsFullscreen() const {
178 DCHECK(thread_checker_
.CalledOnValidThread());
182 bool WebMediaPlayerMS::supportsSave() const {
183 DCHECK(thread_checker_
.CalledOnValidThread());
187 void WebMediaPlayerMS::seekFloat(float seconds
) {
191 void WebMediaPlayerMS::seek(float seconds
) {
192 DCHECK(thread_checker_
.CalledOnValidThread());
195 void WebMediaPlayerMS::setEndTimeFloat(float seconds
) {
199 void WebMediaPlayerMS::setEndTime(float seconds
) {
200 DCHECK(thread_checker_
.CalledOnValidThread());
203 void WebMediaPlayerMS::setRateFloat(float rate
) {
207 void WebMediaPlayerMS::setRate(float rate
) {
208 DCHECK(thread_checker_
.CalledOnValidThread());
211 void WebMediaPlayerMS::setVolumeFloat(float volume
) {
215 void WebMediaPlayerMS::setVolume(float volume
) {
216 DCHECK(thread_checker_
.CalledOnValidThread());
217 if (!audio_renderer_
)
219 DVLOG(1) << "WebMediaPlayerMS::setVolume(volume=" << volume
<< ")";
220 audio_renderer_
->SetVolume(volume
);
223 void WebMediaPlayerMS::setVisible(bool visible
) {
224 DCHECK(thread_checker_
.CalledOnValidThread());
227 void WebMediaPlayerMS::setPreload(WebMediaPlayer::Preload preload
) {
228 DCHECK(thread_checker_
.CalledOnValidThread());
231 bool WebMediaPlayerMS::totalBytesKnown() {
232 DCHECK(thread_checker_
.CalledOnValidThread());
236 bool WebMediaPlayerMS::hasVideo() const {
237 DCHECK(thread_checker_
.CalledOnValidThread());
238 return (video_frame_provider_
!= NULL
);
241 bool WebMediaPlayerMS::hasAudio() const {
242 DCHECK(thread_checker_
.CalledOnValidThread());
243 return (audio_renderer_
!= NULL
);
246 WebKit::WebSize
WebMediaPlayerMS::naturalSize() const {
247 DCHECK(thread_checker_
.CalledOnValidThread());
251 size
= current_frame_
->natural_size();
252 DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size
.ToString();
253 return WebKit::WebSize(size
);
256 bool WebMediaPlayerMS::paused() const {
257 DCHECK(thread_checker_
.CalledOnValidThread());
261 bool WebMediaPlayerMS::seeking() const {
262 DCHECK(thread_checker_
.CalledOnValidThread());
266 float WebMediaPlayerMS::durationFloat() const {
270 float WebMediaPlayerMS::duration() const {
271 DCHECK(thread_checker_
.CalledOnValidThread());
272 return std::numeric_limits
<float>::infinity();
275 float WebMediaPlayerMS::currentTimeFloat() const {
276 return currentTime();
279 float WebMediaPlayerMS::currentTime() const {
280 DCHECK(thread_checker_
.CalledOnValidThread());
281 if (current_frame_
.get()) {
282 return current_frame_
->GetTimestamp().InSecondsF();
283 } else if (audio_renderer_
) {
284 return audio_renderer_
->GetCurrentRenderTime().InSecondsF();
289 int WebMediaPlayerMS::dataRate() const {
290 DCHECK(thread_checker_
.CalledOnValidThread());
294 WebMediaPlayer::NetworkState
WebMediaPlayerMS::networkState() const {
295 DCHECK(thread_checker_
.CalledOnValidThread());
296 DVLOG(1) << "WebMediaPlayerMS::networkState, state:" << network_state_
;
297 return network_state_
;
300 WebMediaPlayer::ReadyState
WebMediaPlayerMS::readyState() const {
301 DCHECK(thread_checker_
.CalledOnValidThread());
302 DVLOG(1) << "WebMediaPlayerMS::readyState, state:" << ready_state_
;
306 const WebKit::WebTimeRanges
& WebMediaPlayerMS::buffered() {
307 DCHECK(thread_checker_
.CalledOnValidThread());
311 float WebMediaPlayerMS::maxTimeSeekableFloat() const {
312 return maxTimeSeekable();
315 float WebMediaPlayerMS::maxTimeSeekable() const {
316 DCHECK(thread_checker_
.CalledOnValidThread());
320 bool WebMediaPlayerMS::didLoadingProgress() const {
321 DCHECK(thread_checker_
.CalledOnValidThread());
325 unsigned long long WebMediaPlayerMS::totalBytes() const {
326 DCHECK(thread_checker_
.CalledOnValidThread());
330 void WebMediaPlayerMS::setSize(const WebSize
& size
) {
331 DCHECK(thread_checker_
.CalledOnValidThread());
332 // Don't need to do anything as we use the dimensions passed in via paint().
335 void WebMediaPlayerMS::paint(WebCanvas
* canvas
,
338 DVLOG(3) << "WebMediaPlayerMS::paint";
339 DCHECK(thread_checker_
.CalledOnValidThread());
341 gfx::RectF
dest_rect(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
342 video_renderer_
.Paint(current_frame_
, canvas
, dest_rect
, alpha
);
345 base::AutoLock
auto_lock(current_frame_lock_
);
346 if (current_frame_
.get())
347 current_frame_used_
= true;
351 bool WebMediaPlayerMS::hasSingleSecurityOrigin() const {
352 DCHECK(thread_checker_
.CalledOnValidThread());
356 bool WebMediaPlayerMS::didPassCORSAccessCheck() const {
357 DCHECK(thread_checker_
.CalledOnValidThread());
361 WebMediaPlayer::MovieLoadType
WebMediaPlayerMS::movieLoadType() const {
362 DCHECK(thread_checker_
.CalledOnValidThread());
363 return WebMediaPlayer::MovieLoadTypeUnknown
;
366 float WebMediaPlayerMS::mediaTimeForTimeValueFloat(float timeValue
) const {
367 return mediaTimeForTimeValue(timeValue
);
370 float WebMediaPlayerMS::mediaTimeForTimeValue(float timeValue
) const {
371 return ConvertSecondsToTimestamp(timeValue
).InSecondsF();
374 unsigned WebMediaPlayerMS::decodedFrameCount() const {
375 DCHECK(thread_checker_
.CalledOnValidThread());
376 DVLOG(1) << "WebMediaPlayerMS::decodedFrameCount, " << total_frame_count_
;
377 return total_frame_count_
;
380 unsigned WebMediaPlayerMS::droppedFrameCount() const {
381 DCHECK(thread_checker_
.CalledOnValidThread());
382 DVLOG(1) << "WebMediaPlayerMS::droppedFrameCount, " << dropped_frame_count_
;
383 return dropped_frame_count_
;
386 unsigned WebMediaPlayerMS::audioDecodedByteCount() const {
387 DCHECK(thread_checker_
.CalledOnValidThread());
392 unsigned WebMediaPlayerMS::videoDecodedByteCount() const {
393 DCHECK(thread_checker_
.CalledOnValidThread());
398 void WebMediaPlayerMS::SetVideoFrameProviderClient(
399 cc::VideoFrameProvider::Client
* client
) {
400 // This is called from both the main renderer thread and the compositor
401 // thread (when the main thread is blocked).
402 if (video_frame_provider_client_
)
403 video_frame_provider_client_
->StopUsingProvider();
404 video_frame_provider_client_
= client
;
407 scoped_refptr
<media::VideoFrame
> WebMediaPlayerMS::GetCurrentFrame() {
408 DVLOG(3) << "WebMediaPlayerMS::GetCurrentFrame";
409 base::AutoLock
auto_lock(current_frame_lock_
);
410 DCHECK(!pending_repaint_
);
413 pending_repaint_
= true;
414 current_frame_used_
= true;
415 return current_frame_
;
418 void WebMediaPlayerMS::PutCurrentFrame(
419 const scoped_refptr
<media::VideoFrame
>& frame
) {
420 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame";
421 DCHECK(pending_repaint_
);
422 pending_repaint_
= false;
425 void WebMediaPlayerMS::OnFrameAvailable(
426 const scoped_refptr
<media::VideoFrame
>& frame
) {
427 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable";
428 DCHECK(thread_checker_
.CalledOnValidThread());
429 ++total_frame_count_
;
430 if (!received_first_frame_
) {
431 received_first_frame_
= true;
433 base::AutoLock
auto_lock(current_frame_lock_
);
434 DCHECK(!current_frame_used_
);
436 media::VideoFrame::CreateBlackFrame(frame
->natural_size());
438 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata
);
439 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData
);
440 GetClient()->sizeChanged();
442 if (video_frame_provider_
&& GetClient()->needsWebLayerForVideo()) {
443 video_weblayer_
.reset(
444 new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
445 GetClient()->setWebLayer(video_weblayer_
.get());
449 // Do not update |current_frame_| when paused.
453 if (!sequence_started_
) {
454 sequence_started_
= true;
455 start_time_
= frame
->GetTimestamp();
457 bool size_changed
= !current_frame_
||
458 current_frame_
->natural_size() != frame
->natural_size();
461 base::AutoLock
auto_lock(current_frame_lock_
);
462 if (!current_frame_used_
&& current_frame_
.get())
463 ++dropped_frame_count_
;
464 current_frame_
= frame
;
465 current_frame_
->SetTimestamp(frame
->GetTimestamp() - start_time_
);
466 current_frame_used_
= false;
470 GetClient()->sizeChanged();
472 GetClient()->repaint();
475 void WebMediaPlayerMS::RepaintInternal() {
476 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal";
477 DCHECK(thread_checker_
.CalledOnValidThread());
478 GetClient()->repaint();
481 void WebMediaPlayerMS::OnSourceError() {
482 DVLOG(1) << "WebMediaPlayerMS::OnSourceError";
483 DCHECK(thread_checker_
.CalledOnValidThread());
484 SetNetworkState(WebMediaPlayer::NetworkStateFormatError
);
488 void WebMediaPlayerMS::SetNetworkState(WebMediaPlayer::NetworkState state
) {
489 DCHECK(thread_checker_
.CalledOnValidThread());
490 network_state_
= state
;
491 // Always notify to ensure client has the latest value.
492 GetClient()->networkStateChanged();
495 void WebMediaPlayerMS::SetReadyState(WebMediaPlayer::ReadyState state
) {
496 DCHECK(thread_checker_
.CalledOnValidThread());
497 ready_state_
= state
;
498 // Always notify to ensure client has the latest value.
499 GetClient()->readyStateChanged();
502 WebKit::WebMediaPlayerClient
* WebMediaPlayerMS::GetClient() {
503 DCHECK(thread_checker_
.CalledOnValidThread());
508 } // namespace webkit_media