Unreviewed, rolling out r146819.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Mar 2013 23:29:40 +0000 (23:29 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Mar 2013 23:29:40 +0000 (23:29 +0000)
http://trac.webkit.org/changeset/146819
https://bugs.webkit.org/show_bug.cgi?id=113249

broke component build (Requested by danakj on #webkit).

Patch by Sheriff Bot <webkit.review.bot@gmail.com> on 2013-03-25

Source/Platform:

* chromium/public/WebVideoFrame.h:

Source/WebKit/chromium:

* WebKit.gypi:
* public/WebMediaPlayerClient.h:
(WebKit):
* src/WebMediaPlayerClientImpl.cpp:
(WebKit::WebMediaPlayerClientImpl::~WebMediaPlayerClientImpl):
(WebKit::WebMediaPlayerClientImpl::readyStateChanged):
(WebKit::WebMediaPlayerClientImpl::repaint):
(WebKit::WebMediaPlayerClientImpl::setOpaque):
(WebKit::WebMediaPlayerClientImpl::disableAcceleratedCompositing):
(WebKit::WebMediaPlayerClientImpl::loadRequested):
(WebKit::WebMediaPlayerClientImpl::loadInternal):
(WebKit):
(WebKit::WebMediaPlayerClientImpl::platformLayer):
(WebKit::WebMediaPlayerClientImpl::paint):
(WebKit::WebMediaPlayerClientImpl::supportsAcceleratedRendering):
(WebKit::WebMediaPlayerClientImpl::acceleratedRenderingInUse):
(WebKit::WebMediaPlayerClientImpl::setVideoFrameProviderClient):
(WebKit::WebMediaPlayerClientImpl::getCurrentFrame):
(WebKit::WebMediaPlayerClientImpl::putCurrentFrame):
(WebKit::WebMediaPlayerClientImpl::create):
(WebKit::WebMediaPlayerClientImpl::supportsType):
* src/WebMediaPlayerClientImpl.h:
(WebKit):
(WebMediaPlayerClientImpl):
* tests/WebMediaPlayerClientImplTest.cpp: Added.
(WebKit):
(FakeWebMediaPlayerClientImpl):
(WebKit::FakeWebMediaPlayerClientImpl::create):
(WebKit::FakeWebMediaPlayerClientImpl::FakeWebMediaPlayerClientImpl):
(FakeVideoFrameProviderClient):
(WebKit::FakeVideoFrameProviderClient::create):
(WebKit::FakeVideoFrameProviderClient::~FakeVideoFrameProviderClient):
(WebKit::FakeVideoFrameProviderClient::didReceiveFrame):
(WebKit::FakeVideoFrameProviderClient::didUpdateMatrix):
(WebKit::FakeVideoFrameProviderClient::stopUsingProvider):
(WebKit::FakeVideoFrameProviderClient::provider):
(WebKit::FakeVideoFrameProviderClient::FakeVideoFrameProviderClient):
(WebKit::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@146824 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/Platform/ChangeLog
Source/Platform/chromium/public/WebVideoFrame.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/WebKit.gypi
Source/WebKit/chromium/public/WebMediaPlayerClient.h
Source/WebKit/chromium/src/WebMediaPlayerClientImpl.cpp
Source/WebKit/chromium/src/WebMediaPlayerClientImpl.h
Source/WebKit/chromium/tests/WebMediaPlayerClientImplTest.cpp [new file with mode: 0644]

index a5ca6af..b62997b 100644 (file)
@@ -1,3 +1,13 @@
+2013-03-25  Sheriff Bot  <webkit.review.bot@gmail.com>
+
+        Unreviewed, rolling out r146819.
+        http://trac.webkit.org/changeset/146819
+        https://bugs.webkit.org/show_bug.cgi?id=113249
+
+        broke component build (Requested by danakj on #webkit).
+
+        * chromium/public/WebVideoFrame.h:
+
 2013-03-25  Dana Jansens  <danakj@chromium.org>
 
         [chromium] Move ownership of compositor VideoLayer to WebMediaPlayer
index 36dc2e4..0cf3e7c 100644 (file)
@@ -31,8 +31,6 @@
 #ifndef WebVideoFrame_h
 #define WebVideoFrame_h
 
-#define REMOVE_WEBVIDEOFRAME
-
 #include "WebRect.h"
 #include "WebSize.h"
 
index 101fdf2..0959795 100644 (file)
@@ -1,3 +1,50 @@
+2013-03-25  Sheriff Bot  <webkit.review.bot@gmail.com>
+
+        Unreviewed, rolling out r146819.
+        http://trac.webkit.org/changeset/146819
+        https://bugs.webkit.org/show_bug.cgi?id=113249
+
+        broke component build (Requested by danakj on #webkit).
+
+        * WebKit.gypi:
+        * public/WebMediaPlayerClient.h:
+        (WebKit):
+        * src/WebMediaPlayerClientImpl.cpp:
+        (WebKit::WebMediaPlayerClientImpl::~WebMediaPlayerClientImpl):
+        (WebKit::WebMediaPlayerClientImpl::readyStateChanged):
+        (WebKit::WebMediaPlayerClientImpl::repaint):
+        (WebKit::WebMediaPlayerClientImpl::setOpaque):
+        (WebKit::WebMediaPlayerClientImpl::disableAcceleratedCompositing):
+        (WebKit::WebMediaPlayerClientImpl::loadRequested):
+        (WebKit::WebMediaPlayerClientImpl::loadInternal):
+        (WebKit):
+        (WebKit::WebMediaPlayerClientImpl::platformLayer):
+        (WebKit::WebMediaPlayerClientImpl::paint):
+        (WebKit::WebMediaPlayerClientImpl::supportsAcceleratedRendering):
+        (WebKit::WebMediaPlayerClientImpl::acceleratedRenderingInUse):
+        (WebKit::WebMediaPlayerClientImpl::setVideoFrameProviderClient):
+        (WebKit::WebMediaPlayerClientImpl::getCurrentFrame):
+        (WebKit::WebMediaPlayerClientImpl::putCurrentFrame):
+        (WebKit::WebMediaPlayerClientImpl::create):
+        (WebKit::WebMediaPlayerClientImpl::supportsType):
+        * src/WebMediaPlayerClientImpl.h:
+        (WebKit):
+        (WebMediaPlayerClientImpl):
+        * tests/WebMediaPlayerClientImplTest.cpp: Added.
+        (WebKit):
+        (FakeWebMediaPlayerClientImpl):
+        (WebKit::FakeWebMediaPlayerClientImpl::create):
+        (WebKit::FakeWebMediaPlayerClientImpl::FakeWebMediaPlayerClientImpl):
+        (FakeVideoFrameProviderClient):
+        (WebKit::FakeVideoFrameProviderClient::create):
+        (WebKit::FakeVideoFrameProviderClient::~FakeVideoFrameProviderClient):
+        (WebKit::FakeVideoFrameProviderClient::didReceiveFrame):
+        (WebKit::FakeVideoFrameProviderClient::didUpdateMatrix):
+        (WebKit::FakeVideoFrameProviderClient::stopUsingProvider):
+        (WebKit::FakeVideoFrameProviderClient::provider):
+        (WebKit::FakeVideoFrameProviderClient::FakeVideoFrameProviderClient):
+        (WebKit::TEST):
+
 2013-03-25  Dana Jansens  <danakj@chromium.org>
 
         [chromium] Move ownership of compositor VideoLayer to WebMediaPlayer
index 6e4a4d8..89c8259 100644 (file)
             'tests/WebImageTest.cpp',
             'tests/WebInputEventConversionTest.cpp',
             'tests/WebInputEventFactoryTestMac.mm',
+            'tests/WebMediaPlayerClientImplTest.cpp',
             'tests/WebPageNewSerializerTest.cpp',
             'tests/WebPageSerializerTest.cpp',
             'tests/WebPluginContainerTest.cpp',
index 8161ae6..089937c 100644 (file)
@@ -36,7 +36,6 @@
 namespace WebKit {
 
 class WebFrame;
-class WebLayer;
 class WebMediaSource;
 class WebPlugin;
 class WebRequest;
@@ -81,8 +80,7 @@ public:
     // Returns 0 if the plugin could not be instantiated.
     virtual WebPlugin* createHelperPlugin(const WebString& pluginType, WebFrame*) = 0;
     virtual void closeHelperPlugin() = 0;
-    virtual bool needsWebLayerForVideo() const = 0;
-    virtual void setWebLayer(WebLayer*) = 0;
+    virtual void disableAcceleratedCompositing() = 0;
 protected:
     ~WebMediaPlayerClient() { }
 };
index bc77af2..aab74e2 100644 (file)
@@ -39,6 +39,7 @@
 #include <public/WebSize.h>
 #include <public/WebString.h>
 #include <public/WebURL.h>
+#include <public/WebVideoLayer.h>
 
 #if USE(ACCELERATED_COMPOSITING)
 #include "RenderLayerCompositor.h"
@@ -93,6 +94,21 @@ WebMediaPlayer* WebMediaPlayerClientImpl::mediaPlayer() const
 
 WebMediaPlayerClientImpl::~WebMediaPlayerClientImpl()
 {
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_videoFrameProviderClient)
+        m_videoFrameProviderClient->stopUsingProvider();
+    // No need for a lock here, as getCurrentFrame/putCurrentFrame can't be
+    // called now that the client is no longer using this provider. Also, load()
+    // and this destructor are called from the same thread.
+    if (m_webMediaPlayer)
+        m_webMediaPlayer->setStreamTextureClient(0);
+#endif
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_videoLayer)
+        GraphicsLayerChromium::unregisterContentsLayer(m_videoLayer->layer());
+#endif
+
     // Explicitly destroy the WebMediaPlayer to allow verification of tear down.
     m_webMediaPlayer.clear();
 
@@ -114,6 +130,14 @@ void WebMediaPlayerClientImpl::readyStateChanged()
 {
     ASSERT(m_mediaPlayer);
     m_mediaPlayer->readyStateChanged();
+#if USE(ACCELERATED_COMPOSITING)
+    if (hasVideo() && supportsAcceleratedRendering() && !m_videoLayer) {
+        m_videoLayer = adoptPtr(Platform::current()->compositorSupport()->createVideoLayer(this));
+
+        m_videoLayer->layer()->setOpaque(m_opaque);
+        GraphicsLayerChromium::registerContentsLayer(m_videoLayer->layer());
+    }
+#endif
 }
 
 void WebMediaPlayerClientImpl::volumeChanged(float newVolume)
@@ -137,8 +161,10 @@ void WebMediaPlayerClientImpl::timeChanged()
 void WebMediaPlayerClientImpl::repaint()
 {
     ASSERT(m_mediaPlayer);
-    if (m_videoLayer)
-        m_videoLayer->invalidate();
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_videoLayer && supportsAcceleratedRendering())
+        m_videoLayer->layer()->invalidate();
+#endif
     m_mediaPlayer->repaint();
 }
 
@@ -165,7 +191,7 @@ void WebMediaPlayerClientImpl::setOpaque(bool opaque)
 #if USE(ACCELERATED_COMPOSITING)
     m_opaque = opaque;
     if (m_videoLayer)
-        m_videoLayer->setOpaque(m_opaque);
+        m_videoLayer->layer()->setOpaque(m_opaque);
 #endif
 }
 
@@ -273,25 +299,9 @@ void WebMediaPlayerClientImpl::closeHelperPlugin()
     m_helperPlugin = 0;
 }
 
-void WebMediaPlayerClientImpl::setWebLayer(WebLayer* layer)
+void WebMediaPlayerClientImpl::disableAcceleratedCompositing()
 {
-    if (layer == m_videoLayer)
-        return;
-
-    // If either of the layers is null we need to enable or disable compositing. This is done by triggering a style recalc.
-    if (!m_videoLayer || !layer) {
-        HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient());
-        if (element)
-            element->setNeedsStyleRecalc(WebCore::SyntheticStyleChange);
-    }
-
-    if (m_videoLayer)
-        GraphicsLayerChromium::unregisterContentsLayer(m_videoLayer);
-    m_videoLayer = layer;
-    if (m_videoLayer) {
-        m_videoLayer->setOpaque(m_opaque);
-        GraphicsLayerChromium::registerContentsLayer(m_videoLayer);
-    }
+    m_supportsAcceleratedCompositing = false;
 }
 
 // MediaPlayerPrivateInterface -------------------------------------------------
