OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/renderer_host/video_layer_x.h" | |
6 | |
7 #include "app/x11_util_internal.h" | |
8 #include "chrome/browser/renderer_host/render_process_host.h" | |
9 #include "media/base/yuv_convert.h" | |
10 | |
11 | |
12 // Assume that somewhere along the line, someone will do width * height * 4 | |
13 // with signed numbers. If the maximum value is 2**31, then 2**31 / 4 = | |
14 // 2**29 and floor(sqrt(2**29)) = 23170. | |
15 | |
16 // Max height and width for layers | |
17 static const int kMaxVideoLayerSize = 23170; | |
18 | |
19 VideoLayerX::VideoLayerX(RenderWidgetHost* widget, | |
20 const gfx::Size& size, | |
21 void* visual, | |
22 int depth) | |
23 : VideoLayer(widget, size), | |
24 visual_(visual), | |
25 depth_(depth), | |
26 display_(x11_util::GetXDisplay()), | |
27 rgb_frame_size_(0) { | |
28 DCHECK(!size.IsEmpty()); | |
29 | |
30 // Create our pixmap + GC representing an RGB version of a video frame. | |
31 pixmap_ = XCreatePixmap(display_, x11_util::GetX11RootWindow(), | |
32 size.width(), size.height(), depth_); | |
33 pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL); | |
34 pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display_, depth_); | |
35 } | |
36 | |
37 VideoLayerX::~VideoLayerX() { | |
38 // In unit tests, |display_| may be NULL. | |
39 if (!display_) | |
40 return; | |
41 | |
42 XFreePixmap(display_, pixmap_); | |
43 XFreeGC(display_, static_cast<GC>(pixmap_gc_)); | |
44 } | |
45 | |
46 void VideoLayerX::CopyTransportDIB(RenderProcessHost* process, | |
47 TransportDIB::Id bitmap, | |
48 const gfx::Rect& bitmap_rect) { | |
49 if (!display_) | |
50 return; | |
51 | |
52 if (bitmap_rect.IsEmpty()) | |
53 return; | |
54 | |
55 if (bitmap_rect.size() != size()) { | |
56 LOG(ERROR) << "Scaled video layer not supported."; | |
57 return; | |
58 } | |
59 | |
60 // Save location and size of destination bitmap. | |
61 rgb_rect_ = bitmap_rect; | |
62 | |
63 const int width = bitmap_rect.width(); | |
64 const int height = bitmap_rect.height(); | |
65 const size_t new_rgb_frame_size = static_cast<size_t>(width * height * 4); | |
66 | |
67 if (width <= 0 || width > kMaxVideoLayerSize || | |
68 height <= 0 || height > kMaxVideoLayerSize) | |
69 return; | |
70 | |
71 // Lazy allocate |rgb_frame_|. | |
72 if (!rgb_frame_.get() || rgb_frame_size_ < new_rgb_frame_size) { | |
73 // TODO(scherkus): handle changing dimensions and re-allocating. | |
74 CHECK(size() == rgb_rect_.size()); | |
75 rgb_frame_.reset(new uint8[new_rgb_frame_size]); | |
76 rgb_frame_size_ = new_rgb_frame_size; | |
77 } | |
78 | |
79 TransportDIB* dib = process->GetTransportDIB(bitmap); | |
80 if (!dib) | |
81 return; | |
82 | |
83 // Perform colour space conversion. | |
84 const uint8* y_plane = reinterpret_cast<uint8*>(dib->memory()); | |
85 const uint8* u_plane = y_plane + width * height; | |
86 const uint8* v_plane = u_plane + ((width * height) >> 2); | |
87 media::ConvertYUVToRGB32(y_plane, | |
88 u_plane, | |
89 v_plane, | |
90 rgb_frame_.get(), | |
91 width, | |
92 height, | |
93 width, | |
94 width / 2, | |
95 width * 4, | |
96 media::YV12); | |
97 | |
98 // Draw ARGB frame onto our pixmap. | |
99 x11_util::PutARGBImage(display_, visual_, depth_, pixmap_, pixmap_gc_, | |
100 rgb_frame_.get(), width, height); | |
101 } | |
102 | |
103 void VideoLayerX::XShow(XID target) { | |
104 if (rgb_rect_.IsEmpty()) | |
105 return; | |
106 | |
107 XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_), | |
108 0, 0, rgb_rect_.width(), rgb_rect_.height(), | |
109 rgb_rect_.x(), rgb_rect_.y()); | |
110 } | |
OLD | NEW |