summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-26 18:50:11 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-26 18:50:11 +0000
commit8400e0328996ef46e390903b6c378549f7b13aa3 (patch)
tree351883f0cdc05aca6f61c0ca0cf9bb945d0b807d
parent7386be50a212a569840f8da41be445cb00e90beb (diff)
downloadchromium_src-8400e0328996ef46e390903b6c378549f7b13aa3.zip
chromium_src-8400e0328996ef46e390903b6c378549f7b13aa3.tar.gz
chromium_src-8400e0328996ef46e390903b6c378549f7b13aa3.tar.bz2
Initial work for cross-process video rendering using layers.
Introduces VideoLayer, which is similar to BackingStore except handles YUV surfaces and conversion to RGB. BUG=33329 TEST=N/A Review URL: http://codereview.chromium.org/597066 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40137 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc1
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc45
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h16
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc20
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h1
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h1
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h1
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.cc6
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/video_layer.cc13
-rw-r--r--chrome/browser/renderer_host/video_layer.h51
-rw-r--r--chrome/browser/renderer_host/video_layer_x.cc101
-rw-r--r--chrome/browser/renderer_host/video_layer_x.h50
-rwxr-xr-xchrome/chrome_browser.gypi6
-rwxr-xr-xchrome/chrome_renderer.gypi2
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/render_messages_internal.h14
-rw-r--r--chrome/renderer/media/ipc_video_renderer.cc183
-rw-r--r--chrome/renderer/media/ipc_video_renderer.h108
-rw-r--r--chrome/renderer/render_view.cc12
-rw-r--r--chrome/renderer/render_widget.cc10
-rw-r--r--chrome/renderer/render_widget.h2
-rw-r--r--webkit/glue/media/video_renderer_impl.cc7
-rw-r--r--webkit/glue/media/video_renderer_impl.h37
-rw-r--r--webkit/glue/media/web_video_renderer.h39
-rw-r--r--webkit/glue/webmediaplayer_impl.cc15
-rw-r--r--webkit/glue/webmediaplayer_impl.h54
-rw-r--r--webkit/tools/test_shell/test_webview_delegate.cc4
-rw-r--r--webkit/webkit.gyp1
33 files changed, 785 insertions, 37 deletions
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 73148c8..793abd4 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -541,6 +541,7 @@ void BrowserRenderProcessHost::PropagateBrowserCommandLineToRenderer(
switches::kEnableGeolocation,
switches::kShowPaintRects,
switches::kEnableOpenMax,
+ switches::kEnableVideoLayering,
// We propagate the Chrome Frame command line here as well in case the
// renderer is not run in the sandbox.
switches::kChromeFrame,
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index ec43fe9..b54fb96 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/renderer_host/video_layer.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/render_messages.h"
#include "webkit/glue/webcursor.h"
@@ -127,6 +128,9 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnMsgClose)
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnMsgUpdateRect)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_CreateVideo, OnMsgCreateVideo)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateVideo, OnMsgUpdateVideo)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyVideo, OnMsgDestroyVideo)
IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnMsgInputEventAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnMsgFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnMsgBlur)
@@ -769,6 +773,27 @@ void RenderWidgetHost::OnMsgUpdateRect(
UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta);
}
+void RenderWidgetHost::OnMsgCreateVideo(const gfx::Size& size) {
+ DCHECK(!video_layer_.get());
+
+ video_layer_.reset(view_->AllocVideoLayer(size));
+
+ // TODO(scherkus): support actual video ids!
+ Send(new ViewMsg_CreateVideo_ACK(routing_id_, -1));
+}
+
+void RenderWidgetHost::OnMsgUpdateVideo(TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect) {
+ PaintVideoLayer(bitmap, bitmap_rect);
+
+ // TODO(scherkus): support actual video ids!
+ Send(new ViewMsg_UpdateVideo_ACK(routing_id_, -1));
+}
+
+void RenderWidgetHost::OnMsgDestroyVideo() {
+ video_layer_.reset();
+}
+
void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
// Log the time delta for processing an input event.
TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
@@ -987,6 +1012,26 @@ void RenderWidgetHost::ScrollBackingStoreRect(int dx, int dy,
backing_store->ScrollBackingStore(dx, dy, clip_rect, view_size);
}
+void RenderWidgetHost::PaintVideoLayer(TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect) {
+ if (is_hidden_ || !video_layer_.get())
+ return;
+
+ video_layer_->CopyTransportDIB(process(), bitmap, bitmap_rect);
+
+ // Don't update the view if we're hidden or if the view has been destroyed.
+ if (is_hidden_ || !view_)
+ return;
+
+ // Trigger a paint for the updated video layer bitmap.
+ std::vector<gfx::Rect> copy_rects;
+ copy_rects.push_back(bitmap_rect);
+
+ view_being_painted_ = true;
+ view_->DidPaintBackingStoreRects(copy_rects);
+ view_being_painted_ = false;
+}
+
void RenderWidgetHost::ToggleSpellPanel(bool is_currently_visible) {
Send(new ViewMsg_ToggleSpellPanel(routing_id(), is_currently_visible));
}
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index e96eae7..f1b402e 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -38,6 +38,7 @@ class RenderProcessHost;
class RenderWidgetHostView;
class RenderWidgetHostPaintingObserver;
class TransportDIB;
+class VideoLayer;
class WebCursor;
struct ViewHostMsg_ShowPopup_Params;
struct ViewHostMsg_UpdateRect_Params;
@@ -220,6 +221,9 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// renderer to send another paint.
void DonePaintingToBackingStore();
+ // Returns the video layer if it exists, NULL otherwise.
+ VideoLayer* const video_layer() { return video_layer_.get(); }
+
// Checks to see if we can give up focus to this widget through a JS call.
virtual bool CanBlur() const { return true; }
@@ -427,6 +431,9 @@ class RenderWidgetHost : public IPC::Channel::Listener,
void OnMsgClose();
void OnMsgRequestMove(const gfx::Rect& pos);
void OnMsgUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
+ void OnMsgCreateVideo(const gfx::Size& size);
+ void OnMsgUpdateVideo(TransportDIB::Id bitmap, const gfx::Rect& bitmap_rect);
+ void OnMsgDestroyVideo();
void OnMsgInputEventAck(const IPC::Message& message);
void OnMsgFocus();
void OnMsgBlur();
@@ -476,6 +483,12 @@ class RenderWidgetHost : public IPC::Channel::Listener,
void ScrollBackingStoreRect(int dx, int dy, const gfx::Rect& clip_rect,
const gfx::Size& view_size);
+ // Paints the entire given bitmap into the current video layer, if it exists.
+ // |bitmap_rect| specifies the destination size and absolute location of the
+ // bitmap on the backing store.
+ void PaintVideoLayer(TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect);
+
// Called by OnMsgInputEventAck() to process a keyboard event ack message.
void ProcessKeyboardEventAck(int type, bool processed);
@@ -613,6 +626,9 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// changed.
bool suppress_next_char_events_;
+ // Optional video YUV layer for used for out-of-process compositing.
+ scoped_ptr<VideoLayer> video_layer_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost);
};
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index f6f8788..339c6aa 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -26,6 +26,7 @@ class Message;
class BackingStore;
class RenderProcessHost;
class RenderWidgetHost;
+class VideoLayer;
class WebCursor;
struct WebMenuItem;
@@ -153,6 +154,9 @@ class RenderWidgetHostView {
// Allocate a backing store for this view
virtual BackingStore* AllocBackingStore(const gfx::Size& size) = 0;
+ // Allocate a video layer for this view.
+ virtual VideoLayer* AllocVideoLayer(const gfx::Size& size) = 0;
+
#if defined(OS_MACOSX)
// Display a native control popup menu for WebKit.
virtual void ShowPopupWithItems(gfx::Rect bounds,
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index e237071..338e960 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -30,6 +30,7 @@
#include "chrome/browser/renderer_host/gtk_im_context_wrapper.h"
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/renderer_host/video_layer_x.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/x11_util.h"
@@ -635,6 +636,17 @@ BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
gtk_widget_get_visual(view_.get())->depth);
}
+VideoLayer* RenderWidgetHostViewGtk::AllocVideoLayer(const gfx::Size& size) {
+ if (kUseGPURendering) {
+ NOTIMPLEMENTED();
+ return NULL;
+ }
+
+ return new VideoLayerX(host_, size,
+ x11_util::GetVisualFromGtkWidget(view_.get()),
+ gtk_widget_get_visual(view_.get())->depth);
+}
+
void RenderWidgetHostViewGtk::SetBackground(const SkBitmap& background) {
RenderWidgetHostView::SetBackground(background);
host_->Send(new ViewMsg_SetBackground(host_->routing_id(), background));
@@ -675,6 +687,14 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) {
// we don't need to double buffer.
backing_store->XShowRect(
paint_rect, x11_util::GetX11WindowFromGtkWidget(view_.get()));
+
+ // Paint the video layer using XCopyArea.
+ // TODO(scherkus): implement VideoLayerX::CairoShow() for grey
+ // blending.
+ VideoLayerX* video_layer = static_cast<VideoLayerX*>(
+ host_->video_layer());
+ if (video_layer)
+ video_layer->XShow(x11_util::GetX11WindowFromGtkWidget(view_.get()));
} else {
// If the grey blend is showing, we make two drawing calls. Use double
// buffering to prevent flicker. Use CairoShowRect because XShowRect
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index d17743a..974a4eb 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -68,6 +68,7 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
virtual void SelectionChanged(const std::string& text);
virtual void ShowingContextMenu(bool showing);
virtual BackingStore* AllocBackingStore(const gfx::Size& size);
+ virtual VideoLayer* AllocVideoLayer(const gfx::Size& size);
virtual void SetBackground(const SkBitmap& background);
virtual void CreatePluginContainer(gfx::PluginWindowHandle id);
virtual void DestroyPluginContainer(gfx::PluginWindowHandle id);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index db0c381..f9d0c92 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -105,6 +105,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
virtual void Destroy();
virtual void SetTooltipText(const std::wstring& tooltip_text);
virtual BackingStore* AllocBackingStore(const gfx::Size& size);
+ virtual VideoLayer* AllocVideoLayer(const gfx::Size& size);
virtual void ShowPopupWithItems(gfx::Rect bounds,
int item_height,
int selected_item,
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 79beb00..1f19167 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -425,6 +425,12 @@ BackingStore* RenderWidgetHostViewMac::AllocBackingStore(
return new BackingStoreMac(render_widget_host_, size);
}
+VideoLayer* RenderWidgetHostViewMac::AllocVideoLayer(
+ const gfx::Size& size) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
// Display a popup menu for WebKit using Cocoa widgets.
void RenderWidgetHostViewMac::ShowPopupWithItems(
gfx::Rect bounds,
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index 8e2ae47..923eab3 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -751,6 +751,12 @@ BackingStore* RenderWidgetHostViewWin::AllocBackingStore(
return new BackingStoreWin(render_widget_host_, size);
}
+VideoLayer* RenderWidgetHostViewWin::AllocVideoLayer(
+ const gfx::Size& size) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
void RenderWidgetHostViewWin::SetBackground(const SkBitmap& background) {
RenderWidgetHostView::SetBackground(background);
Send(new ViewMsg_SetBackground(render_widget_host_->routing_id(),
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 881b425..f43dd0f 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -136,6 +136,7 @@ class RenderWidgetHostViewWin
virtual void Destroy();
virtual void SetTooltipText(const std::wstring& tooltip_text);
virtual BackingStore* AllocBackingStore(const gfx::Size& size);
+ virtual VideoLayer* AllocVideoLayer(const gfx::Size& size);
virtual void SetBackground(const SkBitmap& background);
virtual bool ContainsNativeView(gfx::NativeView native_view) const;
virtual void SetVisuallyDeemphasized(bool deemphasized);
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc
index 91b7b914..1269c7b 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.cc
+++ b/chrome/browser/renderer_host/test/test_render_view_host.cc
@@ -79,6 +79,12 @@ BackingStore* TestRenderWidgetHostView::AllocBackingStore(
return new TestBackingStore(rwh_, size);
}
+VideoLayer* TestRenderWidgetHostView::AllocVideoLayer(
+ const gfx::Size& size) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
#if defined(OS_MACOSX)
gfx::Rect TestRenderWidgetHostView::GetWindowRect() {
return gfx::Rect();
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index fbeb388..2d8025b 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -69,6 +69,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
virtual void PrepareToDestroy() {}
virtual void SetTooltipText(const std::wstring& tooltip_text) {}
virtual BackingStore* AllocBackingStore(const gfx::Size& size);
+ virtual VideoLayer* AllocVideoLayer(const gfx::Size& size);
#if defined(OS_MACOSX)
virtual void ShowPopupWithItems(gfx::Rect bounds,
int item_height,
diff --git a/chrome/browser/renderer_host/video_layer.cc b/chrome/browser/renderer_host/video_layer.cc
new file mode 100644
index 0000000..1555060
--- /dev/null
+++ b/chrome/browser/renderer_host/video_layer.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/video_layer.h"
+
+VideoLayer::VideoLayer(RenderWidgetHost* widget, const gfx::Size& size)
+ : render_widget_host_(widget),
+ size_(size) {
+}
+
+VideoLayer::~VideoLayer() {
+}
diff --git a/chrome/browser/renderer_host/video_layer.h b/chrome/browser/renderer_host/video_layer.h
new file mode 100644
index 0000000..66a084f
--- /dev/null
+++ b/chrome/browser/renderer_host/video_layer.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_VIDEO_LAYER_H_
+#define CHROME_BROWSER_RENDERER_HOST_VIDEO_LAYER_H_
+
+#include "base/gfx/size.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/transport_dib.h"
+
+class RenderProcessHost;
+class RenderWidgetHost;
+
+namespace gfx {
+class Rect;
+}
+
+// Represents a layer of YUV data owned by RenderWidgetHost and composited with
+// the backing store. VideoLayer is responsible for converting to RGB as
+// needed.
+class VideoLayer {
+ public:
+ virtual ~VideoLayer();
+
+ RenderWidgetHost* render_widget_host() const { return render_widget_host_; }
+ const gfx::Size& size() { return size_; }
+
+ // Copy the incoming bitmap into this video layer. |bitmap| contains YUV
+ // pixel data in YV12 format and must be the same dimensions as this video
+ // layer. |bitmap_rect| specifies the absolute position and destination size
+ // of the bitmap on the backing store.
+ virtual void CopyTransportDIB(RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect) = 0;
+
+ protected:
+ // Can only be constructed via subclasses.
+ VideoLayer(RenderWidgetHost* widget, const gfx::Size& size);
+
+ private:
+ // The owner of this video layer.
+ RenderWidgetHost* render_widget_host_;
+
+ // The size of the video layer.
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoLayer);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_VIDEO_LAYER_H_
diff --git a/chrome/browser/renderer_host/video_layer_x.cc b/chrome/browser/renderer_host/video_layer_x.cc
new file mode 100644
index 0000000..ddd2c21
--- /dev/null
+++ b/chrome/browser/renderer_host/video_layer_x.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/video_layer_x.h"
+
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/common/x11_util_internal.h"
+#include "media/base/yuv_convert.h"
+
+VideoLayerX::VideoLayerX(RenderWidgetHost* widget,
+ const gfx::Size& size,
+ void* visual,
+ int depth)
+ : VideoLayer(widget, size),
+ visual_(visual),
+ depth_(depth),
+ display_(x11_util::GetXDisplay()) {
+ DCHECK(!size.IsEmpty());
+
+ // Create our pixmap + GC representing an RGB version of a video frame.
+ pixmap_ = XCreatePixmap(display_, x11_util::GetX11RootWindow(),
+ size.width(), size.height(), depth_);
+ pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
+ pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display_, depth_);
+}
+
+VideoLayerX::~VideoLayerX() {
+ // In unit tests, |display_| may be NULL.
+ if (!display_)
+ return;
+
+ XFreePixmap(display_, pixmap_);
+ XFreeGC(display_, static_cast<GC>(pixmap_gc_));
+}
+
+void VideoLayerX::CopyTransportDIB(RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect) {
+ if (!display_)
+ return;
+
+ if (bitmap_rect.IsEmpty())
+ return;
+
+ if (bitmap_rect.size() != size()) {
+ LOG(ERROR) << "Scaled video layer not supported.";
+ return;
+ }
+
+ // Save location and size of destination bitmap.
+ rgb_rect_ = bitmap_rect;
+
+ // Lazy allocate |rgb_frame_|.
+ if (!rgb_frame_.get()) {
+ // TODO(scherkus): handle changing dimensions and re-allocating.
+ CHECK(size() == rgb_rect_.size());
+
+ rgb_frame_.reset(new uint8[rgb_rect_.width() * rgb_rect_.height() * 4]);
+ }
+
+ const int width = bitmap_rect.width();
+ const int height = bitmap_rect.height();
+ // Assume that somewhere along the line, someone will do width * height * 4
+ // with signed numbers. If the maximum value is 2**31, then 2**31 / 4 =
+ // 2**29 and floor(sqrt(2**29)) = 23170.
+ if (width > 23170 || height > 23170)
+ return;
+
+ TransportDIB* dib = process->GetTransportDIB(bitmap);
+ if (!dib)
+ return;
+
+ // Perform colour space conversion.
+ const uint8* y_plane = reinterpret_cast<uint8*>(dib->memory());
+ const uint8* u_plane = y_plane + width * height;
+ const uint8* v_plane = u_plane + ((width * height) >> 2);
+ media::ConvertYUVToRGB32(y_plane,
+ u_plane,
+ v_plane,
+ rgb_frame_.get(),
+ width,
+ height,
+ width,
+ width / 2,
+ width * 4,
+ media::YV12);
+
+ // Draw ARGB frame onto our pixmap.
+ x11_util::PutARGBImage(display_, visual_, depth_, pixmap_, pixmap_gc_,
+ rgb_frame_.get(), width, height);
+}
+
+void VideoLayerX::XShow(XID target) {
+ if (rgb_rect_.IsEmpty())
+ return;
+
+ XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_),
+ 0, 0, rgb_rect_.width(), rgb_rect_.height(),
+ rgb_rect_.x(), rgb_rect_.y());
+}
diff --git a/chrome/browser/renderer_host/video_layer_x.h b/chrome/browser/renderer_host/video_layer_x.h
new file mode 100644
index 0000000..fbe45cc
--- /dev/null
+++ b/chrome/browser/renderer_host/video_layer_x.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_VIDEO_LAYER_X_
+#define CHROME_BROWSER_RENDERER_HOST_VIDEO_LAYER_X_
+
+#include "chrome/browser/renderer_host/video_layer.h"
+#include "chrome/common/x11_util.h"
+
+// Implements a YUV data layer using X to hold the RGB data.
+class VideoLayerX : public VideoLayer {
+ public:
+ VideoLayerX(RenderWidgetHost* widget, const gfx::Size& size, void* visual,
+ int depth);
+ virtual ~VideoLayerX();
+
+ virtual void CopyTransportDIB(RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect);
+
+ // Copy from the server-side video layer to the target window.
+ // Unlike BackingStore, we maintain the absolute position and destination
+ // size so passing in a rect is not required.
+ void XShow(XID target);
+
+ private:
+ // X Visual to get RGB mask information.
+ void* const visual_;
+ // Depth of the target window.
+ int depth_;
+ // Connection to the X server where this video layer will be displayed.
+ Display* const display_;
+
+ // Handle to the server side pixmap which is our video layer.
+ XID pixmap_;
+ // Graphics context for painting our video layer.
+ void* pixmap_gc_;
+ // Server side bits-per-pixel for |pixmap_|.
+ int pixmap_bpp_;
+
+ // Most recently converted frame stored as 32-bit ARGB.
+ scoped_array<uint8> rgb_frame_;
+ // Destination size and absolution position of the converted frame.
+ gfx::Rect rgb_rect_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoLayerX);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_VIDEO_LAYER_X_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 0616843..461fa04 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1649,8 +1649,12 @@
'browser/renderer_host/socket_stream_host.h',
'browser/renderer_host/sync_resource_handler.cc',
'browser/renderer_host/sync_resource_handler.h',
- 'browser/renderer_host/translation_service.h',
'browser/renderer_host/translation_service.cc',
+ 'browser/renderer_host/translation_service.h',
+ 'browser/renderer_host/video_layer.cc',
+ 'browser/renderer_host/video_layer.h',
+ 'browser/renderer_host/video_layer_x.cc',
+ 'browser/renderer_host/video_layer_x.h',
'browser/renderer_host/web_cache_manager.cc',
'browser/renderer_host/web_cache_manager.h',
'browser/renderer_host/x509_user_cert_resource_handler.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 155c8d2..7acf628 100755
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -59,6 +59,8 @@
'renderer/loadtimes_extension_bindings.cc',
'renderer/media/audio_renderer_impl.cc',
'renderer/media/audio_renderer_impl.h',
+ 'renderer/media/ipc_video_renderer.cc',
+ 'renderer/media/ipc_video_renderer.h',
'renderer/net/render_dns_master.cc',
'renderer/net/render_dns_master.h',
'renderer/net/render_dns_queue.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 29e22c4..505b07b 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -292,6 +292,10 @@ const char kEnableUserDataDirProfiles[] = "enable-udd-profiles";
// browser window.
const char kEnableVerticalTabs[] = "enable-vertical-tabs";
+// Enables video layering where video is rendered as a separate layer outside
+// of the backing store.
+const char kEnableVideoLayering[] = "enable-video-layering";
+
// Spawn threads to watch for excessive delays in specified message loops.
// User should set breakpoints on Alarm() to examine problematic thread.
// Usage: -enable-watchdog=[ui][io]
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 5ab8178..9af1ec9 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -101,6 +101,7 @@ extern const char kEnableSyncBookmarks[];
extern const char kEnableSyncPreferences[];
extern const char kEnableUserDataDirProfiles[];
extern const char kEnableVerticalTabs[];
+extern const char kEnableVideoLayering[];
extern const char kEnableWatchdog[];
extern const char kExperimentalSpellcheckerFeatures[];
extern const char kExplicitlyAllowedPorts[];
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index be83c9a8..bc8aefe 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -143,6 +143,12 @@ IPC_BEGIN_MESSAGES(View)
// This signals the render view that it can send another UpdateRect message.
IPC_MESSAGE_ROUTED0(ViewMsg_UpdateRect_ACK)
+ // Replies to creating and updating videos.
+ IPC_MESSAGE_ROUTED1(ViewMsg_CreateVideo_ACK,
+ int32 /* video_id */)
+ IPC_MESSAGE_ROUTED1(ViewMsg_UpdateVideo_ACK,
+ int32 /* video_id */)
+
// Message payload includes:
// 1. A blob that should be cast to WebInputEvent
// 2. An optional boolean value indicating if a RawKeyDown event is associated
@@ -1091,6 +1097,14 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateRect,
ViewHostMsg_UpdateRect_Params)
+ // Sent to create, update and destroy video layers.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_CreateVideo,
+ gfx::Size /* size */)
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateVideo,
+ TransportDIB::Id /* bitmap */,
+ gfx::Rect /* bitmap_rect */)
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DestroyVideo)
+
// Acknowledges receipt of a ViewMsg_HandleInputEvent message.
// Payload is a WebInputEvent::Type which is the type of the event, followed
// by an optional WebInputEvent which is provided only if the event was not
diff --git a/chrome/renderer/media/ipc_video_renderer.cc b/chrome/renderer/media/ipc_video_renderer.cc
new file mode 100644
index 0000000..0a98489
--- /dev/null
+++ b/chrome/renderer/media/ipc_video_renderer.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/media/ipc_video_renderer.h"
+
+#include "chrome/common/render_messages.h"
+#include "chrome/renderer/render_thread.h"
+#include "media/base/buffers.h"
+#include "media/base/media_format.h"
+
+IPCVideoRenderer::IPCVideoRenderer(
+ webkit_glue::WebMediaPlayerImpl::Proxy* proxy,
+ int routing_id)
+ : proxy_(proxy),
+ created_(false),
+ routing_id_(routing_id),
+ stopped_(false, false) {
+ // TODO(hclam): decide whether to do the following line in this thread or
+ // in the render thread.
+ proxy->SetVideoRenderer(this);
+}
+
+IPCVideoRenderer::~IPCVideoRenderer() {
+}
+
+// static
+media::FilterFactory* IPCVideoRenderer::CreateFactory(
+ webkit_glue::WebMediaPlayerImpl::Proxy* proxy,
+ int routing_id) {
+ return new media::FilterFactoryImpl2<
+ IPCVideoRenderer,
+ webkit_glue::WebMediaPlayerImpl::Proxy*,
+ int>(proxy, routing_id);
+}
+
+// static
+bool IPCVideoRenderer::IsMediaFormatSupported(
+ const media::MediaFormat& media_format) {
+ int width = 0;
+ int height = 0;
+ return ParseMediaFormat(media_format, &width, &height);
+}
+
+bool IPCVideoRenderer::OnInitialize(media::VideoDecoder* decoder) {
+ int width = 0;
+ int height = 0;
+ if (!ParseMediaFormat(decoder->media_format(), &width, &height))
+ return false;
+
+ video_size_.SetSize(width, height);
+
+ // TODO(scherkus): we're assuming YV12 here.
+ size_t size = (width * height) + ((width * height) >> 1);
+ uint32 epoch = static_cast<uint32>(reinterpret_cast<size_t>(this));
+ transport_dib_.reset(TransportDIB::Create(size, epoch));
+ CHECK(transport_dib_.get());
+
+ return true;
+}
+
+void IPCVideoRenderer::OnStop() {
+ stopped_.Signal();
+
+ proxy_->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &IPCVideoRenderer::DoDestroyVideo));
+}
+
+void IPCVideoRenderer::OnFrameAvailable() {
+ proxy_->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &IPCVideoRenderer::DoUpdateVideo));
+}
+
+void IPCVideoRenderer::SetRect(const gfx::Rect& rect) {
+ DCHECK(MessageLoop::current() == proxy_->message_loop());
+
+ // TODO(scherkus): this is actually a SetSize() call... there's a pending
+ // WebKit bug to get this fixed up. It would be nice if this was a real
+ // SetRect() call so we could get the absolute coordinates instead of relying
+ // on Paint().
+}
+
+void IPCVideoRenderer::Paint(skia::PlatformCanvas* canvas,
+ const gfx::Rect& dest_rect) {
+ DCHECK(MessageLoop::current() == proxy_->message_loop());
+
+ // Copy the rect for UpdateVideo messages.
+ video_rect_ = dest_rect;
+
+ if (!created_) {
+ created_ = true;
+ Send(new ViewHostMsg_CreateVideo(routing_id_, video_size_));
+
+ // Force an update in case the first frame arrived before the first
+ // Paint() call.
+ DoUpdateVideo();
+ }
+
+ // TODO(scherkus): code to punch a hole through the backing store goes here.
+ // We don't need it right away since we don't do a proper alpha composite
+ // between the browser BackingStore and VideoLayer.
+}
+
+void IPCVideoRenderer::Send(IPC::Message* msg) {
+ DCHECK(routing_id_ != MSG_ROUTING_NONE);
+ DCHECK(routing_id_ == msg->routing_id());
+
+ bool result = RenderThread::current()->Send(msg);
+ LOG_IF(ERROR, !result) << "RenderThread::current()->Send(msg) failed";
+}
+
+void IPCVideoRenderer::DoUpdateVideo() {
+ DCHECK(MessageLoop::current() == proxy_->message_loop());
+
+ // Nothing to do if we don't know where we are positioned on the page.
+ if (!created_ || video_rect_.IsEmpty() || stopped_.IsSignaled()) {
+ return;
+ }
+
+ scoped_refptr<media::VideoFrame> frame;
+ GetCurrentFrame(&frame);
+ if (!frame) {
+ return;
+ }
+
+ media::VideoSurface surface;
+ CHECK(frame->Lock(&surface));
+ CHECK(surface.width == static_cast<size_t>(video_size_.width()));
+ CHECK(surface.height == static_cast<size_t>(video_size_.height()));
+ CHECK(surface.format == media::VideoSurface::YV12);
+ CHECK(surface.planes == 3);
+
+ uint8* dest = reinterpret_cast<uint8*>(transport_dib_->memory());
+
+ // Copy Y plane.
+ const uint8* src = surface.data[media::VideoSurface::kYPlane];
+ size_t stride = surface.strides[media::VideoSurface::kYPlane];
+ for (size_t row = 0; row < surface.height; ++row) {
+ memcpy(dest, src, surface.width);
+ dest += surface.width;
+ src += stride;
+ }
+
+ // Copy U plane.
+ src = surface.data[media::VideoSurface::kUPlane];
+ stride = surface.strides[media::VideoSurface::kUPlane];
+ for (size_t row = 0; row < surface.height / 2; ++row) {
+ memcpy(dest, src, surface.width / 2);
+ dest += surface.width / 2;
+ src += stride;
+ }
+
+ // Copy V plane.
+ src = surface.data[media::VideoSurface::kVPlane];
+ stride = surface.strides[media::VideoSurface::kVPlane];
+ for (size_t row = 0; row < surface.height / 2; ++row) {
+ memcpy(dest, src, surface.width / 2);
+ dest += surface.width / 2;
+ src += stride;
+ }
+
+ // Sanity check!
+ uint8* expected = reinterpret_cast<uint8*>(transport_dib_->memory()) +
+ transport_dib_->size();
+ CHECK(dest == expected);
+
+ Send(new ViewHostMsg_UpdateVideo(routing_id_,
+ transport_dib_->id(),
+ video_rect_));
+
+ frame->Unlock();
+}
+
+void IPCVideoRenderer::DoDestroyVideo() {
+ DCHECK(MessageLoop::current() == proxy_->message_loop());
+
+ // We shouldn't receive any more messages after the browser receives this.
+ Send(new ViewHostMsg_DestroyVideo(routing_id_));
+
+ // Detach ourselves from the proxy.
+ proxy_->SetVideoRenderer(NULL);
+ proxy_ = NULL;
+}
diff --git a/chrome/renderer/media/ipc_video_renderer.h b/chrome/renderer/media/ipc_video_renderer.h
new file mode 100644
index 0000000..839df03
--- /dev/null
+++ b/chrome/renderer/media/ipc_video_renderer.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This video renderer implementation uses IPC to signal the browser process to
+// composite the video as a separate layer underneath the backing store.
+//
+// Extremely experimental. Use at own risk!
+
+#ifndef CHROME_RENDERER_MEDIA_IPC_VIDEO_RENDERER_H_
+#define CHROME_RENDERER_MEDIA_IPC_VIDEO_RENDERER_H_
+
+#include "base/gfx/rect.h"
+#include "base/gfx/size.h"
+#include "base/waitable_event.h"
+#include "chrome/common/transport_dib.h"
+#include "media/filters/video_renderer_base.h"
+#include "webkit/glue/media/web_video_renderer.h"
+#include "webkit/glue/webmediaplayer_impl.h"
+
+class IPCVideoRenderer : public webkit_glue::WebVideoRenderer {
+ public:
+ // WebVideoRenderer implementation.
+ virtual void SetRect(const gfx::Rect& rect);
+ virtual void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect);
+
+ void OnUpdateVideo();
+ void OnUpdateVideoAck();
+ void OnDestroyVideo();
+
+ // Static method for creating factory for this object.
+ static media::FilterFactory* CreateFactory(
+ webkit_glue::WebMediaPlayerImpl::Proxy* proxy,
+ int routing_id);
+
+ // FilterFactoryImpl2 implementation.
+ static bool IsMediaFormatSupported(const media::MediaFormat& media_format);
+
+ // TODO(scherkus): remove this mega-hack, see http://crbug.com/28207
+ class FactoryFactory : public webkit_glue::WebVideoRendererFactoryFactory {
+ public:
+ FactoryFactory(int routing_id)
+ : webkit_glue::WebVideoRendererFactoryFactory(),
+ routing_id_(routing_id) {
+ }
+
+ virtual media::FilterFactory* CreateFactory(
+ webkit_glue::WebMediaPlayerImpl::Proxy* proxy) {
+ return IPCVideoRenderer::CreateFactory(proxy, routing_id_);
+ }
+
+ private:
+ int routing_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(FactoryFactory);
+ };
+
+ protected:
+ // VideoRendererBase implementation.
+ virtual bool OnInitialize(media::VideoDecoder* decoder);
+ virtual void OnStop();
+ virtual void OnFrameAvailable();
+
+ private:
+ // Only the filter factories can create instances.
+ friend class media::FilterFactoryImpl2<
+ IPCVideoRenderer,
+ webkit_glue::WebMediaPlayerImpl::Proxy*,
+ int>;
+ IPCVideoRenderer(webkit_glue::WebMediaPlayerImpl::Proxy* proxy,
+ int routing_id);
+ virtual ~IPCVideoRenderer();
+
+ // Send an IPC message to the browser process. The routing ID of the message
+ // is assumed to match |routing_id_|.
+ void Send(IPC::Message* msg);
+
+ // Handles updating the video on the render thread.
+ void DoUpdateVideo();
+
+ // Handles destroying the video on the render thread.
+ void DoDestroyVideo();
+
+ // Pointer to our parent object that is called to request repaints.
+ scoped_refptr<webkit_glue::WebMediaPlayerImpl::Proxy> proxy_;
+
+ // The size of the video.
+ gfx::Size video_size_;
+
+ // The rect of the video.
+ gfx::Rect video_rect_;
+
+ // Whether we've created the video layer on the browser.
+ bool created_;
+
+ // Used to transporting YUV to the browser process.
+ int routing_id_;
+ scoped_ptr<TransportDIB> transport_dib_;
+
+ // Used to determine whether we've been instructed to stop.
+ // TODO(scherkus): work around because we don't have asynchronous stopping.
+ // Refer to http://crbug.com/16059
+ base::WaitableEvent stopped_;
+
+ DISALLOW_COPY_AND_ASSIGN(IPCVideoRenderer);
+};
+
+#endif // CHROME_RENDERER_MEDIA_IPC_VIDEO_RENDERER_H_
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 03c0850..b3ef04b 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -47,6 +47,7 @@
#include "chrome/renderer/geolocation_dispatcher.h"
#include "chrome/renderer/localized_error.h"
#include "chrome/renderer/media/audio_renderer_impl.h"
+#include "chrome/renderer/media/ipc_video_renderer.h"
#include "chrome/renderer/navigation_state.h"
#include "chrome/renderer/notification_provider.h"
#include "chrome/renderer/plugin_channel_host.h"
@@ -110,6 +111,7 @@
#include "webkit/glue/password_form.h"
#include "webkit/glue/plugins/plugin_list.h"
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
+#include "webkit/glue/media/video_renderer_impl.h"
#include "webkit/glue/webdropdata.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webmediaplayer_impl.h"
@@ -2140,7 +2142,15 @@ WebMediaPlayer* RenderView::createMediaPlayer(
factory->AddFactory(buffered_data_source_factory);
factory->AddFactory(simple_data_source_factory);
}
- return new webkit_glue::WebMediaPlayerImpl(client, factory);
+
+ webkit_glue::WebVideoRendererFactoryFactory* factory_factory = NULL;
+ if (cmd_line->HasSwitch(switches::kEnableVideoLayering)) {
+ factory_factory = new IPCVideoRenderer::FactoryFactory(routing_id_);
+ } else {
+ factory_factory = new webkit_glue::VideoRendererImpl::FactoryFactory();
+ }
+
+ return new webkit_glue::WebMediaPlayerImpl(client, factory, factory_factory);
}
WebCookieJar* RenderView::cookieJar() {
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc
index 5212635..75cd8d2 100644
--- a/chrome/renderer/render_widget.cc
+++ b/chrome/renderer/render_widget.cc
@@ -140,6 +140,8 @@ IPC_DEFINE_MESSAGE_MAP(RenderWidget)
IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
IPC_MESSAGE_HANDLER(ViewMsg_WasRestored, OnWasRestored)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
+ IPC_MESSAGE_HANDLER(ViewMsg_CreateVideo_ACK, OnCreateVideoAck)
+ IPC_MESSAGE_HANDLER(ViewMsg_UpdateVideo_ACK, OnUpdateVideoAck)
IPC_MESSAGE_HANDLER(ViewMsg_HandleInputEvent, OnHandleInputEvent)
IPC_MESSAGE_HANDLER(ViewMsg_MouseCaptureLost, OnMouseCaptureLost)
IPC_MESSAGE_HANDLER(ViewMsg_SetFocus, OnSetFocus)
@@ -277,6 +279,14 @@ void RenderWidget::OnUpdateRectAck() {
CallDoDeferredUpdate();
}
+void RenderWidget::OnCreateVideoAck(int32 video_id) {
+ // TODO(scherkus): handle CreateVideo_ACK with a message filter.
+}
+
+void RenderWidget::OnUpdateVideoAck(int32 video_id) {
+ // TODO(scherkus): handle UpdateVideo_ACK with a message filter.
+}
+
void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
void* iter = NULL;
diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h
index 571ca8b..feb3efe 100644
--- a/chrome/renderer/render_widget.h
+++ b/chrome/renderer/render_widget.h
@@ -151,6 +151,8 @@ class RenderWidget : public IPC::Channel::Listener,
virtual void OnWasHidden();
virtual void OnWasRestored(bool needs_repainting);
void OnUpdateRectAck();
+ void OnCreateVideoAck(int32 video_id);
+ void OnUpdateVideoAck(int32 video_id);
void OnRequestMoveAck();
void OnHandleInputEvent(const IPC::Message& message);
void OnMouseCaptureLost();
diff --git a/webkit/glue/media/video_renderer_impl.cc b/webkit/glue/media/video_renderer_impl.cc
index a7dc980..ba06d1c 100644
--- a/webkit/glue/media/video_renderer_impl.cc
+++ b/webkit/glue/media/video_renderer_impl.cc
@@ -18,6 +18,13 @@ namespace webkit_glue {
}
// static
+media::FilterFactory* VideoRendererImpl::CreateFactory(
+ WebMediaPlayerImpl::Proxy* proxy) {
+ return new media::FilterFactoryImpl1<VideoRendererImpl,
+ WebMediaPlayerImpl::Proxy*>(proxy);
+}
+
+// static
bool VideoRendererImpl::IsMediaFormatSupported(
const media::MediaFormat& media_format) {
int width = 0;
diff --git a/webkit/glue/media/video_renderer_impl.h b/webkit/glue/media/video_renderer_impl.h
index b0fde12..4bc7210 100644
--- a/webkit/glue/media/video_renderer_impl.h
+++ b/webkit/glue/media/video_renderer_impl.h
@@ -6,10 +6,6 @@
// inside video renderer thread and also WebKit's main thread. We need to be
// extra careful about members shared by two different threads, especially
// video frame buffers.
-//
-// Methods called from WebKit's main thread:
-// Paint()
-// SetRect()
#ifndef WEBKIT_GLUE_MEDIA_VIDEO_RENDERER_IMPL_H_
#define WEBKIT_GLUE_MEDIA_VIDEO_RENDERER_IMPL_H_
@@ -17,38 +13,41 @@
#include "base/gfx/rect.h"
#include "base/gfx/size.h"
#include "media/base/buffers.h"
-#include "media/base/factory.h"
#include "media/base/filters.h"
#include "media/filters/video_renderer_base.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/WebKit/chromium/public/WebMediaPlayer.h"
+#include "webkit/glue/media/web_video_renderer.h"
#include "webkit/glue/webmediaplayer_impl.h"
namespace webkit_glue {
-class VideoRendererImpl : public media::VideoRendererBase {
+class VideoRendererImpl : public WebVideoRenderer {
public:
- // Methods for painting called by the WebMediaPlayerImpl::Proxy
-
- // This method is called with the same rect as the Paint method and could
- // be used by future implementations to implement an improved color space +
- // scale code on a separate thread. Since we always do the stretch on the
- // same thread as the Paint method, we just ignore the call for now.
+ // WebVideoRenderer implementation.
virtual void SetRect(const gfx::Rect& rect);
-
- // Paint the current front frame on the |canvas| stretching it to fit the
- // |dest_rect|
virtual void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect);
// Static method for creating factory for this object.
- static media::FilterFactory* CreateFactory(WebMediaPlayerImpl::Proxy* proxy) {
- return new media::FilterFactoryImpl1<VideoRendererImpl,
- WebMediaPlayerImpl::Proxy*>(proxy);
- }
+ static media::FilterFactory* CreateFactory(WebMediaPlayerImpl::Proxy* proxy);
// FilterFactoryImpl1 implementation.
static bool IsMediaFormatSupported(const media::MediaFormat& media_format);
+ // TODO(scherkus): remove this mega-hack, see http://crbug.com/28207
+ class FactoryFactory : public webkit_glue::WebVideoRendererFactoryFactory {
+ public:
+ FactoryFactory() : webkit_glue::WebVideoRendererFactoryFactory() {}
+
+ virtual media::FilterFactory* CreateFactory(
+ webkit_glue::WebMediaPlayerImpl::Proxy* proxy) {
+ return VideoRendererImpl::CreateFactory(proxy);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FactoryFactory);
+ };
+
protected:
// Method called by VideoRendererBase during initialization.
virtual bool OnInitialize(media::VideoDecoder* decoder);
diff --git a/webkit/glue/media/web_video_renderer.h b/webkit/glue/media/web_video_renderer.h
new file mode 100644
index 0000000..8bafb1a
--- /dev/null
+++ b/webkit/glue/media/web_video_renderer.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#ifndef WEBKIT_GLUE_MEDIA_WEB_VIDEO_RENDERER_H_
+#define WEBKIT_GLUE_MEDIA_WEB_VIDEO_RENDERER_H_
+
+#include "media/filters/video_renderer_base.h"
+
+namespace webkit_glue {
+
+// A specialized version of a VideoRenderer designed to be used inside WebKit.
+class WebVideoRenderer : public media::VideoRendererBase {
+ public:
+ WebVideoRenderer() : media::VideoRendererBase() {}
+ virtual ~WebVideoRenderer() {}
+
+ // This method is called with the same rect as the Paint() method and could
+ // be used by future implementations to implement an improved color space +
+ // scale code on a separate thread. Since we always do the stretch on the
+ // same thread as the Paint method, we just ignore the call for now.
+ //
+ // Method called on the render thread.
+ virtual void SetRect(const gfx::Rect& rect) = 0;
+
+ // Paint the current front frame on the |canvas| stretching it to fit the
+ // |dest_rect|.
+ //
+ // Method called on the render thread.
+ virtual void Paint(skia::PlatformCanvas* canvas,
+ const gfx::Rect& dest_rect) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebVideoRenderer);
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_GLUE_MEDIA_WEB_VIDEO_RENDERER_H_
diff --git a/webkit/glue/webmediaplayer_impl.cc b/webkit/glue/webmediaplayer_impl.cc
index da4339a..8dd46b5 100644
--- a/webkit/glue/webmediaplayer_impl.cc
+++ b/webkit/glue/webmediaplayer_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -18,6 +18,7 @@
#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
#include "webkit/glue/media/video_renderer_impl.h"
+#include "webkit/glue/media/web_video_renderer.h"
using WebKit::WebCanvas;
using WebKit::WebRect;
@@ -80,7 +81,7 @@ void WebMediaPlayerImpl::Proxy::Repaint() {
}
void WebMediaPlayerImpl::Proxy::SetVideoRenderer(
- VideoRendererImpl* video_renderer) {
+ WebVideoRenderer* video_renderer) {
video_renderer_ = video_renderer;
}
@@ -181,7 +182,9 @@ void WebMediaPlayerImpl::Proxy::NetworkEventTask() {
// WebMediaPlayerImpl implementation
WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client,
- media::FilterFactoryCollection* factory)
+ media::FilterFactoryCollection* factory,
+ WebVideoRendererFactoryFactory*
+ video_renderer_factory)
: network_state_(WebKit::WebMediaPlayer::Empty),
ready_state_(WebKit::WebMediaPlayer::HaveNothing),
main_loop_(NULL),
@@ -194,6 +197,10 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client,
DCHECK(!main_loop_);
main_loop_ = MessageLoop::current();
+ // Make sure this gets deleted.
+ scoped_ptr<WebVideoRendererFactoryFactory>
+ scoped_video_renderer_factory(video_renderer_factory);
+
// Create the pipeline and its thread.
if (!pipeline_thread_.Start()) {
NOTREACHED() << "Could not start PipelineThread";
@@ -225,7 +232,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client,
}
filter_factory_->AddFactory(media::FFmpegVideoDecoder::CreateFactory());
filter_factory_->AddFactory(media::NullAudioRenderer::CreateFilterFactory());
- filter_factory_->AddFactory(VideoRendererImpl::CreateFactory(proxy_));
+ filter_factory_->AddFactory(video_renderer_factory->CreateFactory(proxy_));
}
WebMediaPlayerImpl::~WebMediaPlayerImpl() {
diff --git a/webkit/glue/webmediaplayer_impl.h b/webkit/glue/webmediaplayer_impl.h
index 7e2d8b2..b44cc62 100644
--- a/webkit/glue/webmediaplayer_impl.h
+++ b/webkit/glue/webmediaplayer_impl.h
@@ -1,7 +1,7 @@
-// Copyright (c) 2008-2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-//
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
// Delegate calls from WebCore::MediaPlayerPrivate to Chrome's video player.
// It contains PipelineImpl which is the actual media player pipeline, it glues
// the media player pipeline, data source, audio renderer and renderer.
@@ -14,7 +14,7 @@
// media::PipelineImpl
// The media playback pipeline.
//
-// VideoRendererImpl
+// WebVideoRenderer
// Video renderer object.
//
// WebMediaPlayerImpl::Proxy
@@ -29,7 +29,7 @@
// WebMediaPlayerImpl ------> PipelineImpl
// | ^ | r
// | | v
-// | | VideoRendererImpl
+// | | WebVideoRenderer
// | | ^ r
// | | |
// | r | r |
@@ -39,7 +39,7 @@
// v
// WebMediaPlayerClient
//
-// Notice that Proxy and VideoRendererImpl are referencing each other. This
+// Notice that Proxy and WebVideoRenderer are referencing each other. This
// interdependency has to be treated carefully.
//
// Other issues:
@@ -60,6 +60,7 @@
#include "base/lock.h"
#include "base/message_loop.h"
#include "base/ref_counted.h"
+#include "ipc/ipc_message.h"
#include "media/base/filters.h"
#include "media/base/pipeline_impl.h"
#include "skia/ext/platform_canvas.h"
@@ -74,7 +75,8 @@ class FilterFactoryCollection;
namespace webkit_glue {
-class VideoRendererImpl;
+class WebVideoRenderer;
+class WebVideoRendererFactoryFactory;
class WebMediaPlayerImpl : public WebKit::WebMediaPlayer,
public MessageLoop::DestructionObserver {
@@ -94,7 +96,7 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer,
// Public methods called from the video renderer.
void Repaint();
- void SetVideoRenderer(VideoRendererImpl* video_renderer);
+ void SetVideoRenderer(WebVideoRenderer* video_renderer);
// Public methods called from WebMediaPlayerImpl.
void Paint(skia::PlatformCanvas* canvas, const gfx::Rect& dest_rect);
@@ -109,6 +111,9 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer,
void PipelineErrorCallback();
void NetworkEventCallback();
+ // Returns the message loop used by the proxy.
+ MessageLoop* message_loop() { return render_loop_; }
+
private:
friend class base::RefCountedThreadSafe<Proxy>;
@@ -135,7 +140,7 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer,
// The render message loop where WebKit lives.
MessageLoop* render_loop_;
WebMediaPlayerImpl* webmediaplayer_;
- scoped_refptr<VideoRendererImpl> video_renderer_;
+ scoped_refptr<WebVideoRenderer> video_renderer_;
Lock lock_;
int outstanding_repaints_;
@@ -161,8 +166,12 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer,
// audio renderer is a fake audio device that plays silence. Provider of the
// |factory| can override the default filters by adding extra filters to
// |factory| before calling this method.
+ //
+ // |video_renderer_factory| is used to construct a factory that should create
+ // a subclass of WebVideoRenderer. Is deleted by WebMediaPlayerImpl.
WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client,
- media::FilterFactoryCollection* factory);
+ media::FilterFactoryCollection* factory,
+ WebVideoRendererFactoryFactory* video_renderer_factory);
virtual ~WebMediaPlayerImpl();
virtual void load(const WebKit::WebURL& url);
@@ -295,6 +304,29 @@ class WebMediaPlayerImpl : public WebKit::WebMediaPlayer,
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl);
};
+// TODO(scherkus): WebMediaPlayerImpl creates and injects its Proxy into a
+// video renderer factory, so we need to (unfortunately) have a factory of a
+// factory so we can receive the proxy pointer without violating the
+// separation of renderer code from webkit glue code. This is part of a
+// longer-term plan to rethink our FilterFactory strategy (refer to
+// http://crbug.com/28207).
+//
+// Either that or we rethink this Proxy business as a short-term solution.
+class WebVideoRendererFactoryFactory {
+ public:
+ WebVideoRendererFactoryFactory() {}
+ virtual ~WebVideoRendererFactoryFactory() {}
+
+ // Creates a FilterFactory which should be capable of creating a
+ // WebVideoRenderer subclass.
+ virtual media::FilterFactory* CreateFactory(
+ WebMediaPlayerImpl::Proxy* proxy) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebVideoRendererFactoryFactory);
+};
+
+
} // namespace webkit_glue
#endif // WEBKIT_GLUE_WEBMEDIAPLAYER_IMPL_H_
diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc
index 4c5db40..1cff673 100644
--- a/webkit/tools/test_shell/test_webview_delegate.cc
+++ b/webkit/tools/test_shell/test_webview_delegate.cc
@@ -44,6 +44,7 @@
#include "webkit/glue/media/buffered_data_source.h"
#include "webkit/glue/media/media_resource_loader_bridge_factory.h"
#include "webkit/glue/media/simple_data_source.h"
+#include "webkit/glue/media/video_renderer_impl.h"
#include "webkit/glue/webdropdata.h"
#include "webkit/glue/webplugin_impl.h"
#include "webkit/glue/webpreferences.h"
@@ -667,7 +668,8 @@ WebMediaPlayer* TestWebViewDelegate::createMediaPlayer(
bridge_factory);
factory->AddFactory(buffered_data_source_factory);
factory->AddFactory(simple_data_source_factory);
- return new webkit_glue::WebMediaPlayerImpl(client, factory);
+ return new webkit_glue::WebMediaPlayerImpl(
+ client, factory, new webkit_glue::VideoRendererImpl::FactoryFactory());
}
bool TestWebViewDelegate::allowPlugins(WebFrame* frame,
diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp
index 4c1f9a1..fce94944 100644
--- a/webkit/webkit.gyp
+++ b/webkit/webkit.gyp
@@ -240,6 +240,7 @@
'glue/media/simple_data_source.h',
'glue/media/video_renderer_impl.cc',
'glue/media/video_renderer_impl.h',
+ 'glue/media/web_video_renderer.h',
'glue/plugins/coregraphics_private_symbols_mac.h',
'glue/plugins/nphostapi.h',
'glue/plugins/fake_plugin_window_tracker_mac.h',