<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[178671] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/178671">178671</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-01-19 13:03:02 -0800 (Mon, 19 Jan 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>[WinCairo][Video] Windows Media Foundation implementation is not completed.
https://bugs.webkit.org/show_bug.cgi?id=140337
Patch by peavo@outlook.com <peavo@outlook.com> on 2015-01-19
Reviewed by Alex Christensen.
Source/WebCore:
This patch aims to complete some of the methods which are not implemented.
Currently, only MP4 is supported.
Video is rendered in a child window of the main window.
We should eventually render the video directly in the main window,
by reading and painting individual video frames from the stream.
* platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp:
(WebCore::MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation):
(WebCore::MediaPlayerPrivateMediaFoundation::~MediaPlayerPrivateMediaFoundation):
(WebCore::MediaPlayerPrivateMediaFoundation::getSupportedTypes):
(WebCore::MediaPlayerPrivateMediaFoundation::supportsType):
(WebCore::MediaPlayerPrivateMediaFoundation::load):
(WebCore::MediaPlayerPrivateMediaFoundation::play):
(WebCore::MediaPlayerPrivateMediaFoundation::pause):
(WebCore::MediaPlayerPrivateMediaFoundation::naturalSize):
(WebCore::MediaPlayerPrivateMediaFoundation::hasVideo):
(WebCore::MediaPlayerPrivateMediaFoundation::hasAudio):
(WebCore::MediaPlayerPrivateMediaFoundation::setVisible):
(WebCore::MediaPlayerPrivateMediaFoundation::paused):
(WebCore::MediaPlayerPrivateMediaFoundation::readyState):
(WebCore::MediaPlayerPrivateMediaFoundation::didLoadingProgress):
(WebCore::MediaPlayerPrivateMediaFoundation::setSize):
(WebCore::MediaPlayerPrivateMediaFoundation::paint):
(WebCore::MediaPlayerPrivateMediaFoundation::createSession):
(WebCore::MediaPlayerPrivateMediaFoundation::endSession):
(WebCore::MediaPlayerPrivateMediaFoundation::startCreateMediaSource):
(WebCore::MediaPlayerPrivateMediaFoundation::endCreatedMediaSource):
(WebCore::MediaPlayerPrivateMediaFoundation::endGetEvent):
(WebCore::MediaPlayerPrivateMediaFoundation::createTopologyFromSource):
(WebCore::MediaPlayerPrivateMediaFoundation::addBranchToPartialTopology):
(WebCore::MediaPlayerPrivateMediaFoundation::VideoViewWndProc):
(WebCore::MediaPlayerPrivateMediaFoundation::registerVideoWindowClass):
(WebCore::MediaPlayerPrivateMediaFoundation::createVideoWindow):
(WebCore::MediaPlayerPrivateMediaFoundation::destroyVideoWindow):
(WebCore::MediaPlayerPrivateMediaFoundation::createOutputNode):
(WebCore::MediaPlayerPrivateMediaFoundation::createSourceStreamNode):
(WebCore::MediaPlayerPrivateMediaFoundation::onCreatedMediaSource):
(WebCore::MediaPlayerPrivateMediaFoundation::onTopologySet):
(WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::AsyncCallback):
(WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::~AsyncCallback):
(WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::QueryInterface):
(WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::AddRef):
(WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::Release):
(WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::GetParameters):
(WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::Invoke):
* platform/graphics/win/MediaPlayerPrivateMediaFoundation.h:
WebKitLibraries:
Link with Media Foundation libraries.
* win/tools/vsprops/WinCairo.props:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicswinMediaPlayerPrivateMediaFoundationcpp">trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicswinMediaPlayerPrivateMediaFoundationh">trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h</a></li>
<li><a href="#trunkWebKitLibrariesChangeLog">trunk/WebKitLibraries/ChangeLog</a></li>
<li><a href="#trunkWebKitLibrarieswintoolsvspropsWinCairoprops">trunk/WebKitLibraries/win/tools/vsprops/WinCairo.props</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (178670 => 178671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-19 21:01:14 UTC (rev 178670)
+++ trunk/Source/WebCore/ChangeLog        2015-01-19 21:03:02 UTC (rev 178671)
</span><span class="lines">@@ -1,3 +1,57 @@
</span><ins>+2015-01-19 peavo@outlook.com <peavo@outlook.com>
+
+ [WinCairo][Video] Windows Media Foundation implementation is not completed.
+ https://bugs.webkit.org/show_bug.cgi?id=140337
+
+ Reviewed by Alex Christensen.
+
+ This patch aims to complete some of the methods which are not implemented.
+ Currently, only MP4 is supported.
+ Video is rendered in a child window of the main window.
+ We should eventually render the video directly in the main window,
+ by reading and painting individual video frames from the stream.
+
+ * platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp:
+ (WebCore::MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation):
+ (WebCore::MediaPlayerPrivateMediaFoundation::~MediaPlayerPrivateMediaFoundation):
+ (WebCore::MediaPlayerPrivateMediaFoundation::getSupportedTypes):
+ (WebCore::MediaPlayerPrivateMediaFoundation::supportsType):
+ (WebCore::MediaPlayerPrivateMediaFoundation::load):
+ (WebCore::MediaPlayerPrivateMediaFoundation::play):
+ (WebCore::MediaPlayerPrivateMediaFoundation::pause):
+ (WebCore::MediaPlayerPrivateMediaFoundation::naturalSize):
+ (WebCore::MediaPlayerPrivateMediaFoundation::hasVideo):
+ (WebCore::MediaPlayerPrivateMediaFoundation::hasAudio):
+ (WebCore::MediaPlayerPrivateMediaFoundation::setVisible):
+ (WebCore::MediaPlayerPrivateMediaFoundation::paused):
+ (WebCore::MediaPlayerPrivateMediaFoundation::readyState):
+ (WebCore::MediaPlayerPrivateMediaFoundation::didLoadingProgress):
+ (WebCore::MediaPlayerPrivateMediaFoundation::setSize):
+ (WebCore::MediaPlayerPrivateMediaFoundation::paint):
+ (WebCore::MediaPlayerPrivateMediaFoundation::createSession):
+ (WebCore::MediaPlayerPrivateMediaFoundation::endSession):
+ (WebCore::MediaPlayerPrivateMediaFoundation::startCreateMediaSource):
+ (WebCore::MediaPlayerPrivateMediaFoundation::endCreatedMediaSource):
+ (WebCore::MediaPlayerPrivateMediaFoundation::endGetEvent):
+ (WebCore::MediaPlayerPrivateMediaFoundation::createTopologyFromSource):
+ (WebCore::MediaPlayerPrivateMediaFoundation::addBranchToPartialTopology):
+ (WebCore::MediaPlayerPrivateMediaFoundation::VideoViewWndProc):
+ (WebCore::MediaPlayerPrivateMediaFoundation::registerVideoWindowClass):
+ (WebCore::MediaPlayerPrivateMediaFoundation::createVideoWindow):
+ (WebCore::MediaPlayerPrivateMediaFoundation::destroyVideoWindow):
+ (WebCore::MediaPlayerPrivateMediaFoundation::createOutputNode):
+ (WebCore::MediaPlayerPrivateMediaFoundation::createSourceStreamNode):
+ (WebCore::MediaPlayerPrivateMediaFoundation::onCreatedMediaSource):
+ (WebCore::MediaPlayerPrivateMediaFoundation::onTopologySet):
+ (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::AsyncCallback):
+ (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::~AsyncCallback):
+ (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::QueryInterface):
+ (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::AddRef):
+ (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::Release):
+ (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::GetParameters):
+ (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::Invoke):
+ * platform/graphics/win/MediaPlayerPrivateMediaFoundation.h:
+
</ins><span class="cx"> 2015-01-19 Brian J. Burg <burg@cs.washington.edu>
</span><span class="cx">
</span><span class="cx"> Web Replay: convert to is<T> and downcast<T> for decoding replay inputs
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicswinMediaPlayerPrivateMediaFoundationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp (178670 => 178671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp        2015-01-19 21:01:14 UTC (rev 178670)
+++ trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp        2015-01-19 21:03:02 UTC (rev 178671)
</span><span class="lines">@@ -27,20 +27,44 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "MediaPlayerPrivateMediaFoundation.h"
</span><span class="cx">
</span><ins>+#include "CachedResourceLoader.h"
+#include "FrameView.h"
</ins><span class="cx"> #include "GraphicsContext.h"
</span><ins>+#include "HostWindow.h"
</ins><span class="cx"> #include "NotImplemented.h"
</span><span class="cx">
</span><span class="cx"> #if USE(MEDIA_FOUNDATION)
</span><span class="cx">
</span><ins>+#include <wtf/MainThread.h>
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-// TODO: Implement video functionality using Media Foundation
-
</del><span class="cx"> MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation(MediaPlayer* player)
</span><span class="cx"> : m_player(player)
</span><ins>+ , m_visible(false)
+ , m_loadingProgress(false)
+ , m_paused(false)
+ , m_hasAudio(false)
+ , m_hasVideo(false)
+ , m_hwndVideo(nullptr)
+ , m_readyState(MediaPlayer::HaveNothing)
+ , m_mediaSession(nullptr)
+ , m_sourceResolver(nullptr)
+ , m_mediaSource(nullptr)
+ , m_topology(nullptr)
+ , m_sourcePD(nullptr)
+ , m_videoDisplay(nullptr)
</ins><span class="cx"> {
</span><ins>+ createSession();
+ createVideoWindow();
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+MediaPlayerPrivateMediaFoundation::~MediaPlayerPrivateMediaFoundation()
+{
+ destroyVideoWindow();
+ endSession();
+}
+
</ins><span class="cx"> PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateMediaFoundation::create(MediaPlayer* player)
</span><span class="cx"> {
</span><span class="cx"> return adoptPtr(new MediaPlayerPrivateMediaFoundation(player));
</span><span class="lines">@@ -60,19 +84,23 @@
</span><span class="cx">
</span><span class="cx"> void MediaPlayerPrivateMediaFoundation::getSupportedTypes(HashSet<String>& types)
</span><span class="cx"> {
</span><del>- notImplemented();
- types = HashSet<String>();
</del><ins>+ types.add(String("video/mp4"));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> MediaPlayer::SupportsType MediaPlayerPrivateMediaFoundation::supportsType(const MediaEngineSupportParameters& parameters)
</span><span class="cx"> {
</span><del>- notImplemented();
</del><ins>+ if (parameters.type.isNull() || parameters.type.isEmpty())
+ return MediaPlayer::IsNotSupported;
+
+ if (parameters.type == "video/mp4")
+ return MediaPlayer::IsSupported;
+
</ins><span class="cx"> return MediaPlayer::IsNotSupported;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void MediaPlayerPrivateMediaFoundation::load(const String&)
</del><ins>+void MediaPlayerPrivateMediaFoundation::load(const String& url)
</ins><span class="cx"> {
</span><del>- notImplemented();
</del><ins>+ startCreateMediaSource(url);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void MediaPlayerPrivateMediaFoundation::cancelLoad()
</span><span class="lines">@@ -82,35 +110,47 @@
</span><span class="cx">
</span><span class="cx"> void MediaPlayerPrivateMediaFoundation::play()
</span><span class="cx"> {
</span><del>- notImplemented();
</del><ins>+ if (!m_mediaSession)
+ return;
+
+ PROPVARIANT varStart;
+ PropVariantInit(&varStart);
+ varStart.vt = VT_EMPTY;
+
+ HRESULT hr = m_mediaSession->Start(nullptr, &varStart);
+ ASSERT(SUCCEEDED(hr));
+
+ PropVariantClear(&varStart);
+
+ m_paused = !SUCCEEDED(hr);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void MediaPlayerPrivateMediaFoundation::pause()
</span><span class="cx"> {
</span><del>- notImplemented();
</del><ins>+ if (!m_mediaSession)
+ return;
+
+ m_paused = SUCCEEDED(m_mediaSession->Pause());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> IntSize MediaPlayerPrivateMediaFoundation::naturalSize() const
</span><span class="cx"> {
</span><del>- notImplemented();
- return IntSize(0, 0);
</del><ins>+ return m_size;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool MediaPlayerPrivateMediaFoundation::hasVideo() const
</span><span class="cx"> {
</span><del>- notImplemented();
- return false;
</del><ins>+ return m_hasVideo;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool MediaPlayerPrivateMediaFoundation::hasAudio() const
</span><span class="cx"> {
</span><del>- notImplemented();
- return false;
</del><ins>+ return m_hasAudio;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void MediaPlayerPrivateMediaFoundation::setVisible(bool)
</del><ins>+void MediaPlayerPrivateMediaFoundation::setVisible(bool visible)
</ins><span class="cx"> {
</span><del>- notImplemented();
</del><ins>+ m_visible = visible;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool MediaPlayerPrivateMediaFoundation::seeking() const
</span><span class="lines">@@ -121,8 +161,7 @@
</span><span class="cx">
</span><span class="cx"> bool MediaPlayerPrivateMediaFoundation::paused() const
</span><span class="cx"> {
</span><del>- notImplemented();
- return false;
</del><ins>+ return m_paused;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> MediaPlayer::NetworkState MediaPlayerPrivateMediaFoundation::networkState() const
</span><span class="lines">@@ -133,8 +172,7 @@
</span><span class="cx">
</span><span class="cx"> MediaPlayer::ReadyState MediaPlayerPrivateMediaFoundation::readyState() const
</span><span class="cx"> {
</span><del>- notImplemented();
- return MediaPlayer::HaveNothing;
</del><ins>+ return m_readyState;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> std::unique_ptr<PlatformTimeRanges> MediaPlayerPrivateMediaFoundation::buffered() const
</span><span class="lines">@@ -145,13 +183,32 @@
</span><span class="cx">
</span><span class="cx"> bool MediaPlayerPrivateMediaFoundation::didLoadingProgress() const
</span><span class="cx"> {
</span><del>- notImplemented();
- return false;
</del><ins>+ return m_loadingProgress;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void MediaPlayerPrivateMediaFoundation::setSize(const IntSize&)
</del><ins>+void MediaPlayerPrivateMediaFoundation::setSize(const IntSize& size)
</ins><span class="cx"> {
</span><del>- notImplemented();
</del><ins>+ m_size = size;
+
+ if (!m_videoDisplay)
+ return;
+
+ LayoutSize scrollOffset;
+
+ FrameView* view = nullptr;
+ if (m_player && m_player->cachedResourceLoader() && m_player->cachedResourceLoader()->document())
+ view = m_player->cachedResourceLoader()->document()->view();
+ if (view)
+ scrollOffset = view->scrollOffsetForFixedPosition();
+
+ int xPos = -scrollOffset.width().toInt() + m_lastPaintRect.x();
+ int yPos = -scrollOffset.height().toInt() + m_lastPaintRect.y();
+
+ if (m_hwndVideo && !m_lastPaintRect.isEmpty())
+ ::MoveWindow(m_hwndVideo, xPos, yPos, m_size.width(), m_size.height(), FALSE);
+
+ RECT rc = { 0, 0, m_size.width(), m_size.height() };
+ m_videoDisplay->SetVideoPosition(nullptr, &rc);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void MediaPlayerPrivateMediaFoundation::paint(GraphicsContext* context, const IntRect& rect)
</span><span class="lines">@@ -160,10 +217,397 @@
</span><span class="cx"> || !m_player->visible())
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- // TODO: Paint the contents of the video to the context
</del><ins>+ m_lastPaintRect = rect;
+
+ // We currently let Media Foundation handle the drawing, by providing a handle to the window to draw in.
+ // We should instead read individual frames from the stream, and paint them into the graphics context here.
+
</ins><span class="cx"> notImplemented();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool MediaPlayerPrivateMediaFoundation::createSession()
+{
+ if (FAILED(MFStartup(MF_VERSION, MFSTARTUP_FULL)))
+ return false;
+
+ if (FAILED(MFCreateMediaSession(nullptr, &m_mediaSession)))
+ return false;
+
+ // Get next event.
+ AsyncCallback* callback = new AsyncCallback(this, true);
+ HRESULT hr = m_mediaSession->BeginGetEvent(callback, nullptr);
+ ASSERT(SUCCEEDED(hr));
+
+ return true;
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+bool MediaPlayerPrivateMediaFoundation::endSession()
+{
+ if (m_mediaSession) {
+ m_mediaSession->Shutdown();
+ m_mediaSession->Release();
+ m_mediaSession = nullptr;
+ }
+
+ HRESULT hr = MFShutdown();
+ ASSERT(SUCCEEDED(hr));
+
+ return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::startCreateMediaSource(const String& url)
+{
+ if (FAILED(MFCreateSourceResolver(&m_sourceResolver)))
+ return false;
+
+ COMPtr<IUnknown> cancelCookie;
+ Vector<UChar> urlSource = url.charactersWithNullTermination();
+
+ AsyncCallback* callback = new AsyncCallback(this, false);
+
+ if (FAILED(m_sourceResolver->BeginCreateObjectFromURL(urlSource.data(), MF_RESOLUTION_MEDIASOURCE, nullptr, &cancelCookie, callback, nullptr)))
+ return false;
+
+ return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::endCreatedMediaSource(IMFAsyncResult* asyncResult)
+{
+ MF_OBJECT_TYPE objectType;
+ COMPtr<IUnknown> source;
+
+ HRESULT hr = m_sourceResolver->EndCreateObjectFromURL(asyncResult, &objectType, &source);
+ if (FAILED(hr))
+ return false;
+
+ hr = source->QueryInterface(IID_PPV_ARGS(&m_mediaSource));
+ if (FAILED(hr))
+ return false;
+
+ hr = asyncResult->GetStatus();
+ m_loadingProgress = SUCCEEDED(hr);
+
+ callOnMainThread([this] {
+ onCreatedMediaSource();
+ });
+
+ return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
+{
+ COMPtr<IMFMediaEvent> event;
+
+ // Get the event from the event queue.
+ HRESULT hr = m_mediaSession->EndGetEvent(asyncResult, &event);
+ if (FAILED(hr))
+ return false;
+
+ // Get the event type.
+ MediaEventType mediaEventType;
+ hr = event->GetType(&mediaEventType);
+ if (FAILED(hr))
+ return false;
+
+ switch (mediaEventType) {
+ case MESessionTopologySet:
+ callOnMainThread([this] {
+ onTopologySet();
+ });
+ break;
+
+ case MESessionClosed:
+ break;
+ }
+
+ if (mediaEventType != MESessionClosed) {
+ // For all other events, ask the media session for the
+ // next event in the queue.
+ AsyncCallback* callback = new AsyncCallback(this, true);
+
+ hr = m_mediaSession->BeginGetEvent(callback, nullptr);
+ if (FAILED(hr))
+ return false;
+ }
+
+ return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::createTopologyFromSource()
+{
+ // Create a new topology.
+ if (FAILED(MFCreateTopology(&m_topology)))
+ return false;
+
+ // Create the presentation descriptor for the media source.
+ if (FAILED(m_mediaSource->CreatePresentationDescriptor(&m_sourcePD)))
+ return false;
+
+ // Get the number of streams in the media source.
+ DWORD sourceStreams = 0;
+ if (FAILED(m_sourcePD->GetStreamDescriptorCount(&sourceStreams)))
+ return false;
+
+ // For each stream, create the topology nodes and add them to the topology.
+ for (DWORD i = 0; i < sourceStreams; i++) {
+ if (!addBranchToPartialTopology(i))
+ return false;
+ }
+
+ return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::addBranchToPartialTopology(int stream)
+{
+ // Get the stream descriptor for this stream.
+ COMPtr<IMFStreamDescriptor> sourceSD;
+ BOOL selected = FALSE;
+ if (FAILED(m_sourcePD->GetStreamDescriptorByIndex(stream, &selected, &sourceSD)))
+ return false;
+
+ // Create the topology branch only if the stream is selected.
+ // Otherwise, do nothing.
+ if (!selected)
+ return true;
+
+ // Create a source node for this stream.
+ COMPtr<IMFTopologyNode> sourceNode;
+ if (!createSourceStreamNode(sourceSD, sourceNode))
+ return false;
+
+ COMPtr<IMFTopologyNode> outputNode;
+ if (!createOutputNode(sourceSD, outputNode))
+ return false;
+
+ // Add both nodes to the topology.
+ if (FAILED(m_topology->AddNode(sourceNode.get())))
+ return false;
+
+ if (FAILED(m_topology->AddNode(outputNode.get())))
+ return false;
+
+ // Connect the source node to the output node.
+ if (FAILED(sourceNode->ConnectOutput(0, outputNode.get(), 0)))
+ return false;
+
+ return true;
+}
+
+LRESULT CALLBACK MediaPlayerPrivateMediaFoundation::VideoViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+LPCWSTR MediaPlayerPrivateMediaFoundation::registerVideoWindowClass()
+{
+ const LPCWSTR kVideoWindowClassName = L"WebVideoWindowClass";
+
+ static bool haveRegisteredWindowClass = false;
+ if (haveRegisteredWindowClass)
+ return kVideoWindowClassName;
+
+ haveRegisteredWindowClass = true;
+
+ WNDCLASSEX wcex;
+
+ wcex.cbSize = sizeof(WNDCLASSEX);
+
+ wcex.style = CS_DBLCLKS;
+ wcex.lpfnWndProc = VideoViewWndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = nullptr;
+ wcex.hIcon = nullptr;
+ wcex.hCursor = ::LoadCursor(0, IDC_ARROW);
+ wcex.hbrBackground = nullptr;
+ wcex.lpszMenuName = nullptr;
+ wcex.lpszClassName = kVideoWindowClassName;
+ wcex.hIconSm = nullptr;
+
+ if (RegisterClassEx(&wcex))
+ return kVideoWindowClassName;
+
+ return nullptr;
+}
+
+void MediaPlayerPrivateMediaFoundation::createVideoWindow()
+{
+ HWND hWndParent = nullptr;
+ FrameView* view = nullptr;
+ if (!m_player || !m_player->cachedResourceLoader() || !m_player->cachedResourceLoader()->document())
+ return;
+ view = m_player->cachedResourceLoader()->document()->view();
+ if (!view || !view->hostWindow())
+ return;
+ hWndParent = view->hostWindow()->platformPageClient();
+
+ m_hwndVideo = CreateWindowEx(WS_EX_NOACTIVATE | WS_EX_TRANSPARENT, registerVideoWindowClass(), 0, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ 0, 0, 0, 0, hWndParent, 0, 0, 0);
+}
+
+void MediaPlayerPrivateMediaFoundation::destroyVideoWindow()
+{
+ if (m_hwndVideo) {
+ DestroyWindow(m_hwndVideo);
+ m_hwndVideo = nullptr;
+ }
+}
+
+bool MediaPlayerPrivateMediaFoundation::createOutputNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>& node)
+{
+ if (!sourceSD)
+ return false;
+
+#ifndef NDEBUG
+ // Get the stream ID.
+ DWORD streamID = 0;
+ sourceSD->GetStreamIdentifier(&streamID); // Just for debugging, ignore any failures.
</ins><span class="cx"> #endif
</span><ins>+
+ COMPtr<IMFMediaTypeHandler> handler;
+ if (FAILED(sourceSD->GetMediaTypeHandler(&handler)))
+ return false;
+
+ GUID guidMajorType = GUID_NULL;
+ if (FAILED(handler->GetMajorType(&guidMajorType)))
+ return false;
+
+ // Create a downstream node.
+ if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node)))
+ return false;
+
+ // Create an IMFActivate object for the renderer, based on the media type.
+ COMPtr<IMFActivate> rendererActivate;
+ if (MFMediaType_Audio == guidMajorType) {
+ // Create the audio renderer.
+ if (FAILED(MFCreateAudioRendererActivate(&rendererActivate)))
+ return false;
+ m_hasAudio = true;
+ } else if (MFMediaType_Video == guidMajorType) {
+ // Create the video renderer.
+ if (FAILED(MFCreateVideoRendererActivate(m_hwndVideo, &rendererActivate)))
+ return false;
+ m_hasVideo = true;
+ } else
+ return false;
+
+ // Set the IActivate object on the output node.
+ if (FAILED(node->SetObject(rendererActivate.get())))
+ return false;
+
+ return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::createSourceStreamNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>& node)
+{
+ if (!m_mediaSource || !m_sourcePD || !sourceSD)
+ return false;
+
+ // Create the source-stream node.
+ HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
+ if (FAILED(hr))
+ return false;
+
+ // Set attribute: Pointer to the media source.
+ hr = node->SetUnknown(MF_TOPONODE_SOURCE, m_mediaSource.get());
+ if (FAILED(hr))
+ return false;
+
+ // Set attribute: Pointer to the presentation descriptor.
+ hr = node->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, m_sourcePD.get());
+ if (FAILED(hr))
+ return false;
+
+ // Set attribute: Pointer to the stream descriptor.
+ hr = node->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, sourceSD.get());
+ if (FAILED(hr))
+ return false;
+
+ return true;
+}
+
+void MediaPlayerPrivateMediaFoundation::onCreatedMediaSource()
+{
+ if (!createTopologyFromSource())
+ return;
+
+ // Set the topology on the media session.
+ HRESULT hr = m_mediaSession->SetTopology(0, m_topology.get());
+ ASSERT(SUCCEEDED(hr));
+}
+
+void MediaPlayerPrivateMediaFoundation::onTopologySet()
+{
+ if (FAILED(MFGetService(m_mediaSession.get(), MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&m_videoDisplay))))
+ return;
+
+ ASSERT(m_videoDisplay);
+
+ RECT rc = { 0, 0, m_size.width(), m_size.height() };
+ m_videoDisplay->SetVideoPosition(nullptr, &rc);
+
+ m_readyState = MediaPlayer::HaveFutureData;
+
+ ASSERT(m_player);
+ m_player->readyStateChanged();
+
+ play();
+ m_player->playbackStateChanged();
+}
+
+MediaPlayerPrivateMediaFoundation::AsyncCallback::AsyncCallback(MediaPlayerPrivateMediaFoundation* mediaPlayer, bool event)
+ : m_refCount(0)
+ , m_mediaPlayer(mediaPlayer)
+ , m_event(event)
+{
+}
+
+MediaPlayerPrivateMediaFoundation::AsyncCallback::~AsyncCallback()
+{
+}
+
+HRESULT MediaPlayerPrivateMediaFoundation::AsyncCallback::QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
+{
+ if (!IsEqualGUID(riid, IID_IMFAsyncCallback)) {
+ *ppvObject = nullptr;
+ return E_NOINTERFACE;
+ }
+ *ppvObject = this;
+ AddRef();
+ return S_OK;
+}
+
+ULONG STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::AddRef()
+{
+ m_refCount++;
+ return m_refCount;
+}
+
+ULONG STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::Release()
+{
+ m_refCount--;
+ ULONG refCount = m_refCount;
+ if (!refCount)
+ delete this;
+ return refCount;
+}
+
+HRESULT STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::GetParameters(__RPC__out DWORD *pdwFlags, __RPC__out DWORD *pdwQueue)
+{
+ // Returning E_NOTIMPL gives default values.
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::Invoke(__RPC__in_opt IMFAsyncResult *pAsyncResult)
+{
+ if (m_event)
+ m_mediaPlayer->endGetEvent(pAsyncResult);
+ else
+ m_mediaPlayer->endCreatedMediaSource(pAsyncResult);
+
+ return S_OK;
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicswinMediaPlayerPrivateMediaFoundationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h (178670 => 178671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h        2015-01-19 21:01:14 UTC (rev 178670)
+++ trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.h        2015-01-19 21:03:02 UTC (rev 178671)
</span><span class="lines">@@ -24,13 +24,19 @@
</span><span class="cx"> * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx"> */
</span><span class="cx">
</span><ins>+#include "COMPtr.h"
</ins><span class="cx"> #include "MediaPlayerPrivate.h"
</span><span class="cx">
</span><ins>+#include <Mfapi.h>
+#include <Mfidl.h>
+#include <evr.h>
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="cx"> class MediaPlayerPrivateMediaFoundation : public MediaPlayerPrivateInterface {
</span><span class="cx"> public:
</span><span class="cx"> MediaPlayerPrivateMediaFoundation(MediaPlayer*);
</span><ins>+ ~MediaPlayerPrivateMediaFoundation();
</ins><span class="cx"> static void registerMediaEngine(MediaEngineRegistrar);
</span><span class="cx">
</span><span class="cx"> static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*);
</span><span class="lines">@@ -67,9 +73,61 @@
</span><span class="cx"> virtual void paint(GraphicsContext*, const IntRect&);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>-
</del><span class="cx"> MediaPlayer* m_player;
</span><ins>+ IntSize m_size;
+ bool m_visible;
+ bool m_loadingProgress;
+ bool m_paused;
+ bool m_hasAudio;
+ bool m_hasVideo;
+ HWND m_hwndVideo;
+ MediaPlayer::ReadyState m_readyState;
+ IntRect m_lastPaintRect;
</ins><span class="cx">
</span><ins>+ COMPtr<IMFMediaSession> m_mediaSession;
+ COMPtr<IMFSourceResolver> m_sourceResolver;
+ COMPtr<IMFMediaSource> m_mediaSource;
+ COMPtr<IMFTopology> m_topology;
+ COMPtr<IMFPresentationDescriptor> m_sourcePD;
+ COMPtr<IMFVideoDisplayControl> m_videoDisplay;
+
+ bool createSession();
+ bool endSession();
+ bool startCreateMediaSource(const String& url);
+ bool endCreatedMediaSource(IMFAsyncResult*);
+ bool endGetEvent(IMFAsyncResult*);
+ bool createTopologyFromSource();
+ bool addBranchToPartialTopology(int stream);
+ bool createOutputNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>&);
+ bool createSourceStreamNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>&);
+
+ void onCreatedMediaSource();
+ void onTopologySet();
+
+ LPCWSTR registerVideoWindowClass();
+ void createVideoWindow();
+ void destroyVideoWindow();
+
+ static LRESULT CALLBACK VideoViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+ class AsyncCallback : public IMFAsyncCallback {
+ public:
+ AsyncCallback(MediaPlayerPrivateMediaFoundation*, bool event);
+ ~AsyncCallback();
+
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) override;
+ virtual ULONG STDMETHODCALLTYPE AddRef() override;
+ virtual ULONG STDMETHODCALLTYPE Release() override;
+
+ virtual HRESULT STDMETHODCALLTYPE GetParameters(__RPC__out DWORD *pdwFlags, __RPC__out DWORD *pdwQueue) override;
+ virtual HRESULT STDMETHODCALLTYPE Invoke(__RPC__in_opt IMFAsyncResult *pAsyncResult) override;
+
+ private:
+ ULONG m_refCount;
+ MediaPlayerPrivateMediaFoundation* m_mediaPlayer;
+ bool m_event;
+ };
+
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkWebKitLibrariesChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/WebKitLibraries/ChangeLog (178670 => 178671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebKitLibraries/ChangeLog        2015-01-19 21:01:14 UTC (rev 178670)
+++ trunk/WebKitLibraries/ChangeLog        2015-01-19 21:03:02 UTC (rev 178671)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-01-19 peavo@outlook.com <peavo@outlook.com>
+
+ [WinCairo][Video] Windows Media Foundation implementation is not completed.
+ https://bugs.webkit.org/show_bug.cgi?id=140337
+
+ Reviewed by Alex Christensen.
+
+ Link with Media Foundation libraries.
+
+ * win/tools/vsprops/WinCairo.props:
+
</ins><span class="cx"> 2015-01-01 Jeff Miller <jeffm@apple.com>
</span><span class="cx">
</span><span class="cx"> Update user-visible copyright strings to include 2015
</span></span></pre></div>
<a id="trunkWebKitLibrarieswintoolsvspropsWinCairoprops"></a>
<div class="modfile"><h4>Modified: trunk/WebKitLibraries/win/tools/vsprops/WinCairo.props (178670 => 178671)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebKitLibraries/win/tools/vsprops/WinCairo.props        2015-01-19 21:01:14 UTC (rev 178670)
+++ trunk/WebKitLibraries/win/tools/vsprops/WinCairo.props        2015-01-19 21:03:02 UTC (rev 178671)
</span><span class="lines">@@ -9,7 +9,7 @@
</span><span class="cx"> <PreprocessorDefinitions>WIN_CAIRO=1;WTF_PLATFORM_WIN_CAIRO=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</span><span class="cx"> </ClCompile>
</span><span class="cx"> <Link>
</span><del>- <AdditionalDependencies>cairo.lib;libjpeg.lib;zdll.lib;libpng.lib;%(AdditionalDependencies)</AdditionalDependencies>
</del><ins>+ <AdditionalDependencies>cairo.lib;libjpeg.lib;zdll.lib;libpng.lib;Mf.lib;Mfplat.lib;Mfuuid.lib;strmiids.lib;%(AdditionalDependencies)</AdditionalDependencies>
</ins><span class="cx"> <AdditionalLibraryDirectories>$(WebKit_Libraries)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</span><span class="cx"> </Link>
</span><span class="cx"> </ItemDefinitionGroup>
</span></span></pre>
</div>
</div>
</body>
</html>