| 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 |