@@ -316,6 +326,7 @@ void WebMediaPlayerClientImpl::load(const String& url, PassRefPtr<WebCore::Media
 
 void WebMediaPlayerClientImpl::loadRequested()
 {
+    MutexLocker locker(m_webMediaPlayerMutex);
     if (m_preload == MediaPlayer::None) {
 #if ENABLE(WEB_AUDIO)
         m_audioSourceProvider.wrap(0); // Clear weak reference to m_webMediaPlayer's WebAudioSourceProvider.
@@ -333,13 +344,6 @@ void WebMediaPlayerClientImpl::loadInternal()
 #endif
 
     Frame* frame = static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient())->document()->frame();
-
-    // This does not actually check whether the hardware can support accelerated
-    // compositing, but only if the flag is set. However, this is checked lazily
-    // in WebViewImpl::setIsAcceleratedCompositingActive() and will fail there
-    // if necessary.
-    m_needsWebLayerForVideo = frame->contentRenderer()->compositor()->hasAcceleratedCompositing();
-
     m_webMediaPlayer = createWebMediaPlayer(this, m_url, frame);
     if (m_webMediaPlayer) {
 #if ENABLE(WEB_AUDIO)
@@ -364,10 +368,13 @@ void WebMediaPlayerClientImpl::cancelLoad()
         m_webMediaPlayer->cancelLoad();
 }
 
+#if USE(ACCELERATED_COMPOSITING)
 WebLayer* WebMediaPlayerClientImpl::platformLayer() const
 {
-    return m_videoLayer;
+    ASSERT(m_supportsAcceleratedCompositing);
+    return m_videoLayer ? m_videoLayer->layer() : 0;
 }
+#endif
 
 PlatformMedia WebMediaPlayerClientImpl::platformMedia() const
 {
@@ -605,10 +612,12 @@ void WebMediaPlayerClientImpl::setSize(const IntSize& size)
 
 void WebMediaPlayerClientImpl::paint(GraphicsContext* context, const IntRect& rect)
 {
+#if USE(ACCELERATED_COMPOSITING)
     // If we are using GPU to render video, ignore requests to paint frames into
-    // canvas because it will be taken care of by the VideoLayer.
+    // canvas because it will be taken care of by WebVideoLayer.
     if (acceleratedRenderingInUse())
         return;
+#endif
     paintCurrentFrameInContext(context, rect);
 }
 
@@ -710,25 +719,69 @@ AudioSourceProvider* WebMediaPlayerClientImpl::audioSourceProvider()
 }
 #endif
 
-bool WebMediaPlayerClientImpl::needsWebLayerForVideo() const
+#if USE(ACCELERATED_COMPOSITING)
+bool WebMediaPlayerClientImpl::supportsAcceleratedRendering() const
+{
+    return m_supportsAcceleratedCompositing;
+}
+
+bool WebMediaPlayerClientImpl::acceleratedRenderingInUse()
 {
-    return m_needsWebLayerForVideo;
+    return m_videoLayer && m_videoLayer->active();
 }
 
-bool WebMediaPlayerClientImpl::supportsAcceleratedRendering() const
+void WebMediaPlayerClientImpl::setVideoFrameProviderClient(WebVideoFrameProvider::Client* client)
 {
-    return !!m_videoLayer;
+    MutexLocker locker(m_webMediaPlayerMutex);
+    if (m_videoFrameProviderClient)
+        m_videoFrameProviderClient->stopUsingProvider();
+    m_videoFrameProviderClient = client;
+    if (m_webMediaPlayer)
+        m_webMediaPlayer->setStreamTextureClient(client ? this : 0);
 }
 
-bool WebMediaPlayerClientImpl::acceleratedRenderingInUse()
+WebVideoFrame* WebMediaPlayerClientImpl::getCurrentFrame()
 {
-    return m_videoLayer && !m_videoLayer->isOrphan();
+    // This function is called only by the client.
+    MutexLocker locker(m_webMediaPlayerMutex);
+    ASSERT(!m_currentVideoFrame);
+    ASSERT(m_videoFrameProviderClient);
+    if (m_webMediaPlayer)
+        m_currentVideoFrame = m_webMediaPlayer->getCurrentFrame();
+    return m_currentVideoFrame;
+}
+
+void WebMediaPlayerClientImpl::putCurrentFrame(WebVideoFrame* videoFrame)
+{
+    // This function is called only by the client.
+    MutexLocker locker(m_webMediaPlayerMutex);
+    ASSERT(videoFrame == m_currentVideoFrame);
+    ASSERT(m_videoFrameProviderClient);
+    if (!videoFrame)
+        return;
+    if (m_webMediaPlayer)
+        m_webMediaPlayer->putCurrentFrame(videoFrame);
+    m_currentVideoFrame = 0;
 }
+#endif
 
 PassOwnPtr<MediaPlayerPrivateInterface> WebMediaPlayerClientImpl::create(MediaPlayer* player)
 {
     OwnPtr<WebMediaPlayerClientImpl> client = adoptPtr(new WebMediaPlayerClientImpl());
     client->m_mediaPlayer = player;
+
+#if USE(ACCELERATED_COMPOSITING)
+    Frame* frame = static_cast<HTMLMediaElement*>(
+        client->m_mediaPlayer->mediaPlayerClient())->document()->frame();
+
+    // This does not actually check whether the hardware can support accelerated
+    // compositing, but only if the flag is set. However, this is checked lazily
+    // in WebViewImpl::setIsAcceleratedCompositingActive() and will fail there
+    // if necessary.
+    client->m_supportsAcceleratedCompositing =
+        frame->contentRenderer()->compositor()->hasAcceleratedCompositing();
+#endif
+
     return client.release();
 }
 
@@ -776,13 +829,28 @@ void WebMediaPlayerClientImpl::startDelayedLoad()
     loadInternal();
 }
 
+void WebMediaPlayerClientImpl::didReceiveFrame()
+{
+    // No lock since this gets called on the client's thread.
+    m_videoFrameProviderClient->didReceiveFrame();
+}
+
+void WebMediaPlayerClientImpl::didUpdateMatrix(const float* matrix)
+{
+    // No lock since this gets called on the client's thread.
+    m_videoFrameProviderClient->didUpdateMatrix(matrix);
+}
+
 WebMediaPlayerClientImpl::WebMediaPlayerClientImpl()
     : m_mediaPlayer(0)
+    , m_currentVideoFrame(0)
     , m_delayingLoad(false)
     , m_preload(MediaPlayer::MetaData)
-    , m_videoLayer(0)
+#if USE(ACCELERATED_COMPOSITING)
+    , m_supportsAcceleratedCompositing(false)
     , m_opaque(false)
-    , m_needsWebLayerForVideo(false)
+    , m_videoFrameProviderClient(0)
+#endif
 {
 }
 
index 32e3c4d..82d8f27 100644 (file)
@@ -37,6 +37,8 @@
 #include "MediaPlayerPrivate.h"
 #include "WebAudioSourceProviderClient.h"
 #include "WebMediaPlayerClient.h"
+#include "WebStreamTextureClient.h"
+#include <public/WebVideoFrameProvider.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
 
@@ -47,10 +49,16 @@ namespace WebKit {
 class WebHelperPluginImpl;
 class WebAudioSourceProvider;
 class WebMediaPlayer;
+class WebVideoLayer;
 
 // This class serves as a bridge between WebCore::MediaPlayer and
 // WebKit::WebMediaPlayer.
-class WebMediaPlayerClientImpl : public WebCore::MediaPlayerPrivateInterface, public WebMediaPlayerClient {
+class WebMediaPlayerClientImpl : public WebCore::MediaPlayerPrivateInterface
+#if USE(ACCELERATED_COMPOSITING)
+                               , public WebVideoFrameProvider
+#endif
+                               , public WebMediaPlayerClient
+                               , public WebStreamTextureClient {
 
 public:
     static bool isEnabled();
@@ -82,8 +90,7 @@ public:
     virtual void keyNeeded(const WebString& keySystem, const WebString& sessionId, const unsigned char* initData, unsigned initDataLength);
     virtual WebPlugin* createHelperPlugin(const WebString& pluginType, WebFrame*);
     virtual void closeHelperPlugin();
-    virtual bool needsWebLayerForVideo() const;
-    virtual void setWebLayer(WebLayer*);
+    virtual void disableAcceleratedCompositing();
 
     // MediaPlayerPrivateInterface methods:
     virtual void load(const WTF::String& url);
@@ -143,14 +150,25 @@ public:
     virtual WebCore::AudioSourceProvider* audioSourceProvider();
 #endif
 
+#if USE(ACCELERATED_COMPOSITING)
     virtual bool supportsAcceleratedRendering() const;
 
+    // WebVideoFrameProvider methods:
+    virtual void setVideoFrameProviderClient(WebVideoFrameProvider::Client*);
+    virtual WebVideoFrame* getCurrentFrame();
+    virtual void putCurrentFrame(WebVideoFrame*);
+#endif
+
 #if ENABLE(ENCRYPTED_MEDIA)
     virtual WebCore::MediaPlayer::MediaKeyException generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength) OVERRIDE;
     virtual WebCore::MediaPlayer::MediaKeyException addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId) OVERRIDE;
     virtual WebCore::MediaPlayer::MediaKeyException cancelKeyRequest(const String& keySystem, const String& sessionId) OVERRIDE;
 #endif
 
+    // WebStreamTextureClient methods:
+    virtual void didReceiveFrame();
+    virtual void didUpdateMatrix(const float*);
+
 protected:
     WebMediaPlayerClientImpl();
 private:
@@ -171,15 +189,20 @@ private:
     bool acceleratedRenderingInUse();
 #endif
 
+    Mutex m_webMediaPlayerMutex; // Guards the m_webMediaPlayer
     WebCore::MediaPlayer* m_mediaPlayer;
     OwnPtr<WebMediaPlayer> m_webMediaPlayer;
+    WebVideoFrame* m_currentVideoFrame;
     WebCore::KURL m_url;
     bool m_delayingLoad;
     WebCore::MediaPlayer::Preload m_preload;
     RefPtr<WebHelperPluginImpl> m_helperPlugin;
-    WebLayer* m_videoLayer;
+#if USE(ACCELERATED_COMPOSITING)
+    OwnPtr<WebVideoLayer> m_videoLayer;
+    bool m_supportsAcceleratedCompositing;
     bool m_opaque;
-    bool m_needsWebLayerForVideo;
+    WebVideoFrameProvider::Client* m_videoFrameProviderClient;
+#endif
     static bool m_isEnabled;
 
 #if ENABLE(WEB_AUDIO)
diff --git a/Source/WebKit/chromium/tests/WebMediaPlayerClientImplTest.cpp b/Source/WebKit/chromium/tests/WebMediaPlayerClientImplTest.cpp
new file mode 100644 (file)
index 0000000..56a1a6e
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "WebMediaPlayerClientImpl.h"
+
+#include <gtest/gtest.h>
+#include <wtf/PassOwnPtr.h>
+
+using namespace WebKit;
+
+namespace {
+
+class FakeWebMediaPlayerClientImpl : public WebMediaPlayerClientImpl {
+public:
+    static PassOwnPtr<FakeWebMediaPlayerClientImpl> create() { return adoptPtr(new FakeWebMediaPlayerClientImpl()); }
+
+private:
+    FakeWebMediaPlayerClientImpl() { }
+};
+
+class FakeVideoFrameProviderClient : public WebVideoFrameProvider::Client {
+public:
+    static PassOwnPtr<FakeVideoFrameProviderClient> create(WebVideoFrameProvider* provider)
+    {
+        return adoptPtr(new FakeVideoFrameProviderClient(provider));
+    }
+
+    virtual ~FakeVideoFrameProviderClient()
+    {
+        if (m_provider)
+            m_provider->setVideoFrameProviderClient(0);
+    }
+
+    // WebKit::WebVideoFrameProvider::Client implementation.
+    virtual void didReceiveFrame() { }
+    virtual void didUpdateMatrix(const float*) { }
+    virtual void stopUsingProvider()
+    {
+        m_provider = 0;
+    }
+
+    WebVideoFrameProvider* provider() const { return m_provider; }
+
+private:
+    FakeVideoFrameProviderClient(WebVideoFrameProvider* provider)
+        : m_provider(provider)
+    {
+        m_provider->setVideoFrameProviderClient(this);
+    }
+
+    WebVideoFrameProvider* m_provider;
+};
+
+TEST(WebMediaPlayerClientImplTest, InitialNullVideoClient)
+{
+    // No explict checks in this test; just make sure it doesn't crash.
+    OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+    provider->setVideoFrameProviderClient(0);
+}
+
+TEST(WebMediaPlayerClientImplTest, SetAndUnsetVideoClient)
+{
+    OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+    OwnPtr<FakeVideoFrameProviderClient> client(FakeVideoFrameProviderClient::create(provider.get()));
+
+    EXPECT_EQ(client->provider(), provider.get());
+
+    provider->setVideoFrameProviderClient(0);
+    ASSERT_FALSE(client->provider());
+}
+
+TEST(WebMediaPlayerClientImplTest, DestroyProvider)
+{
+    OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+    OwnPtr<FakeVideoFrameProviderClient> client(FakeVideoFrameProviderClient::create(provider.get()));
+
+    EXPECT_EQ(client->provider(), provider);
+    provider.clear();
+    ASSERT_FALSE(client->provider());
+}
+
+TEST(WebMediaPlayerClientImplTest, SetMultipleVideoClients)
+{
+    OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+    OwnPtr<FakeVideoFrameProviderClient> firstClient(FakeVideoFrameProviderClient::create(provider.get()));
+    EXPECT_EQ(firstClient->provider(), provider);
+
+    OwnPtr<FakeVideoFrameProviderClient> secondClient(FakeVideoFrameProviderClient::create(provider.get()));
+    EXPECT_FALSE(firstClient->provider());
+    EXPECT_EQ(secondClient->provider(), provider);
+
+    provider.clear();
+    ASSERT_FALSE(firstClient->provider());
+    ASSERT_FALSE(secondClient->provider());
+}
+
+}