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 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 62 WebMediaPlayer* WebMediaPlayerClientImpl::mediaPlayer() const 63 { 64 return m_webMediaPlayer.get(); 65 } 66 67 // WebMediaPlayerClient -------------------------------------------------------- 68 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 78 void WebMediaPlayerClientImpl::networkStateChanged() 79 { 80 m_client->mediaPlayerNetworkStateChanged(); 81 } 82 83 void WebMediaPlayerClientImpl::readyStateChanged() 84 { 85 m_client->mediaPlayerReadyStateChanged(); 86 } 87 88 void WebMediaPlayerClientImpl::timeChanged() 89 { 90 m_client->mediaPlayerTimeChanged(); 91 } 92 93 void WebMediaPlayerClientImpl::repaint() 94 { 95 m_client->mediaPlayerRepaint(); 96 } 97 98 void WebMediaPlayerClientImpl::durationChanged() 99 { 100 m_client->mediaPlayerDurationChanged(); 101 } 102 103 void WebMediaPlayerClientImpl::sizeChanged() 104 { 105 m_client->mediaPlayerSizeChanged(); 106 } 107 108 void WebMediaPlayerClientImpl::setOpaque(bool opaque) 109 { 110 m_client->mediaPlayerSetOpaque(opaque); 111 } 112 113 double WebMediaPlayerClientImpl::volume() const 114 { 115 return m_volume; 116 } 117 118 void WebMediaPlayerClientImpl::playbackStateChanged() 119 { 120 m_client->mediaPlayerPlaybackStateChanged(); 121 } 122 123 WebMediaPlayer::Preload WebMediaPlayerClientImpl::preload() const 124 { 125 return static_cast<WebMediaPlayer::Preload>(m_preload); 126 } 127 128 void WebMediaPlayerClientImpl::keyAdded(const WebString& keySystem, const WebString& sessionId) 129 { 130 m_client->mediaPlayerKeyAdded(keySystem, sessionId); 131 } 132 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 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 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 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 168 void WebMediaPlayerClientImpl::closeHelperPluginSoon(WebFrame* frame) 169 { 170 ASSERT(m_helperPlugin); 171 toWebViewImpl(frame->view())->closeHelperPluginSoon(m_helperPlugin.release()); 172 } 173 174 void WebMediaPlayerClientImpl::setWebLayer(blink::WebLayer* layer) 175 { 176 m_client->mediaPlayerSetWebLayer(layer); 177 } 178 179 void WebMediaPlayerClientImpl::addTextTrack(WebInbandTextTrack* textTrack) 180 { 181 m_client->mediaPlayerDidAddTrack(textTrack); 182 } 183 184 void WebMediaPlayerClientImpl::removeTextTrack(WebInbandTextTrack* textTrack) 185 { 186 m_client->mediaPlayerDidRemoveTrack(textTrack); 187 } 188 189 void WebMediaPlayerClientImpl::mediaSourceOpened(WebMediaSource* webMediaSource) 190 { 191 ASSERT(webMediaSource); 192 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); 193 m_mediaSource = 0; 194 } 195 196 void WebMediaPlayerClientImpl::requestFullscreen() 197 { 198 m_client->mediaPlayerRequestFullscreen(); 199 } 200 201 void WebMediaPlayerClientImpl::requestSeek(double time) 202 { 203 m_client->mediaPlayerRequestSeek(time); 204 } 205 206 // MediaPlayer ------------------------------------------------- 207 208 void WebMediaPlayerClientImpl::load(const String& url) 209 { 210 m_url = KURL(ParsedURLString, url); 211 m_mediaSource = 0; 212 loadRequested(); 213 } 214 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 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 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 270 void WebMediaPlayerClientImpl::play() 271 { 272 if (m_webMediaPlayer) 273 m_webMediaPlayer->play(); 274 } 275 276 void WebMediaPlayerClientImpl::pause() 277 { 278 if (m_webMediaPlayer) 279 m_webMediaPlayer->pause(); 280 } 281 282 void WebMediaPlayerClientImpl::showFullscreenOverlay() 283 { 284 if (m_webMediaPlayer) 285 m_webMediaPlayer->enterFullscreen(); 286 } 287 288 void WebMediaPlayerClientImpl::hideFullscreenOverlay() 289 { 290 if (m_webMediaPlayer) 291 m_webMediaPlayer->exitFullscreen(); 292 } 293 294 bool WebMediaPlayerClientImpl::canShowFullscreenOverlay() const 295 { 296 return m_webMediaPlayer && m_webMediaPlayer->canEnterFullscreen(); 297 } 298 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 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 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 326 void WebMediaPlayerClientImpl::prepareToPlay() 327 { 328 if (m_delayingLoad) 329 startDelayedLoad(); 330 } 331 332 IntSize WebMediaPlayerClientImpl::naturalSize() const 333 { 334 if (m_webMediaPlayer) 335 return m_webMediaPlayer->naturalSize(); 336 return IntSize(); 337 } 338 339 bool WebMediaPlayerClientImpl::hasVideo() const 340 { 341 if (m_webMediaPlayer) 342 return m_webMediaPlayer->hasVideo(); 343 return false; 344 } 345 346 bool WebMediaPlayerClientImpl::hasAudio() const 347 { 348 if (m_webMediaPlayer) 349 return m_webMediaPlayer->hasAudio(); 350 return false; 351 } 352 353 double WebMediaPlayerClientImpl::duration() const 354 { 355 if (m_webMediaPlayer) 356 return m_webMediaPlayer->duration(); 357 return 0.0; 358 } 359 360 double WebMediaPlayerClientImpl::currentTime() const 361 { 362 if (m_webMediaPlayer) 363 return m_webMediaPlayer->currentTime(); 364 return 0.0; 365 } 366 367 void WebMediaPlayerClientImpl::seek(double time) 368 { 369 if (m_webMediaPlayer) 370 m_webMediaPlayer->seek(time); 371 } 372 373 bool WebMediaPlayerClientImpl::seeking() const 374 { 375 if (m_webMediaPlayer) 376 return m_webMediaPlayer->seeking(); 377 return false; 378 } 379 380 double WebMediaPlayerClientImpl::rate() const 381 { 382 return m_rate; 383 } 384 385 void WebMediaPlayerClientImpl::setRate(double rate) 386 { 387 m_rate = rate; 388 if (m_webMediaPlayer) 389 m_webMediaPlayer->setRate(rate); 390 } 391 392 bool WebMediaPlayerClientImpl::paused() const 393 { 394 if (m_webMediaPlayer) 395 return m_webMediaPlayer->paused(); 396 return false; 397 } 398 399 bool WebMediaPlayerClientImpl::supportsFullscreen() const 400 { 401 if (m_webMediaPlayer) 402 return m_webMediaPlayer->supportsFullscreen(); 403 return false; 404 } 405 406 bool WebMediaPlayerClientImpl::supportsSave() const 407 { 408 if (m_webMediaPlayer) 409 return m_webMediaPlayer->supportsSave(); 410 return false; 411 } 412 413 void WebMediaPlayerClientImpl::setVolume(double volume) 414 { 415 m_volume = volume; 416 if (m_webMediaPlayer && !m_muted) 417 m_webMediaPlayer->setVolume(volume); 418 } 419 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 427 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 434 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 441 double WebMediaPlayerClientImpl::maxTimeSeekable() const 442 { 443 if (m_webMediaPlayer) 444 return m_webMediaPlayer->maxTimeSeekable(); 445 return 0.0; 446 } 447 448 PassRefPtr<TimeRanges> WebMediaPlayerClientImpl::buffered() const 449 { 450 if (m_webMediaPlayer) 451 return TimeRanges::create(m_webMediaPlayer->buffered()); 452 return TimeRanges::create(); 453 } 454 455 bool WebMediaPlayerClientImpl::didLoadingProgress() const 456 { 457 return m_webMediaPlayer && m_webMediaPlayer->didLoadingProgress(); 458 } 459 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 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 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 503 bool WebMediaPlayerClientImpl::hasSingleSecurityOrigin() const 504 { 505 if (m_webMediaPlayer) 506 return m_webMediaPlayer->hasSingleSecurityOrigin(); 507 return false; 508 } 509 510 bool WebMediaPlayerClientImpl::didPassCORSAccessCheck() const 511 { 512 if (m_webMediaPlayer) 513 return m_webMediaPlayer->didPassCORSAccessCheck(); 514 return false; 515 } 516 517 double WebMediaPlayerClientImpl::mediaTimeForTimeValue(double timeValue) const 518 { 519 if (m_webMediaPlayer) 520 return m_webMediaPlayer->mediaTimeForTimeValue(timeValue); 521 return timeValue; 522 } 523 524 unsigned WebMediaPlayerClientImpl::decodedFrameCount() const 525 { 526 if (m_webMediaPlayer) 527 return m_webMediaPlayer->decodedFrameCount(); 528 return 0; 529 } 530 531 unsigned WebMediaPlayerClientImpl::droppedFrameCount() const 532 { 533 if (m_webMediaPlayer) 534 return m_webMediaPlayer->droppedFrameCount(); 535 return 0; 536 } 537 538 unsigned WebMediaPlayerClientImpl::corruptedFrameCount() const 539 { 540 if (m_webMediaPlayer) 541 return m_webMediaPlayer->corruptedFrameCount(); 542 return 0; 543 } 544 545 unsigned WebMediaPlayerClientImpl::audioDecodedByteCount() const 546 { 547 if (m_webMediaPlayer) 548 return m_webMediaPlayer->audioDecodedByteCount(); 549 return 0; 550 } 551 552 unsigned WebMediaPlayerClientImpl::videoDecodedByteCount() const 553 { 554 if (m_webMediaPlayer) 555 return m_webMediaPlayer->videoDecodedByteCount(); 556 return 0; 557 } 558 559 #if ENABLE(WEB_AUDIO) 560 AudioSourceProvider* WebMediaPlayerClientImpl::audioSourceProvider() 561 { 562 return &m_audioSourceProvider; 563 } 564 #endif 565 566 bool WebMediaPlayerClientImpl::needsWebLayerForVideo() const 567 { 568 return m_needsWebLayerForVideo; 569 } 570 571 PassOwnPtr<MediaPlayer> WebMediaPlayerClientImpl::create(MediaPlayerClient* client) 572 { 573 return adoptPtr(new WebMediaPlayerClientImpl(client)); 574 } 575 576 #if OS(ANDROID) 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 612 void WebMediaPlayerClientImpl::startDelayedLoad() 613 { 614 ASSERT(m_delayingLoad); 615 ASSERT(!m_webMediaPlayer); 616 617 m_delayingLoad = false; 618 619 loadInternal(); 620 } 621 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) 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 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 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 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