1 // Copyright (c) 2009 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 "config.h"
6 #include "WebMediaPlayerClientImpl.h"
7
8 #include "WebDocument.h"
9 #include "WebFrameClient.h"
10 #include "WebFrameImpl.h"
11 #include "WebHelperPluginImpl.h"
12 #include "WebViewImpl.h"
13 #include "core/frame/Frame.h"
14 #include "core/html/HTMLMediaElement.h"
15 #include "core/html/HTMLMediaSource.h"
16 #include "core/html/TimeRanges.h"
17 #include "core/rendering/RenderLayerCompositor.h"
18 #include "core/rendering/RenderView.h"
19 #include "modules/mediastream/MediaStreamRegistry.h"
20 #include "platform/audio/AudioBus.h"
21 #include "platform/audio/AudioSourceProviderClient.h"
22 #include "platform/geometry/IntSize.h"
23 #include "platform/graphics/GraphicsContext.h"
24 #include "platform/graphics/GraphicsContext3D.h"
25 #include "platform/graphics/GraphicsLayer.h"
26 #include "platform/graphics/skia/GaneshUtils.h"
27 #include "public/platform/WebAudioSourceProvider.h"
28 #include "public/platform/WebCString.h"
29 #include "public/platform/WebCanvas.h"
30 #include "public/platform/WebCompositorSupport.h"
31 #include "public/platform/WebInbandTextTrack.h"
32 #include "public/platform/WebMediaPlayer.h"
33 #include "public/platform/WebRect.h"
34 #include "public/platform/WebString.h"
35 #include "public/platform/WebURL.h"
36
37 #if OS(ANDROID)
38 #include "GrContext.h"
39 #include "GrTypes.h"
40 #include "SkCanvas.h"
41 #include "SkGrPixelRef.h"
42 #include "platform/graphics/gpu/SharedGraphicsContext3D.h"
43 #endif
44
45
46 #include "wtf/Assertions.h"
47 #include "wtf/text/CString.h"
48
49 using namespace WebCore;
50
51 namespace blink {
52
createWebMediaPlayer(WebMediaPlayerClient * client,const WebURL & url,Frame * frame)53 static PassOwnPtr<WebMediaPlayer> createWebMediaPlayer(WebMediaPlayerClient* client, const WebURL& url, Frame* frame)
54 {
55 WebFrameImpl* webFrame = WebFrameImpl::fromFrame(frame);
56
57 if (!webFrame->client())
58 return nullptr;
59 return adoptPtr(webFrame->client()->createMediaPlayer(webFrame, url, client));
60 }
61
mediaPlayer() const62 WebMediaPlayer* WebMediaPlayerClientImpl::mediaPlayer() const
63 {
64 return m_webMediaPlayer.get();
65 }
66
67 // WebMediaPlayerClient --------------------------------------------------------
68
~WebMediaPlayerClientImpl()69 WebMediaPlayerClientImpl::~WebMediaPlayerClientImpl()
70 {
71 // Explicitly destroy the WebMediaPlayer to allow verification of tear down.
72 m_webMediaPlayer.clear();
73
74 // Ensure the m_webMediaPlayer destroyed any WebHelperPlugin used.
75 ASSERT(!m_helperPlugin);
76 }
77
networkStateChanged()78 void WebMediaPlayerClientImpl::networkStateChanged()
79 {
80 m_client->mediaPlayerNetworkStateChanged();
81 }
82
readyStateChanged()83 void WebMediaPlayerClientImpl::readyStateChanged()
84 {
85 m_client->mediaPlayerReadyStateChanged();
86 }
87
timeChanged()88 void WebMediaPlayerClientImpl::timeChanged()
89 {
90 m_client->mediaPlayerTimeChanged();
91 }
92
repaint()93 void WebMediaPlayerClientImpl::repaint()
94 {
95 m_client->mediaPlayerRepaint();
96 }
97
durationChanged()98 void WebMediaPlayerClientImpl::durationChanged()
99 {
100 m_client->mediaPlayerDurationChanged();
101 }
102
sizeChanged()103 void WebMediaPlayerClientImpl::sizeChanged()
104 {
105 m_client->mediaPlayerSizeChanged();
106 }
107
setOpaque(bool opaque)108 void WebMediaPlayerClientImpl::setOpaque(bool opaque)
109 {
110 m_client->mediaPlayerSetOpaque(opaque);
111 }
112
volume() const113 double WebMediaPlayerClientImpl::volume() const
114 {
115 return m_volume;
116 }
117
playbackStateChanged()118 void WebMediaPlayerClientImpl::playbackStateChanged()
119 {
120 m_client->mediaPlayerPlaybackStateChanged();
121 }
122
preload() const123 WebMediaPlayer::Preload WebMediaPlayerClientImpl::preload() const
124 {
125 return static_cast<WebMediaPlayer::Preload>(m_preload);
126 }
127
keyAdded(const WebString & keySystem,const WebString & sessionId)128 void WebMediaPlayerClientImpl::keyAdded(const WebString& keySystem, const WebString& sessionId)
129 {
130 m_client->mediaPlayerKeyAdded(keySystem, sessionId);
131 }
132
keyError(const WebString & keySystem,const WebString & sessionId,MediaKeyErrorCode errorCode,unsigned short systemCode)133 void WebMediaPlayerClientImpl::keyError(const WebString& keySystem, const WebString& sessionId, MediaKeyErrorCode errorCode, unsigned short systemCode)
134 {
135 m_client->mediaPlayerKeyError(keySystem, sessionId, static_cast<MediaPlayerClient::MediaKeyErrorCode>(errorCode), systemCode);
136 }
137
keyMessage(const WebString & keySystem,const WebString & sessionId,const unsigned char * message,unsigned messageLength,const WebURL & defaultURL)138 void WebMediaPlayerClientImpl::keyMessage(const WebString& keySystem, const WebString& sessionId, const unsigned char* message, unsigned messageLength, const WebURL& defaultURL)
139 {
140 m_client->mediaPlayerKeyMessage(keySystem, sessionId, message, messageLength, defaultURL);
141 }
142
keyNeeded(const WebString & keySystem,const WebString & sessionId,const unsigned char * initData,unsigned initDataLength)143 void WebMediaPlayerClientImpl::keyNeeded(const WebString& keySystem, const WebString& sessionId, const unsigned char* initData, unsigned initDataLength)
144 {
145 m_client->mediaPlayerKeyNeeded(keySystem, sessionId, initData, initDataLength);
146 }
147
createHelperPlugin(const WebString & pluginType,WebFrame * frame)148 WebPlugin* WebMediaPlayerClientImpl::createHelperPlugin(const WebString& pluginType, WebFrame* frame)
149 {
150 ASSERT(!m_helperPlugin);
151
152 m_helperPlugin = toWebViewImpl(frame->view())->createHelperPlugin(pluginType, frame->document());
153 if (!m_helperPlugin)
154 return 0;
155
156 WebPlugin* plugin = m_helperPlugin->getPlugin();
157 if (!plugin) {
158 // There is no need to keep the helper plugin around and the caller
159 // should not be expected to call close after a failure (null pointer).
160 closeHelperPluginSoon(frame);
161 return 0;
162 }
163
164 return plugin;
165 }
166
167
closeHelperPluginSoon(WebFrame * frame)168 void WebMediaPlayerClientImpl::closeHelperPluginSoon(WebFrame* frame)
169 {
170 ASSERT(m_helperPlugin);
171 toWebViewImpl(frame->view())->closeHelperPluginSoon(m_helperPlugin.release());
172 }
173
setWebLayer(blink::WebLayer * layer)174 void WebMediaPlayerClientImpl::setWebLayer(blink::WebLayer* layer)
175 {
176 m_client->mediaPlayerSetWebLayer(layer);
177 }
178
addTextTrack(WebInbandTextTrack * textTrack)179 void WebMediaPlayerClientImpl::addTextTrack(WebInbandTextTrack* textTrack)
180 {
181 m_client->mediaPlayerDidAddTrack(textTrack);
182 }
183
removeTextTrack(WebInbandTextTrack * textTrack)184 void WebMediaPlayerClientImpl::removeTextTrack(WebInbandTextTrack* textTrack)
185 {
186 m_client->mediaPlayerDidRemoveTrack(textTrack);
187 }
188
mediaSourceOpened(WebMediaSource * webMediaSource)189 void WebMediaPlayerClientImpl::mediaSourceOpened(WebMediaSource* webMediaSource)
190 {
191 ASSERT(webMediaSource);
192 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource));
193 m_mediaSource = 0;
194 }
195
requestFullscreen()196 void WebMediaPlayerClientImpl::requestFullscreen()
197 {
198 m_client->mediaPlayerRequestFullscreen();
199 }
200
requestSeek(double time)201 void WebMediaPlayerClientImpl::requestSeek(double time)
202 {
203 m_client->mediaPlayerRequestSeek(time);
204 }
205
206 // MediaPlayer -------------------------------------------------
207
load(const String & url)208 void WebMediaPlayerClientImpl::load(const String& url)
209 {
210 m_url = KURL(ParsedURLString, url);
211 m_mediaSource = 0;
212 loadRequested();
213 }
214
load(const String & url,PassRefPtr<WebCore::HTMLMediaSource> mediaSource)215 void WebMediaPlayerClientImpl::load(const String& url, PassRefPtr<WebCore::HTMLMediaSource> mediaSource)
216 {
217 m_url = KURL(ParsedURLString, url);
218 m_mediaSource = mediaSource;
219 loadRequested();
220 }
221
loadRequested()222 void WebMediaPlayerClientImpl::loadRequested()
223 {
224 if (m_preload == MediaPlayer::None) {
225 #if ENABLE(WEB_AUDIO)
226 m_audioSourceProvider.wrap(0); // Clear weak reference to m_webMediaPlayer's WebAudioSourceProvider.
227 #endif
228 m_webMediaPlayer.clear();
229 m_delayingLoad = true;
230 } else
231 loadInternal();
232 }
233
loadInternal()234 void WebMediaPlayerClientImpl::loadInternal()
235 {
236 m_isMediaStream = WebCore::MediaStreamRegistry::registry().lookupMediaStreamDescriptor(m_url.string());
237
238 #if ENABLE(WEB_AUDIO)
239 m_audioSourceProvider.wrap(0); // Clear weak reference to m_webMediaPlayer's WebAudioSourceProvider.
240 #endif
241
242 // FIXME: Remove this cast
243 Frame* frame = static_cast<HTMLMediaElement*>(m_client)->document().frame();
244
245 // This does not actually check whether the hardware can support accelerated
246 // compositing, but only if the flag is set. However, this is checked lazily
247 // in WebViewImpl::setIsAcceleratedCompositingActive() and will fail there
248 // if necessary.
249 m_needsWebLayerForVideo = frame->contentRenderer()->compositor()->hasAcceleratedCompositing();
250
251 m_webMediaPlayer = createWebMediaPlayer(this, m_url, frame);
252 if (m_webMediaPlayer) {
253 #if ENABLE(WEB_AUDIO)
254 // Make sure if we create/re-create the WebMediaPlayer that we update our wrapper.
255 m_audioSourceProvider.wrap(m_webMediaPlayer->audioSourceProvider());
256 #endif
257
258 WebMediaPlayer::LoadType loadType = WebMediaPlayer::LoadTypeURL;
259
260 if (m_mediaSource)
261 loadType = WebMediaPlayer::LoadTypeMediaSource;
262 else if (m_isMediaStream)
263 loadType = WebMediaPlayer::LoadTypeMediaStream;
264
265 WebMediaPlayer::CORSMode corsMode = static_cast<WebMediaPlayer::CORSMode>(m_client->mediaPlayerCORSMode());
266 m_webMediaPlayer->load(loadType, m_url, corsMode);
267 }
268 }
269
play()270 void WebMediaPlayerClientImpl::play()
271 {
272 if (m_webMediaPlayer)
273 m_webMediaPlayer->play();
274 }
275
pause()276 void WebMediaPlayerClientImpl::pause()
277 {
278 if (m_webMediaPlayer)
279 m_webMediaPlayer->pause();
280 }
281
showFullscreenOverlay()282 void WebMediaPlayerClientImpl::showFullscreenOverlay()
283 {
284 if (m_webMediaPlayer)
285 m_webMediaPlayer->enterFullscreen();
286 }
287
hideFullscreenOverlay()288 void WebMediaPlayerClientImpl::hideFullscreenOverlay()
289 {
290 if (m_webMediaPlayer)
291 m_webMediaPlayer->exitFullscreen();
292 }
293
canShowFullscreenOverlay() const294 bool WebMediaPlayerClientImpl::canShowFullscreenOverlay() const
295 {
296 return m_webMediaPlayer && m_webMediaPlayer->canEnterFullscreen();
297 }
298
generateKeyRequest(const String & keySystem,const unsigned char * initData,unsigned initDataLength)299 MediaPlayer::MediaKeyException WebMediaPlayerClientImpl::generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength)
300 {
301 if (!m_webMediaPlayer)
302 return MediaPlayer::InvalidPlayerState;
303
304 WebMediaPlayer::MediaKeyException result = m_webMediaPlayer->generateKeyRequest(keySystem, initData, initDataLength);
305 return static_cast<MediaPlayer::MediaKeyException>(result);
306 }
307
addKey(const String & keySystem,const unsigned char * key,unsigned keyLength,const unsigned char * initData,unsigned initDataLength,const String & sessionId)308 MediaPlayer::MediaKeyException WebMediaPlayerClientImpl::addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId)
309 {
310 if (!m_webMediaPlayer)
311 return MediaPlayer::InvalidPlayerState;
312
313 WebMediaPlayer::MediaKeyException result = m_webMediaPlayer->addKey(keySystem, key, keyLength, initData, initDataLength, sessionId);
314 return static_cast<MediaPlayer::MediaKeyException>(result);
315 }
316
cancelKeyRequest(const String & keySystem,const String & sessionId)317 MediaPlayer::MediaKeyException WebMediaPlayerClientImpl::cancelKeyRequest(const String& keySystem, const String& sessionId)
318 {
319 if (!m_webMediaPlayer)
320 return MediaPlayer::InvalidPlayerState;
321
322 WebMediaPlayer::MediaKeyException result = m_webMediaPlayer->cancelKeyRequest(keySystem, sessionId);
323 return static_cast<MediaPlayer::MediaKeyException>(result);
324 }
325
prepareToPlay()326 void WebMediaPlayerClientImpl::prepareToPlay()
327 {
328 if (m_delayingLoad)
329 startDelayedLoad();
330 }
331
naturalSize() const332 IntSize WebMediaPlayerClientImpl::naturalSize() const
333 {
334 if (m_webMediaPlayer)
335 return m_webMediaPlayer->naturalSize();
336 return IntSize();
337 }
338
hasVideo() const339 bool WebMediaPlayerClientImpl::hasVideo() const
340 {
341 if (m_webMediaPlayer)
342 return m_webMediaPlayer->hasVideo();
343 return false;
344 }
345
hasAudio() const346 bool WebMediaPlayerClientImpl::hasAudio() const
347 {
348 if (m_webMediaPlayer)
349 return m_webMediaPlayer->hasAudio();
350 return false;
351 }
352
duration() const353 double WebMediaPlayerClientImpl::duration() const
354 {
355 if (m_webMediaPlayer)
356 return m_webMediaPlayer->duration();
357 return 0.0;
358 }
359
currentTime() const360 double WebMediaPlayerClientImpl::currentTime() const
361 {
362 if (m_webMediaPlayer)
363 return m_webMediaPlayer->currentTime();
364 return 0.0;
365 }
366
seek(double time)367 void WebMediaPlayerClientImpl::seek(double time)
368 {
369 if (m_webMediaPlayer)
370 m_webMediaPlayer->seek(time);
371 }
372
seeking() const373 bool WebMediaPlayerClientImpl::seeking() const
374 {
375 if (m_webMediaPlayer)
376 return m_webMediaPlayer->seeking();
377 return false;
378 }
379
rate() const380 double WebMediaPlayerClientImpl::rate() const
381 {
382 return m_rate;
383 }
384
setRate(double rate)385 void WebMediaPlayerClientImpl::setRate(double rate)
386 {
387 m_rate = rate;
388 if (m_webMediaPlayer)
389 m_webMediaPlayer->setRate(rate);
390 }
391
paused() const392 bool WebMediaPlayerClientImpl::paused() const
393 {
394 if (m_webMediaPlayer)
395 return m_webMediaPlayer->paused();
396 return false;
397 }
398
supportsFullscreen() const399 bool WebMediaPlayerClientImpl::supportsFullscreen() const
400 {
401 if (m_webMediaPlayer)
402 return m_webMediaPlayer->supportsFullscreen();
403 return false;
404 }
405
supportsSave() const406 bool WebMediaPlayerClientImpl::supportsSave() const
407 {
408 if (m_webMediaPlayer)
409 return m_webMediaPlayer->supportsSave();
410 return false;
411 }
412
setVolume(double volume)413 void WebMediaPlayerClientImpl::setVolume(double volume)
414 {
415 m_volume = volume;
416 if (m_webMediaPlayer && !m_muted)
417 m_webMediaPlayer->setVolume(volume);
418 }
419
setMuted(bool muted)420 void WebMediaPlayerClientImpl::setMuted(bool muted)
421 {
422 m_muted = muted;
423 if (m_webMediaPlayer)
424 m_webMediaPlayer->setVolume(muted ? 0 : m_volume);
425 }
426
networkState() const427 MediaPlayer::NetworkState WebMediaPlayerClientImpl::networkState() const
428 {
429 if (m_webMediaPlayer)
430 return static_cast<MediaPlayer::NetworkState>(m_webMediaPlayer->networkState());
431 return MediaPlayer::Empty;
432 }
433
readyState() const434 MediaPlayer::ReadyState WebMediaPlayerClientImpl::readyState() const
435 {
436 if (m_webMediaPlayer)
437 return static_cast<MediaPlayer::ReadyState>(m_webMediaPlayer->readyState());
438 return MediaPlayer::HaveNothing;
439 }
440
maxTimeSeekable() const441 double WebMediaPlayerClientImpl::maxTimeSeekable() const
442 {
443 if (m_webMediaPlayer)
444 return m_webMediaPlayer->maxTimeSeekable();
445 return 0.0;
446 }
447
buffered() const448 PassRefPtr<TimeRanges> WebMediaPlayerClientImpl::buffered() const
449 {
450 if (m_webMediaPlayer)
451 return TimeRanges::create(m_webMediaPlayer->buffered());
452 return TimeRanges::create();
453 }
454
didLoadingProgress() const455 bool WebMediaPlayerClientImpl::didLoadingProgress() const
456 {
457 return m_webMediaPlayer && m_webMediaPlayer->didLoadingProgress();
458 }
459
paint(GraphicsContext * context,const IntRect & rect)460 void WebMediaPlayerClientImpl::paint(GraphicsContext* context, const IntRect& rect)
461 {
462 // Normally GraphicsContext operations do nothing when painting is disabled.
463 // Since we're accessing platformContext() directly we have to manually
464 // check.
465 if (m_webMediaPlayer && !context->paintingDisabled()) {
466 // On Android, video frame is emitted as GL_TEXTURE_EXTERNAL_OES texture. We use a different path to
467 // paint the video frame into the context.
468 #if OS(ANDROID)
469 if (!m_isMediaStream) {
470 RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get();
471 paintOnAndroid(context, context3D.get(), rect, context->getNormalizedAlpha());
472 return;
473 }
474 #endif
475 WebCanvas* canvas = context->canvas();
476 m_webMediaPlayer->paint(canvas, rect, context->getNormalizedAlpha());
477 }
478 }
479
copyVideoTextureToPlatformTexture(WebCore::GraphicsContext3D * context,Platform3DObject texture,GC3Dint level,GC3Denum type,GC3Denum internalFormat,bool premultiplyAlpha,bool flipY)480 bool WebMediaPlayerClientImpl::copyVideoTextureToPlatformTexture(WebCore::GraphicsContext3D* context, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY)
481 {
482 if (!context || !m_webMediaPlayer)
483 return false;
484 Extensions3D* extensions = context->extensions();
485 if (!extensions || !extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy")
486 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, type, level) || !context->makeContextCurrent())
487 return false;
488 WebGraphicsContext3D* webGraphicsContext3D = context->webContext();
489 return m_webMediaPlayer->copyVideoTextureToPlatformTexture(webGraphicsContext3D, texture, level, internalFormat, type, premultiplyAlpha, flipY);
490 }
491
setPreload(MediaPlayer::Preload preload)492 void WebMediaPlayerClientImpl::setPreload(MediaPlayer::Preload preload)
493 {
494 m_preload = preload;
495
496 if (m_webMediaPlayer)
497 m_webMediaPlayer->setPreload(static_cast<WebMediaPlayer::Preload>(preload));
498
499 if (m_delayingLoad && m_preload != MediaPlayer::None)
500 startDelayedLoad();
501 }
502
hasSingleSecurityOrigin() const503 bool WebMediaPlayerClientImpl::hasSingleSecurityOrigin() const
504 {
505 if (m_webMediaPlayer)
506 return m_webMediaPlayer->hasSingleSecurityOrigin();
507 return false;
508 }
509
didPassCORSAccessCheck() const510 bool WebMediaPlayerClientImpl::didPassCORSAccessCheck() const
511 {
512 if (m_webMediaPlayer)
513 return m_webMediaPlayer->didPassCORSAccessCheck();
514 return false;
515 }
516
mediaTimeForTimeValue(double timeValue) const517 double WebMediaPlayerClientImpl::mediaTimeForTimeValue(double timeValue) const
518 {
519 if (m_webMediaPlayer)
520 return m_webMediaPlayer->mediaTimeForTimeValue(timeValue);
521 return timeValue;
522 }
523
decodedFrameCount() const524 unsigned WebMediaPlayerClientImpl::decodedFrameCount() const
525 {
526 if (m_webMediaPlayer)
527 return m_webMediaPlayer->decodedFrameCount();
528 return 0;
529 }
530
droppedFrameCount() const531 unsigned WebMediaPlayerClientImpl::droppedFrameCount() const
532 {
533 if (m_webMediaPlayer)
534 return m_webMediaPlayer->droppedFrameCount();
535 return 0;
536 }
537
corruptedFrameCount() const538 unsigned WebMediaPlayerClientImpl::corruptedFrameCount() const
539 {
540 if (m_webMediaPlayer)
541 return m_webMediaPlayer->corruptedFrameCount();
542 return 0;
543 }
544
audioDecodedByteCount() const545 unsigned WebMediaPlayerClientImpl::audioDecodedByteCount() const
546 {
547 if (m_webMediaPlayer)
548 return m_webMediaPlayer->audioDecodedByteCount();
549 return 0;
550 }
551
videoDecodedByteCount() const552 unsigned WebMediaPlayerClientImpl::videoDecodedByteCount() const
553 {
554 if (m_webMediaPlayer)
555 return m_webMediaPlayer->videoDecodedByteCount();
556 return 0;
557 }
558
559 #if ENABLE(WEB_AUDIO)
audioSourceProvider()560 AudioSourceProvider* WebMediaPlayerClientImpl::audioSourceProvider()
561 {
562 return &m_audioSourceProvider;
563 }
564 #endif
565
needsWebLayerForVideo() const566 bool WebMediaPlayerClientImpl::needsWebLayerForVideo() const
567 {
568 return m_needsWebLayerForVideo;
569 }
570
create(MediaPlayerClient * client)571 PassOwnPtr<MediaPlayer> WebMediaPlayerClientImpl::create(MediaPlayerClient* client)
572 {
573 return adoptPtr(new WebMediaPlayerClientImpl(client));
574 }
575
576 #if OS(ANDROID)
paintOnAndroid(WebCore::GraphicsContext * context,WebCore::GraphicsContext3D * context3D,const IntRect & rect,uint8_t alpha)577 void WebMediaPlayerClientImpl::paintOnAndroid(WebCore::GraphicsContext* context, WebCore::GraphicsContext3D* context3D, const IntRect& rect, uint8_t alpha)
578 {
579 if (!context || !context3D || !m_webMediaPlayer || context->paintingDisabled())
580 return;
581
582 Extensions3D* extensions = context3D->extensions();
583 if (!extensions || !extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy")
584 || !context3D->makeContextCurrent())
585 return;
586
587 // Copy video texture into a RGBA texture based bitmap first as video texture on Android is GL_TEXTURE_EXTERNAL_OES
588 // which is not supported by Skia yet. The bitmap's size needs to be the same as the video and use naturalSize() here.
589 // Check if we could reuse existing texture based bitmap.
590 // Otherwise, release existing texture based bitmap and allocate a new one based on video size.
591 if (!ensureTextureBackedSkBitmap(context3D->grContext(), m_bitmap, naturalSize(), kTopLeft_GrSurfaceOrigin, kSkia8888_GrPixelConfig))
592 return;
593
594 // Copy video texture to bitmap texture.
595 WebGraphicsContext3D* webGraphicsContext3D = context3D->webContext();
596 WebCanvas* canvas = context->canvas();
597 unsigned textureId = static_cast<unsigned>((m_bitmap.getTexture())->getTextureHandle());
598 if (!m_webMediaPlayer->copyVideoTextureToPlatformTexture(webGraphicsContext3D, textureId, 0, GL_RGBA, GL_UNSIGNED_BYTE, true, false))
599 return;
600
601 // Draw the texture based bitmap onto the Canvas. If the canvas is hardware based, this will do a GPU-GPU texture copy. If the canvas is software based,
602 // the texture based bitmap will be readbacked to system memory then draw onto the canvas.
603 SkRect dest;
604 dest.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
605 SkPaint paint;
606 paint.setAlpha(alpha);
607 // It is not necessary to pass the dest into the drawBitmap call since all the context have been set up before calling paintCurrentFrameInContext.
608 canvas->drawBitmapRect(m_bitmap, NULL, dest, &paint);
609 }
610 #endif
611
startDelayedLoad()612 void WebMediaPlayerClientImpl::startDelayedLoad()
613 {
614 ASSERT(m_delayingLoad);
615 ASSERT(!m_webMediaPlayer);
616
617 m_delayingLoad = false;
618
619 loadInternal();
620 }
621
WebMediaPlayerClientImpl(MediaPlayerClient * client)622 WebMediaPlayerClientImpl::WebMediaPlayerClientImpl(MediaPlayerClient* client)
623 : m_client(client)
624 , m_isMediaStream(false)
625 , m_delayingLoad(false)
626 , m_preload(MediaPlayer::Auto)
627 , m_helperPlugin(0)
628 , m_needsWebLayerForVideo(false)
629 , m_volume(1.0)
630 , m_muted(false)
631 , m_rate(1.0)
632 {
633 ASSERT(m_client);
634 }
635
636 #if ENABLE(WEB_AUDIO)
wrap(WebAudioSourceProvider * provider)637 void WebMediaPlayerClientImpl::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* provider)
638 {
639 MutexLocker locker(provideInputLock);
640
641 if (m_webAudioSourceProvider && provider != m_webAudioSourceProvider)
642 m_webAudioSourceProvider->setClient(0);
643
644 m_webAudioSourceProvider = provider;
645 if (m_webAudioSourceProvider)
646 m_webAudioSourceProvider->setClient(m_client.get());
647 }
648
setClient(AudioSourceProviderClient * client)649 void WebMediaPlayerClientImpl::AudioSourceProviderImpl::setClient(AudioSourceProviderClient* client)
650 {
651 MutexLocker locker(provideInputLock);
652
653 if (client)
654 m_client = adoptPtr(new WebMediaPlayerClientImpl::AudioClientImpl(client));
655 else
656 m_client.clear();
657
658 if (m_webAudioSourceProvider)
659 m_webAudioSourceProvider->setClient(m_client.get());
660 }
661
provideInput(AudioBus * bus,size_t framesToProcess)662 void WebMediaPlayerClientImpl::AudioSourceProviderImpl::provideInput(AudioBus* bus, size_t framesToProcess)
663 {
664 ASSERT(bus);
665 if (!bus)
666 return;
667
668 MutexTryLocker tryLocker(provideInputLock);
669 if (!tryLocker.locked() || !m_webAudioSourceProvider || !m_client.get()) {
670 bus->zero();
671 return;
672 }
673
674 // Wrap the AudioBus channel data using WebVector.
675 size_t n = bus->numberOfChannels();
676 WebVector<float*> webAudioData(n);
677 for (size_t i = 0; i < n; ++i)
678 webAudioData[i] = bus->channel(i)->mutableData();
679
680 m_webAudioSourceProvider->provideInput(webAudioData, framesToProcess);
681 }
682
setFormat(size_t numberOfChannels,float sampleRate)683 void WebMediaPlayerClientImpl::AudioClientImpl::setFormat(size_t numberOfChannels, float sampleRate)
684 {
685 if (m_client)
686 m_client->setFormat(numberOfChannels, sampleRate);
687 }
688
689 #endif
690
691 } // namespace blink
692