diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-26 18:50:11 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-26 18:50:11 +0000 |
commit | 8400e0328996ef46e390903b6c378549f7b13aa3 (patch) | |
tree | 351883f0cdc05aca6f61c0ca0cf9bb945d0b807d /chrome/browser/renderer_host/video_layer_x.cc | |
parent | 7386be50a212a569840f8da41be445cb00e90beb (diff) | |
download | chromium_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
Diffstat (limited to 'chrome/browser/renderer_host/video_layer_x.cc')
-rw-r--r-- | chrome/browser/renderer_host/video_layer_x.cc | 101 |
1 files changed, 101 insertions, 0 deletions
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()); +} |