<!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 &lt;peavo@outlook.com&gt; 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  &lt;peavo@outlook.com&gt;
+
+        [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  &lt;burg@cs.washington.edu&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Replay: convert to is&lt;T&gt; and downcast&lt;T&gt; 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 &quot;config.h&quot;
</span><span class="cx"> #include &quot;MediaPlayerPrivateMediaFoundation.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CachedResourceLoader.h&quot;
+#include &quot;FrameView.h&quot;
</ins><span class="cx"> #include &quot;GraphicsContext.h&quot;
</span><ins>+#include &quot;HostWindow.h&quot;
</ins><span class="cx"> #include &quot;NotImplemented.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #if USE(MEDIA_FOUNDATION)
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/MainThread.h&gt;
+
</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&lt;MediaPlayerPrivateInterface&gt; 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&lt;String&gt;&amp; types)
</span><span class="cx"> {
</span><del>-    notImplemented();
-    types = HashSet&lt;String&gt;();
</del><ins>+    types.add(String(&quot;video/mp4&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MediaPlayer::SupportsType MediaPlayerPrivateMediaFoundation::supportsType(const MediaEngineSupportParameters&amp; parameters)
</span><span class="cx"> {
</span><del>-    notImplemented();
</del><ins>+    if (parameters.type.isNull() || parameters.type.isEmpty())
+        return MediaPlayer::IsNotSupported;
+
+    if (parameters.type == &quot;video/mp4&quot;)
+        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&amp;)
</del><ins>+void MediaPlayerPrivateMediaFoundation::load(const String&amp; 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(&amp;varStart);
+    varStart.vt = VT_EMPTY;
+
+    HRESULT hr = m_mediaSession-&gt;Start(nullptr, &amp;varStart);
+    ASSERT(SUCCEEDED(hr));
+
+    PropVariantClear(&amp;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-&gt;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&lt;PlatformTimeRanges&gt; 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&amp;)
</del><ins>+void MediaPlayerPrivateMediaFoundation::setSize(const IntSize&amp; 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 &amp;&amp; m_player-&gt;cachedResourceLoader() &amp;&amp; m_player-&gt;cachedResourceLoader()-&gt;document())
+        view = m_player-&gt;cachedResourceLoader()-&gt;document()-&gt;view();
+    if (view)
+        scrollOffset = view-&gt;scrollOffsetForFixedPosition();
+
+    int xPos = -scrollOffset.width().toInt() + m_lastPaintRect.x();
+    int yPos = -scrollOffset.height().toInt() + m_lastPaintRect.y();
+
+    if (m_hwndVideo &amp;&amp; !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-&gt;SetVideoPosition(nullptr, &amp;rc);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaFoundation::paint(GraphicsContext* context, const IntRect&amp; rect)
</span><span class="lines">@@ -160,10 +217,397 @@
</span><span class="cx">         || !m_player-&gt;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, &amp;m_mediaSession)))
+        return false;
+
+    // Get next event.
+    AsyncCallback* callback = new AsyncCallback(this, true);
+    HRESULT hr = m_mediaSession-&gt;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-&gt;Shutdown();
+        m_mediaSession-&gt;Release();
+        m_mediaSession = nullptr;
+    }
+
+    HRESULT hr = MFShutdown();
+    ASSERT(SUCCEEDED(hr));
+
+    return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::startCreateMediaSource(const String&amp; url)
+{
+    if (FAILED(MFCreateSourceResolver(&amp;m_sourceResolver)))
+        return false;
+
+    COMPtr&lt;IUnknown&gt; cancelCookie;
+    Vector&lt;UChar&gt; urlSource = url.charactersWithNullTermination();
+
+    AsyncCallback* callback = new AsyncCallback(this, false);
+
+    if (FAILED(m_sourceResolver-&gt;BeginCreateObjectFromURL(urlSource.data(), MF_RESOLUTION_MEDIASOURCE, nullptr, &amp;cancelCookie, callback, nullptr)))
+        return false;
+
+    return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::endCreatedMediaSource(IMFAsyncResult* asyncResult)
+{
+    MF_OBJECT_TYPE objectType;
+    COMPtr&lt;IUnknown&gt; source;
+
+    HRESULT hr = m_sourceResolver-&gt;EndCreateObjectFromURL(asyncResult, &amp;objectType, &amp;source);
+    if (FAILED(hr))
+        return false;
+
+    hr = source-&gt;QueryInterface(IID_PPV_ARGS(&amp;m_mediaSource));
+    if (FAILED(hr))
+        return false;
+
+    hr = asyncResult-&gt;GetStatus();
+    m_loadingProgress = SUCCEEDED(hr);
+
+    callOnMainThread([this] {
+        onCreatedMediaSource();
+    });
+
+    return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
+{
+    COMPtr&lt;IMFMediaEvent&gt; event;
+
+    // Get the event from the event queue.
+    HRESULT hr = m_mediaSession-&gt;EndGetEvent(asyncResult, &amp;event);
+    if (FAILED(hr))
+        return false;
+
+    // Get the event type.
+    MediaEventType mediaEventType;
+    hr = event-&gt;GetType(&amp;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-&gt;BeginGetEvent(callback, nullptr);
+        if (FAILED(hr))
+            return false;
+    }
+
+    return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::createTopologyFromSource()
+{
+    // Create a new topology.
+    if (FAILED(MFCreateTopology(&amp;m_topology)))
+        return false;
+
+    // Create the presentation descriptor for the media source.
+    if (FAILED(m_mediaSource-&gt;CreatePresentationDescriptor(&amp;m_sourcePD)))
+        return false;
+
+    // Get the number of streams in the media source.
+    DWORD sourceStreams = 0;
+    if (FAILED(m_sourcePD-&gt;GetStreamDescriptorCount(&amp;sourceStreams)))
+        return false;
+
+    // For each stream, create the topology nodes and add them to the topology.
+    for (DWORD i = 0; i &lt; sourceStreams; i++) {
+        if (!addBranchToPartialTopology(i))
+            return false;
+    }
+
+    return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::addBranchToPartialTopology(int stream)
+{
+    // Get the stream descriptor for this stream.
+    COMPtr&lt;IMFStreamDescriptor&gt; sourceSD;
+    BOOL selected = FALSE;
+    if (FAILED(m_sourcePD-&gt;GetStreamDescriptorByIndex(stream, &amp;selected, &amp;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&lt;IMFTopologyNode&gt; sourceNode;
+    if (!createSourceStreamNode(sourceSD, sourceNode))
+        return false;
+
+    COMPtr&lt;IMFTopologyNode&gt; outputNode;
+    if (!createOutputNode(sourceSD, outputNode))
+        return false;
+
+    // Add both nodes to the topology.
+    if (FAILED(m_topology-&gt;AddNode(sourceNode.get())))
+        return false;
+
+    if (FAILED(m_topology-&gt;AddNode(outputNode.get())))
+        return false;
+
+    // Connect the source node to the output node.
+    if (FAILED(sourceNode-&gt;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&quot;WebVideoWindowClass&quot;;
+
+    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(&amp;wcex))
+        return kVideoWindowClassName;
+
+    return nullptr;
+}
+
+void MediaPlayerPrivateMediaFoundation::createVideoWindow()
+{
+    HWND hWndParent = nullptr;
+    FrameView* view = nullptr;
+    if (!m_player || !m_player-&gt;cachedResourceLoader() || !m_player-&gt;cachedResourceLoader()-&gt;document())
+        return;
+    view = m_player-&gt;cachedResourceLoader()-&gt;document()-&gt;view();
+    if (!view || !view-&gt;hostWindow())
+        return;
+    hWndParent = view-&gt;hostWindow()-&gt;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&lt;IMFStreamDescriptor&gt; sourceSD, COMPtr&lt;IMFTopologyNode&gt;&amp; node)
+{
+    if (!sourceSD)
+        return false;
+
+#ifndef NDEBUG
+    // Get the stream ID.
+    DWORD streamID = 0;
+    sourceSD-&gt;GetStreamIdentifier(&amp;streamID); // Just for debugging, ignore any failures.
</ins><span class="cx"> #endif
</span><ins>+
+    COMPtr&lt;IMFMediaTypeHandler&gt; handler;
+    if (FAILED(sourceSD-&gt;GetMediaTypeHandler(&amp;handler)))
+        return false;
+
+    GUID guidMajorType = GUID_NULL;
+    if (FAILED(handler-&gt;GetMajorType(&amp;guidMajorType)))
+        return false;
+
+    // Create a downstream node.
+    if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &amp;node)))
+        return false;
+
+    // Create an IMFActivate object for the renderer, based on the media type.
+    COMPtr&lt;IMFActivate&gt; rendererActivate;
+    if (MFMediaType_Audio == guidMajorType) {
+        // Create the audio renderer.
+        if (FAILED(MFCreateAudioRendererActivate(&amp;rendererActivate)))
+            return false;
+        m_hasAudio = true;
+    } else if (MFMediaType_Video == guidMajorType) {
+        // Create the video renderer.
+        if (FAILED(MFCreateVideoRendererActivate(m_hwndVideo, &amp;rendererActivate)))
+            return false;
+        m_hasVideo = true;
+    } else
+        return false;
+
+    // Set the IActivate object on the output node.
+    if (FAILED(node-&gt;SetObject(rendererActivate.get())))
+        return false;
+
+    return true;
+}
+
+bool MediaPlayerPrivateMediaFoundation::createSourceStreamNode(COMPtr&lt;IMFStreamDescriptor&gt; sourceSD, COMPtr&lt;IMFTopologyNode&gt;&amp; node)
+{
+    if (!m_mediaSource || !m_sourcePD || !sourceSD)
+        return false;
+
+    // Create the source-stream node.
+    HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &amp;node);
+    if (FAILED(hr))
+        return false;
+
+    // Set attribute: Pointer to the media source.
+    hr = node-&gt;SetUnknown(MF_TOPONODE_SOURCE, m_mediaSource.get());
+    if (FAILED(hr))
+        return false;
+
+    // Set attribute: Pointer to the presentation descriptor.
+    hr = node-&gt;SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, m_sourcePD.get());
+    if (FAILED(hr))
+        return false;
+
+    // Set attribute: Pointer to the stream descriptor.
+    hr = node-&gt;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-&gt;SetTopology(0, m_topology.get());
+    ASSERT(SUCCEEDED(hr));
+}
+
+void MediaPlayerPrivateMediaFoundation::onTopologySet()
+{
+    if (FAILED(MFGetService(m_mediaSession.get(), MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&amp;m_videoDisplay))))
+        return;
+
+    ASSERT(m_videoDisplay);
+
+    RECT rc = { 0, 0, m_size.width(), m_size.height() };
+    m_videoDisplay-&gt;SetVideoPosition(nullptr, &amp;rc);
+
+    m_readyState = MediaPlayer::HaveFutureData;
+
+    ASSERT(m_player);
+    m_player-&gt;readyStateChanged();
+
+    play();
+    m_player-&gt;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-&gt;endGetEvent(pAsyncResult);
+    else
+        m_mediaPlayer-&gt;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 &quot;COMPtr.h&quot;
</ins><span class="cx"> #include &quot;MediaPlayerPrivate.h&quot;
</span><span class="cx"> 
</span><ins>+#include &lt;Mfapi.h&gt;
+#include &lt;Mfidl.h&gt;
+#include &lt;evr.h&gt;
+
</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&lt;MediaPlayerPrivateInterface&gt; create(MediaPlayer*);
</span><span class="lines">@@ -67,9 +73,61 @@
</span><span class="cx">     virtual void paint(GraphicsContext*, const IntRect&amp;);
</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&lt;IMFMediaSession&gt; m_mediaSession;
+    COMPtr&lt;IMFSourceResolver&gt; m_sourceResolver;
+    COMPtr&lt;IMFMediaSource&gt; m_mediaSource;
+    COMPtr&lt;IMFTopology&gt; m_topology;
+    COMPtr&lt;IMFPresentationDescriptor&gt; m_sourcePD;
+    COMPtr&lt;IMFVideoDisplayControl&gt; m_videoDisplay;
+
+    bool createSession();
+    bool endSession();
+    bool startCreateMediaSource(const String&amp; url);
+    bool endCreatedMediaSource(IMFAsyncResult*);
+    bool endGetEvent(IMFAsyncResult*);
+    bool createTopologyFromSource();
+    bool addBranchToPartialTopology(int stream);
+    bool createOutputNode(COMPtr&lt;IMFStreamDescriptor&gt; sourceSD, COMPtr&lt;IMFTopologyNode&gt;&amp;);
+    bool createSourceStreamNode(COMPtr&lt;IMFStreamDescriptor&gt; sourceSD, COMPtr&lt;IMFTopologyNode&gt;&amp;);
+
+    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  &lt;peavo@outlook.com&gt;
+
+        [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  &lt;jeffm@apple.com&gt;
</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">       &lt;PreprocessorDefinitions&gt;WIN_CAIRO=1;WTF_PLATFORM_WIN_CAIRO=1;%(PreprocessorDefinitions)&lt;/PreprocessorDefinitions&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="cx">     &lt;Link&gt;
</span><del>-      &lt;AdditionalDependencies&gt;cairo.lib;libjpeg.lib;zdll.lib;libpng.lib;%(AdditionalDependencies)&lt;/AdditionalDependencies&gt;
</del><ins>+      &lt;AdditionalDependencies&gt;cairo.lib;libjpeg.lib;zdll.lib;libpng.lib;Mf.lib;Mfplat.lib;Mfuuid.lib;strmiids.lib;%(AdditionalDependencies)&lt;/AdditionalDependencies&gt;
</ins><span class="cx">       &lt;AdditionalLibraryDirectories&gt;$(WebKit_Libraries)\lib;%(AdditionalLibraryDirectories)&lt;/AdditionalLibraryDirectories&gt;
</span><span class="cx">     &lt;/Link&gt;
</span><span class="cx">   &lt;/ItemDefinitionGroup&gt;
</span></span></pre>
</div>
</div>

</body>
</html>