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