1 /* 2 Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public License 15 along with this library; see the file COPYING.LIB. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Boston, MA 02110-1301, USA. 18 */ 19 20 #include "config.h" 21 #include "MediaPlayerPrivateQt.h" 22 23 #include "FrameView.h" 24 #include "GraphicsContext.h" 25 #include "HTMLMediaElement.h" 26 #include "HTMLVideoElement.h" 27 #include "NetworkingContext.h" 28 #include "NotImplemented.h" 29 #include "RenderVideo.h" 30 #include "TimeRanges.h" 31 #include "Widget.h" 32 #include "qwebframe.h" 33 #include "qwebpage.h" 34 35 #include <QGraphicsScene> 36 #include <QGraphicsVideoItem> 37 #include <QMediaPlayerControl> 38 #include <QMediaService> 39 #include <QNetworkAccessManager> 40 #include <QNetworkCookieJar> 41 #include <QNetworkRequest> 42 #include <QPainter> 43 #include <QPoint> 44 #include <QRect> 45 #include <QStyleOptionGraphicsItem> 46 #include <QTime> 47 #include <QTimer> 48 #include <QUrl> 49 #include <limits> 50 #include <wtf/HashSet.h> 51 #include <wtf/text/CString.h> 52 53 #if USE(ACCELERATED_COMPOSITING) 54 #include "texmap/TextureMapperPlatformLayer.h" 55 #endif 56 57 using namespace WTF; 58 59 namespace WebCore { 60 61 MediaPlayerPrivateInterface* MediaPlayerPrivateQt::create(MediaPlayer* player) 62 { 63 return new MediaPlayerPrivateQt(player); 64 } 65 66 void MediaPlayerPrivateQt::registerMediaEngine(MediaEngineRegistrar registrar) 67 { 68 registrar(create, getSupportedTypes, supportsType, 0, 0, 0); 69 } 70 71 void MediaPlayerPrivateQt::getSupportedTypes(HashSet<String> &supported) 72 { 73 QStringList types = QMediaPlayer::supportedMimeTypes(); 74 75 for (int i = 0; i < types.size(); i++) { 76 QString mime = types.at(i); 77 if (mime.startsWith(QString::fromLatin1("audio/")) || mime.startsWith(QString::fromLatin1("video/"))) 78 supported.add(mime); 79 } 80 } 81 82 MediaPlayer::SupportsType MediaPlayerPrivateQt::supportsType(const String& mime, const String& codec) 83 { 84 if (!mime.startsWith("audio/") && !mime.startsWith("video/")) 85 return MediaPlayer::IsNotSupported; 86 87 // Parse and trim codecs. 88 QString codecStr = codec; 89 QStringList codecList = codecStr.split(QLatin1Char(','), QString::SkipEmptyParts); 90 QStringList codecListTrimmed; 91 foreach (const QString& codecStrNotTrimmed, codecList) { 92 QString codecStrTrimmed = codecStrNotTrimmed.trimmed(); 93 if (!codecStrTrimmed.isEmpty()) 94 codecListTrimmed.append(codecStrTrimmed); 95 } 96 97 if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QtMultimediaKit::ProbablySupported) 98 return MediaPlayer::IsSupported; 99 100 return MediaPlayer::MayBeSupported; 101 } 102 103 MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player) 104 : m_webCorePlayer(player) 105 , m_mediaPlayer(new QMediaPlayer) 106 , m_mediaPlayerControl(0) 107 , m_videoItem(new QGraphicsVideoItem) 108 , m_videoScene(new QGraphicsScene) 109 , m_networkState(MediaPlayer::Empty) 110 , m_readyState(MediaPlayer::HaveNothing) 111 , m_currentSize(0, 0) 112 , m_naturalSize(RenderVideo::defaultSize()) 113 , m_isVisible(false) 114 , m_isSeeking(false) 115 , m_composited(false) 116 , m_preload(MediaPlayer::Auto) 117 , m_suppressNextPlaybackChanged(false) 118 { 119 m_mediaPlayer->setVideoOutput(m_videoItem); 120 m_videoScene->addItem(m_videoItem); 121 122 // Signal Handlers 123 connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), 124 this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus))); 125 connect(m_mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), 126 this, SLOT(stateChanged(QMediaPlayer::State))); 127 connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)), 128 this, SLOT(handleError(QMediaPlayer::Error))); 129 connect(m_mediaPlayer, SIGNAL(bufferStatusChanged(int)), 130 this, SLOT(bufferStatusChanged(int))); 131 connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)), 132 this, SLOT(durationChanged(qint64))); 133 connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)), 134 this, SLOT(positionChanged(qint64))); 135 connect(m_mediaPlayer, SIGNAL(volumeChanged(int)), 136 this, SLOT(volumeChanged(int))); 137 connect(m_mediaPlayer, SIGNAL(mutedChanged(bool)), 138 this, SLOT(mutedChanged(bool))); 139 connect(m_videoScene, SIGNAL(changed(QList<QRectF>)), 140 this, SLOT(repaint())); 141 connect(m_videoItem, SIGNAL(nativeSizeChanged(QSizeF)), 142 this, SLOT(nativeSizeChanged(QSizeF))); 143 144 // Grab the player control 145 if (QMediaService* service = m_mediaPlayer->service()) { 146 m_mediaPlayerControl = qobject_cast<QMediaPlayerControl *>( 147 service->requestControl(QMediaPlayerControl_iid)); 148 } 149 } 150 151 MediaPlayerPrivateQt::~MediaPlayerPrivateQt() 152 { 153 m_mediaPlayer->disconnect(this); 154 m_mediaPlayer->stop(); 155 m_mediaPlayer->setMedia(QMediaContent()); 156 157 delete m_mediaPlayer; 158 delete m_videoScene; 159 } 160 161 bool MediaPlayerPrivateQt::hasVideo() const 162 { 163 return m_mediaPlayer->isVideoAvailable(); 164 } 165 166 bool MediaPlayerPrivateQt::hasAudio() const 167 { 168 return true; 169 } 170 171 void MediaPlayerPrivateQt::load(const String& url) 172 { 173 m_mediaUrl = url; 174 175 // QtMultimedia does not have an API to throttle loading 176 // so we handle this ourselves by delaying the load 177 if (m_preload == MediaPlayer::None) { 178 m_delayingLoad = true; 179 return; 180 } 181 182 commitLoad(url); 183 } 184 185 void MediaPlayerPrivateQt::commitLoad(const String& url) 186 { 187 // We are now loading 188 if (m_networkState != MediaPlayer::Loading) { 189 m_networkState = MediaPlayer::Loading; 190 m_webCorePlayer->networkStateChanged(); 191 } 192 193 // And we don't have any data yet 194 if (m_readyState != MediaPlayer::HaveNothing) { 195 m_readyState = MediaPlayer::HaveNothing; 196 m_webCorePlayer->readyStateChanged(); 197 } 198 199 KURL kUrl(ParsedURLString, url); 200 const QUrl rUrl = kUrl; 201 const QString scheme = rUrl.scheme().toLower(); 202 203 // Grab the client media element 204 HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()); 205 206 // Construct the media content with a network request if the resource is http[s] 207 if (scheme == QString::fromLatin1("http") || scheme == QString::fromLatin1("https")) { 208 QNetworkRequest request = QNetworkRequest(rUrl); 209 210 // Grab the current document 211 Document* document = element->document(); 212 if (!document) 213 document = element->ownerDocument(); 214 215 // Grab the frame and network manager 216 Frame* frame = document ? document->frame() : 0; 217 FrameLoader* frameLoader = frame ? frame->loader() : 0; 218 QNetworkAccessManager* manager = frameLoader ? frameLoader->networkingContext()->networkAccessManager() : 0; 219 220 if (manager) { 221 // Set the cookies 222 QNetworkCookieJar* jar = manager->cookieJar(); 223 QList<QNetworkCookie> cookies = jar->cookiesForUrl(rUrl); 224 225 // Don't set the header if there are no cookies. 226 // This prevents a warning from being emitted. 227 if (!cookies.isEmpty()) 228 request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); 229 230 // Set the refferer, but not when requesting insecure content from a secure page 231 QUrl documentUrl = QUrl(QString(document->documentURI())); 232 if (documentUrl.scheme().toLower() == QString::fromLatin1("http") || scheme == QString::fromLatin1("https")) 233 request.setRawHeader("Referer", documentUrl.toEncoded()); 234 235 // Set the user agent 236 request.setRawHeader("User-Agent", frameLoader->userAgent(rUrl).utf8().data()); 237 } 238 239 m_mediaPlayer->setMedia(QMediaContent(request)); 240 } else { 241 // Otherwise, just use the URL 242 m_mediaPlayer->setMedia(QMediaContent(rUrl)); 243 } 244 245 // Set the current volume and mute status 246 // We get these from the element, rather than the player, in case we have 247 // transitioned from a media engine which doesn't support muting, to a media 248 // engine which does. 249 m_mediaPlayer->setMuted(element->muted()); 250 m_mediaPlayer->setVolume(static_cast<int>(element->volume() * 100.0)); 251 252 // Don't send PlaybackChanged notification for pre-roll. 253 m_suppressNextPlaybackChanged = true; 254 255 // Setting a media source will start loading the media, but we need 256 // to pre-roll as well to get video size-hints and buffer-status 257 if (element->paused()) 258 m_mediaPlayer->pause(); 259 else 260 m_mediaPlayer->play(); 261 } 262 263 void MediaPlayerPrivateQt::resumeLoad() 264 { 265 m_delayingLoad = false; 266 267 if (!m_mediaUrl.isNull()) 268 commitLoad(m_mediaUrl); 269 } 270 271 void MediaPlayerPrivateQt::cancelLoad() 272 { 273 m_mediaPlayer->setMedia(QMediaContent()); 274 updateStates(); 275 } 276 277 void MediaPlayerPrivateQt::prepareToPlay() 278 { 279 if (m_mediaPlayer->media().isNull() || m_delayingLoad) 280 resumeLoad(); 281 } 282 283 void MediaPlayerPrivateQt::play() 284 { 285 if (m_mediaPlayer->state() != QMediaPlayer::PlayingState) 286 m_mediaPlayer->play(); 287 } 288 289 void MediaPlayerPrivateQt::pause() 290 { 291 if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) 292 m_mediaPlayer->pause(); 293 } 294 295 bool MediaPlayerPrivateQt::paused() const 296 { 297 return (m_mediaPlayer->state() != QMediaPlayer::PlayingState); 298 } 299 300 void MediaPlayerPrivateQt::seek(float position) 301 { 302 if (!m_mediaPlayer->isSeekable()) 303 return; 304 305 if (m_mediaPlayerControl && !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000)) 306 return; 307 308 m_isSeeking = true; 309 m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000)); 310 } 311 312 bool MediaPlayerPrivateQt::seeking() const 313 { 314 return m_isSeeking; 315 } 316 317 float MediaPlayerPrivateQt::duration() const 318 { 319 if (m_readyState < MediaPlayer::HaveMetadata) 320 return 0.0f; 321 322 float duration = m_mediaPlayer->duration() / 1000.0f; 323 324 // We are streaming 325 if (duration <= 0.0f) 326 duration = std::numeric_limits<float>::infinity(); 327 328 return duration; 329 } 330 331 float MediaPlayerPrivateQt::currentTime() const 332 { 333 return m_mediaPlayer->position() / 1000.0f; 334 } 335 336 PassRefPtr<TimeRanges> MediaPlayerPrivateQt::buffered() const 337 { 338 RefPtr<TimeRanges> buffered = TimeRanges::create(); 339 340 if (!m_mediaPlayerControl) 341 return buffered; 342 343 QMediaTimeRange playbackRanges = m_mediaPlayerControl->availablePlaybackRanges(); 344 345 foreach (const QMediaTimeInterval interval, playbackRanges.intervals()) { 346 float rangeMin = static_cast<float>(interval.start()) / 1000.0f; 347 float rangeMax = static_cast<float>(interval.end()) / 1000.0f; 348 buffered->add(rangeMin, rangeMax); 349 } 350 351 return buffered.release(); 352 } 353 354 float MediaPlayerPrivateQt::maxTimeSeekable() const 355 { 356 if (!m_mediaPlayerControl) 357 return 0; 358 359 return static_cast<float>(m_mediaPlayerControl->availablePlaybackRanges().latestTime()) / 1000.0f; 360 } 361 362 unsigned MediaPlayerPrivateQt::bytesLoaded() const 363 { 364 QLatin1String bytesLoadedKey("bytes-loaded"); 365 if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey)) 366 return m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt(); 367 368 return m_mediaPlayer->bufferStatus(); 369 } 370 371 unsigned MediaPlayerPrivateQt::totalBytes() const 372 { 373 if (m_mediaPlayer->availableMetaData().contains(QtMultimediaKit::Size)) 374 return m_mediaPlayer->metaData(QtMultimediaKit::Size).toInt(); 375 376 return 100; 377 } 378 379 void MediaPlayerPrivateQt::setPreload(MediaPlayer::Preload preload) 380 { 381 m_preload = preload; 382 if (m_delayingLoad && m_preload != MediaPlayer::None) 383 resumeLoad(); 384 } 385 386 void MediaPlayerPrivateQt::setRate(float rate) 387 { 388 m_mediaPlayer->setPlaybackRate(rate); 389 } 390 391 void MediaPlayerPrivateQt::setVolume(float volume) 392 { 393 m_mediaPlayer->setVolume(static_cast<int>(volume * 100.0)); 394 } 395 396 bool MediaPlayerPrivateQt::supportsMuting() const 397 { 398 return true; 399 } 400 401 void MediaPlayerPrivateQt::setMuted(bool muted) 402 { 403 m_mediaPlayer->setMuted(muted); 404 } 405 406 MediaPlayer::NetworkState MediaPlayerPrivateQt::networkState() const 407 { 408 return m_networkState; 409 } 410 411 MediaPlayer::ReadyState MediaPlayerPrivateQt::readyState() const 412 { 413 return m_readyState; 414 } 415 416 void MediaPlayerPrivateQt::setVisible(bool visible) 417 { 418 m_isVisible = visible; 419 } 420 421 void MediaPlayerPrivateQt::mediaStatusChanged(QMediaPlayer::MediaStatus) 422 { 423 updateStates(); 424 } 425 426 void MediaPlayerPrivateQt::handleError(QMediaPlayer::Error) 427 { 428 updateStates(); 429 } 430 431 void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State) 432 { 433 if (!m_suppressNextPlaybackChanged) 434 m_webCorePlayer->playbackStateChanged(); 435 else 436 m_suppressNextPlaybackChanged = false; 437 } 438 439 void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF& size) 440 { 441 LOG(Media, "MediaPlayerPrivateQt::naturalSizeChanged(%dx%d)", 442 size.toSize().width(), size.toSize().height()); 443 444 if (!size.isValid()) 445 return; 446 447 m_naturalSize = size.toSize(); 448 m_webCorePlayer->sizeChanged(); 449 } 450 451 void MediaPlayerPrivateQt::positionChanged(qint64) 452 { 453 // Only propagate this event if we are seeking 454 if (m_isSeeking) { 455 m_isSeeking = false; 456 m_webCorePlayer->timeChanged(); 457 } 458 } 459 460 void MediaPlayerPrivateQt::bufferStatusChanged(int) 461 { 462 notImplemented(); 463 } 464 465 void MediaPlayerPrivateQt::durationChanged(qint64) 466 { 467 m_webCorePlayer->durationChanged(); 468 } 469 470 void MediaPlayerPrivateQt::volumeChanged(int volume) 471 { 472 m_webCorePlayer->volumeChanged(static_cast<float>(volume) / 100.0); 473 } 474 475 void MediaPlayerPrivateQt::mutedChanged(bool muted) 476 { 477 m_webCorePlayer->muteChanged(muted); 478 } 479 480 void MediaPlayerPrivateQt::updateStates() 481 { 482 // Store the old states so that we can detect a change and raise change events 483 MediaPlayer::NetworkState oldNetworkState = m_networkState; 484 MediaPlayer::ReadyState oldReadyState = m_readyState; 485 486 QMediaPlayer::MediaStatus currentStatus = m_mediaPlayer->mediaStatus(); 487 QMediaPlayer::Error currentError = m_mediaPlayer->error(); 488 489 if (currentError != QMediaPlayer::NoError) { 490 m_readyState = MediaPlayer::HaveNothing; 491 if (currentError == QMediaPlayer::FormatError) 492 m_networkState = MediaPlayer::FormatError; 493 else 494 m_networkState = MediaPlayer::NetworkError; 495 } else if (currentStatus == QMediaPlayer::UnknownMediaStatus 496 || currentStatus == QMediaPlayer::NoMedia) { 497 m_networkState = MediaPlayer::Idle; 498 m_readyState = MediaPlayer::HaveNothing; 499 } else if (currentStatus == QMediaPlayer::LoadingMedia) { 500 m_networkState = MediaPlayer::Loading; 501 m_readyState = MediaPlayer::HaveNothing; 502 } else if (currentStatus == QMediaPlayer::LoadedMedia) { 503 m_networkState = MediaPlayer::Loading; 504 m_readyState = MediaPlayer::HaveMetadata; 505 } else if (currentStatus == QMediaPlayer::BufferingMedia) { 506 m_networkState = MediaPlayer::Loading; 507 m_readyState = MediaPlayer::HaveFutureData; 508 } else if (currentStatus == QMediaPlayer::StalledMedia) { 509 m_networkState = MediaPlayer::Loading; 510 m_readyState = MediaPlayer::HaveCurrentData; 511 } else if (currentStatus == QMediaPlayer::BufferedMedia 512 || currentStatus == QMediaPlayer::EndOfMedia) { 513 m_networkState = MediaPlayer::Loaded; 514 m_readyState = MediaPlayer::HaveEnoughData; 515 } else if (currentStatus == QMediaPlayer::InvalidMedia) { 516 m_networkState = MediaPlayer::NetworkError; 517 m_readyState = MediaPlayer::HaveNothing; 518 } 519 520 // Log the state changes and raise the state change events 521 // NB: The readyStateChanged event must come before the networkStateChanged event. 522 // Breaking this invariant will cause the resource selection algorithm for multiple 523 // sources to fail. 524 if (m_readyState != oldReadyState) 525 m_webCorePlayer->readyStateChanged(); 526 527 if (m_networkState != oldNetworkState) 528 m_webCorePlayer->networkStateChanged(); 529 } 530 531 void MediaPlayerPrivateQt::setSize(const IntSize& size) 532 { 533 LOG(Media, "MediaPlayerPrivateQt::setSize(%dx%d)", 534 size.width(), size.height()); 535 536 if (size == m_currentSize) 537 return; 538 539 m_currentSize = size; 540 m_videoItem->setSize(QSizeF(QSize(size))); 541 } 542 543 IntSize MediaPlayerPrivateQt::naturalSize() const 544 { 545 if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata) { 546 LOG(Media, "MediaPlayerPrivateQt::naturalSize() -> 0x0 (!hasVideo || !haveMetaData)"); 547 return IntSize(); 548 } 549 550 LOG(Media, "MediaPlayerPrivateQt::naturalSize() -> %dx%d (m_naturalSize)", 551 m_naturalSize.width(), m_naturalSize.height()); 552 553 return m_naturalSize; 554 } 555 556 void MediaPlayerPrivateQt::removeVideoItem() 557 { 558 m_oldNaturalSize = m_naturalSize; 559 m_mediaPlayer->setVideoOutput(static_cast<QGraphicsVideoItem*>(0)); 560 m_videoScene->removeItem(m_videoItem); 561 } 562 563 void MediaPlayerPrivateQt::restoreVideoItem() 564 { 565 m_mediaPlayer->setVideoOutput(m_videoItem); 566 m_videoScene->addItem(m_videoItem); 567 // FIXME: a qtmobility bug, need to reset the size when restore the videoitem, otherwise the size is 0 568 // http://bugreports.qt.nokia.com/browse/QTMOBILITY-971 569 nativeSizeChanged(QSize(m_oldNaturalSize)); 570 } 571 572 void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect) 573 { 574 #if USE(ACCELERATED_COMPOSITING) 575 if (m_composited) 576 return; 577 #endif 578 if (context->paintingDisabled()) 579 return; 580 581 if (!m_isVisible) 582 return; 583 584 QPainter* painter = context->platformContext(); 585 m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect()); 586 } 587 588 void MediaPlayerPrivateQt::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect) 589 { 590 if (context->paintingDisabled()) 591 return; 592 593 if (!m_isVisible) 594 return; 595 596 // Grab the painter and widget 597 QPainter* painter = context->platformContext(); 598 599 // Render the video, using the item as it might not be in the scene 600 m_videoItem->paint(painter, 0, 0); 601 } 602 603 void MediaPlayerPrivateQt::repaint() 604 { 605 m_webCorePlayer->repaint(); 606 } 607 608 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) 609 610 class TextureMapperVideoLayerQt : public virtual TextureMapperMediaLayer { 611 public: 612 TextureMapperVideoLayerQt(QGraphicsVideoItem* videoItem) 613 : m_videoItem(videoItem) 614 { 615 } 616 617 virtual void setPlatformLayerClient(TextureMapperLayerClient* client) 618 { 619 m_client = client; 620 } 621 622 virtual void paint(GraphicsContext* context) 623 { 624 if (!m_videoItem) 625 return; 626 627 QStyleOptionGraphicsItem opt; 628 opt.exposedRect = m_videoItem.data()->sceneBoundingRect(); 629 opt.rect = opt.exposedRect.toRect(); 630 m_videoItem.data()->paint(context->platformContext(), &opt); 631 } 632 633 virtual IntSize size() const 634 { 635 return m_videoItem ? IntSize(m_videoItem.data()->size().width(), m_videoItem.data()->size().height()) : IntSize(); 636 } 637 638 QWeakPointer<QGraphicsVideoItem> m_videoItem; 639 TextureMapperLayerClient* m_client; 640 }; 641 642 643 void MediaPlayerPrivateQt::acceleratedRenderingStateChanged() 644 { 645 MediaPlayerClient* client = m_webCorePlayer->mediaPlayerClient(); 646 bool composited = client->mediaPlayerRenderingCanBeAccelerated(m_webCorePlayer); 647 if (composited == m_composited) 648 return; 649 650 m_composited = composited; 651 if (composited) 652 m_platformLayer = new TextureMapperVideoLayerQt(m_videoItem); 653 } 654 655 PlatformLayer* MediaPlayerPrivateQt::platformLayer() const 656 { 657 return m_composited ? m_platformLayer.get() : 0; 658 } 659 #endif 660 661 PlatformMedia MediaPlayerPrivateQt::platformMedia() const 662 { 663 PlatformMedia pm; 664 pm.type = PlatformMedia::QtMediaPlayerType; 665 pm.media.qtMediaPlayer = const_cast<MediaPlayerPrivateQt*>(this); 666 return pm; 667 } 668 669 } // namespace WebCore 670 671 #include "moc_MediaPlayerPrivateQt.cpp" 672