Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(805)

Side by Side Diff: remoting/host/capturer_linux.cc

Issue 6780014: Clean up remoting project (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix a compile glitch on Windows Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/capturer_linux.h" 5 #include "remoting/host/capturer.h"
6 6
7 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h> 8 #include <X11/Xutil.h>
9 #include <X11/extensions/Xdamage.h> 9 #include <X11/extensions/Xdamage.h>
10 10
11 #include <set> 11 #include <set>
12 12
13 #include "base/basictypes.h"
13 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
14 #include "remoting/base/types.h" 16 #include "remoting/base/types.h"
15 #include "remoting/host/capturer_helper.h" 17 #include "remoting/host/capturer_helper.h"
16 #include "remoting/host/x_server_pixel_buffer.h" 18 #include "remoting/host/x_server_pixel_buffer.h"
17 19
18 namespace remoting { 20 namespace remoting {
19 21
20 // Private Implementation pattern to avoid leaking the X11 types into the header 22 namespace {
21 // file. 23
22 class CapturerLinuxPimpl : public Capturer { 24 // A class to perform capturing for Linux.
25 class CapturerLinux : public Capturer {
23 public: 26 public:
24 CapturerLinuxPimpl(); 27 CapturerLinux();
25 virtual ~CapturerLinuxPimpl(); 28 virtual ~CapturerLinux();
26 29
27 bool Init(); // TODO(ajwong): Do we really want this to be synchronous?
28 30
29 // Capturer interface. 31 // Capturer interface.
30 virtual void ScreenConfigurationChanged(); 32 virtual void ScreenConfigurationChanged() OVERRIDE;
31 virtual media::VideoFrame::Format pixel_format() const; 33 virtual media::VideoFrame::Format pixel_format() const OVERRIDE;
32 virtual void ClearInvalidRects(); 34 virtual void ClearInvalidRects() OVERRIDE;
33 virtual void InvalidateRects(const InvalidRects& inval_rects); 35 virtual void InvalidateRects(const InvalidRects& inval_rects) OVERRIDE;
34 virtual void InvalidateScreen(const gfx::Size& size); 36 virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE;
35 virtual void InvalidateFullScreen(); 37 virtual void InvalidateFullScreen() OVERRIDE;
36 virtual void CaptureInvalidRects(CaptureCompletedCallback* callback); 38 virtual void CaptureInvalidRects(CaptureCompletedCallback* callback) OVERRIDE;
37 virtual const gfx::Size& size_most_recent() const; 39 virtual const gfx::Size& size_most_recent() const OVERRIDE;
38 40
39 private: 41 private:
42 bool Init(); // TODO(ajwong): Do we really want this to be synchronous?
40 void CalculateInvalidRects(); 43 void CalculateInvalidRects();
41 void CaptureRects(const InvalidRects& rects, 44 void CaptureRects(const InvalidRects& rects,
42 Capturer::CaptureCompletedCallback* callback); 45 Capturer::CaptureCompletedCallback* callback);
43 46
44 void DeinitXlib(); 47 void DeinitXlib();
45 // We expose two forms of blitting to handle variations in the pixel format. 48 // We expose two forms of blitting to handle variations in the pixel format.
46 // In FastBlit, the operation is effectively a memcpy. 49 // In FastBlit, the operation is effectively a memcpy.
47 void FastBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data); 50 void FastBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data);
48 void SlowBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data); 51 void SlowBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data);
49 52
(...skipping 26 matching lines...) Expand all
76 bool capture_fullscreen_; 79 bool capture_fullscreen_;
77 80
78 // Format of pixels returned in buffer. 81 // Format of pixels returned in buffer.
79 media::VideoFrame::Format pixel_format_; 82 media::VideoFrame::Format pixel_format_;
80 83
81 // Invalid rects in the last capture. This is used to synchronize current with 84 // Invalid rects in the last capture. This is used to synchronize current with
82 // the previous buffer used. 85 // the previous buffer used.
83 InvalidRects last_invalid_rects_; 86 InvalidRects last_invalid_rects_;
84 87
85 // Last capture buffer used. 88 // Last capture buffer used.
86 uint8* last_buffer_; 89 uint8* last_buffer_;
Lambros 2011/04/01 15:54:00 Nit: Maybe a bit too pedantic, but do we want DISA
dmac 2011/04/01 21:15:07 Done.
87 }; 90 };
88 91
89 CapturerLinux::CapturerLinux() 92 CapturerLinux::CapturerLinux()
90 : pimpl_(new CapturerLinuxPimpl()) {
91 // TODO(ajwong): This should be moved into an Init() method on Capturer
92 // itself. Then we can remove the CHECK.
93 CHECK(pimpl_->Init());
94 }
95
96 CapturerLinux::~CapturerLinux() {
97 }
98
99 void CapturerLinux::ScreenConfigurationChanged() {
100 pimpl_->ScreenConfigurationChanged();
101 }
102
103 media::VideoFrame::Format CapturerLinux::pixel_format() const {
104 return pimpl_->pixel_format();
105 }
106
107 void CapturerLinux::ClearInvalidRects() {
108 pimpl_->ClearInvalidRects();
109 }
110
111 void CapturerLinux::InvalidateRects(const InvalidRects& inval_rects) {
112 pimpl_->InvalidateRects(inval_rects);
113 }
114
115 void CapturerLinux::InvalidateScreen(const gfx::Size& size) {
116 pimpl_->InvalidateScreen(size);
117 }
118
119 void CapturerLinux::InvalidateFullScreen() {
120 pimpl_->InvalidateFullScreen();
121 }
122
123 void CapturerLinux::CaptureInvalidRects(CaptureCompletedCallback* callback) {
124 pimpl_->CaptureInvalidRects(callback);
125 }
126
127 const gfx::Size& CapturerLinux::size_most_recent() const {
128 return pimpl_->size_most_recent();
129 }
130
131 CapturerLinuxPimpl::CapturerLinuxPimpl()
132 : display_(NULL), 93 : display_(NULL),
133 gc_(NULL), 94 gc_(NULL),
134 root_window_(BadValue), 95 root_window_(BadValue),
135 width_(0), 96 width_(0),
136 height_(0), 97 height_(0),
137 damage_handle_(BadValue), 98 damage_handle_(BadValue),
138 damage_event_base_(-1), 99 damage_event_base_(-1),
139 damage_error_base_(-1), 100 damage_error_base_(-1),
140 current_buffer_(0), 101 current_buffer_(0),
141 stride_(0), 102 stride_(0),
142 capture_fullscreen_(true), 103 capture_fullscreen_(true),
143 pixel_format_(media::VideoFrame::RGB32), 104 pixel_format_(media::VideoFrame::RGB32),
144 last_buffer_(NULL) { 105 last_buffer_(NULL) {
145 for (int i = 0; i < kNumBuffers; i++) { 106 for (int i = 0; i < kNumBuffers; i++) {
146 buffers_[i] = NULL; 107 buffers_[i] = NULL;
147 } 108 }
109 CHECK(Init());
148 } 110 }
149 111
150 CapturerLinuxPimpl::~CapturerLinuxPimpl() { 112 CapturerLinux::~CapturerLinux() {
151 DeinitXlib(); 113 DeinitXlib();
152 114
153 for (int i = 0; i < kNumBuffers; i++) { 115 for (int i = 0; i < kNumBuffers; i++) {
154 delete [] buffers_[i]; 116 delete [] buffers_[i];
155 buffers_[i] = NULL; 117 buffers_[i] = NULL;
156 } 118 }
157 } 119 }
158 120
159 bool CapturerLinuxPimpl::Init() { 121 bool CapturerLinux::Init() {
160 // TODO(ajwong): We should specify the display string we are attaching to 122 // TODO(ajwong): We should specify the display string we are attaching to
161 // in the constructor. 123 // in the constructor.
162 display_ = XOpenDisplay(NULL); 124 display_ = XOpenDisplay(NULL);
163 if (!display_) { 125 if (!display_) {
164 LOG(ERROR) << "Unable to open display"; 126 LOG(ERROR) << "Unable to open display";
165 return false; 127 return false;
166 } 128 }
167 129
168 x_server_pixel_buffer_.Init(display_); 130 x_server_pixel_buffer_.Init(display_);
169 131
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 VLOG(1) << "Initialized with Geometry: " << width_ << "x" << height_; 171 VLOG(1) << "Initialized with Geometry: " << width_ << "x" << height_;
210 172
211 // Allocate the screen buffers. 173 // Allocate the screen buffers.
212 for (int i = 0; i < kNumBuffers; i++) { 174 for (int i = 0; i < kNumBuffers; i++) {
213 buffers_[i] = new uint8[width_ * height_ * kBytesPerPixel]; 175 buffers_[i] = new uint8[width_ * height_ * kBytesPerPixel];
214 } 176 }
215 177
216 return true; 178 return true;
217 } 179 }
218 180
219 void CapturerLinuxPimpl::ScreenConfigurationChanged() { 181 void CapturerLinux::ScreenConfigurationChanged() {
220 // TODO(ajwong): Support resolution changes. 182 // TODO(ajwong): Support resolution changes.
221 NOTIMPLEMENTED(); 183 NOTIMPLEMENTED();
222 } 184 }
223 185
224 media::VideoFrame::Format CapturerLinuxPimpl::pixel_format() const { 186 media::VideoFrame::Format CapturerLinux::pixel_format() const {
225 return pixel_format_; 187 return pixel_format_;
226 } 188 }
227 189
228 void CapturerLinuxPimpl::ClearInvalidRects() { 190 void CapturerLinux::ClearInvalidRects() {
229 helper_.ClearInvalidRects(); 191 helper_.ClearInvalidRects();
230 } 192 }
231 193
232 void CapturerLinuxPimpl::InvalidateRects(const InvalidRects& inval_rects) { 194 void CapturerLinux::InvalidateRects(const InvalidRects& inval_rects) {
233 helper_.InvalidateRects(inval_rects); 195 helper_.InvalidateRects(inval_rects);
234 } 196 }
235 197
236 void CapturerLinuxPimpl::InvalidateScreen(const gfx::Size& size) { 198 void CapturerLinux::InvalidateScreen(const gfx::Size& size) {
237 helper_.InvalidateScreen(size); 199 helper_.InvalidateScreen(size);
238 } 200 }
239 201
240 void CapturerLinuxPimpl::InvalidateFullScreen() { 202 void CapturerLinux::InvalidateFullScreen() {
241 helper_.InvalidateFullScreen(); 203 helper_.InvalidateFullScreen();
242 } 204 }
243 205
244 void CapturerLinuxPimpl::CaptureInvalidRects( 206 void CapturerLinux::CaptureInvalidRects(
245 CaptureCompletedCallback* callback) { 207 CaptureCompletedCallback* callback) {
246 CalculateInvalidRects(); 208 CalculateInvalidRects();
247 209
248 InvalidRects rects; 210 InvalidRects rects;
249 helper_.SwapInvalidRects(rects); 211 helper_.SwapInvalidRects(rects);
250 212
251 CaptureRects(rects, callback); 213 CaptureRects(rects, callback);
252 } 214 }
253 215
254 void CapturerLinuxPimpl::CalculateInvalidRects() { 216 void CapturerLinux::CalculateInvalidRects() {
255 if (helper_.IsCaptureFullScreen(gfx::Size(width_, height_))) 217 if (helper_.IsCaptureFullScreen(gfx::Size(width_, height_)))
256 capture_fullscreen_ = true; 218 capture_fullscreen_ = true;
257 219
258 // TODO(ajwong): The capture_fullscreen_ logic here is very ugly. Refactor. 220 // TODO(ajwong): The capture_fullscreen_ logic here is very ugly. Refactor.
259 221
260 // Find the number of events that are outstanding "now." We don't just loop 222 // Find the number of events that are outstanding "now." We don't just loop
261 // on XPending because we want to guarantee this terminates. 223 // on XPending because we want to guarantee this terminates.
262 int events_to_process = XPending(display_); 224 int events_to_process = XPending(display_);
263 XEvent e; 225 XEvent e;
264 InvalidRects invalid_rects; 226 InvalidRects invalid_rects;
(...skipping 22 matching lines...) Expand all
287 249
288 if (capture_fullscreen_) { 250 if (capture_fullscreen_) {
289 // TODO(hclam): Check the new dimension again. 251 // TODO(hclam): Check the new dimension again.
290 helper_.InvalidateScreen(gfx::Size(width_, height_)); 252 helper_.InvalidateScreen(gfx::Size(width_, height_));
291 capture_fullscreen_ = false; 253 capture_fullscreen_ = false;
292 } else { 254 } else {
293 helper_.InvalidateRects(invalid_rects); 255 helper_.InvalidateRects(invalid_rects);
294 } 256 }
295 } 257 }
296 258
297 void CapturerLinuxPimpl::CaptureRects( 259 void CapturerLinux::CaptureRects(
298 const InvalidRects& rects, 260 const InvalidRects& rects,
299 Capturer::CaptureCompletedCallback* callback) { 261 Capturer::CaptureCompletedCallback* callback) {
300 scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); 262 scoped_ptr<CaptureCompletedCallback> callback_deleter(callback);
301 263
302 uint8* buffer = buffers_[current_buffer_]; 264 uint8* buffer = buffers_[current_buffer_];
303 DataPlanes planes; 265 DataPlanes planes;
304 planes.data[0] = buffer; 266 planes.data[0] = buffer;
305 planes.strides[0] = stride_; 267 planes.strides[0] = stride_;
306 268
307 scoped_refptr<CaptureData> capture_data(new CaptureData( 269 scoped_refptr<CaptureData> capture_data(new CaptureData(
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 capture_data->mutable_dirty_rects() = rects; 309 capture_data->mutable_dirty_rects() = rects;
348 last_invalid_rects_ = rects; 310 last_invalid_rects_ = rects;
349 last_buffer_ = buffer; 311 last_buffer_ = buffer;
350 312
351 current_buffer_ = (current_buffer_ + 1) % kNumBuffers; 313 current_buffer_ = (current_buffer_ + 1) % kNumBuffers;
352 helper_.set_size_most_recent(capture_data->size()); 314 helper_.set_size_most_recent(capture_data->size());
353 315
354 callback->Run(capture_data); 316 callback->Run(capture_data);
355 } 317 }
356 318
357 void CapturerLinuxPimpl::DeinitXlib() { 319 void CapturerLinux::DeinitXlib() {
358 if (gc_) { 320 if (gc_) {
359 XFreeGC(display_, gc_); 321 XFreeGC(display_, gc_);
360 gc_ = NULL; 322 gc_ = NULL;
361 } 323 }
362 324
363 if (display_) { 325 if (display_) {
364 XCloseDisplay(display_); 326 XCloseDisplay(display_);
365 display_ = NULL; 327 display_ = NULL;
366 } 328 }
367 } 329 }
368 330
369 void CapturerLinuxPimpl::FastBlit(uint8* image, const gfx::Rect& rect, 331 void CapturerLinux::FastBlit(uint8* image, const gfx::Rect& rect,
370 CaptureData* capture_data) { 332 CaptureData* capture_data) {
371 uint8* src_pos = image; 333 uint8* src_pos = image;
372 int src_stride = x_server_pixel_buffer_.GetStride(); 334 int src_stride = x_server_pixel_buffer_.GetStride();
373 int dst_x = rect.x(), dst_y = rect.y(); 335 int dst_x = rect.x(), dst_y = rect.y();
374 336
375 DataPlanes planes = capture_data->data_planes(); 337 DataPlanes planes = capture_data->data_planes();
376 uint8* dst_buffer = planes.data[0]; 338 uint8* dst_buffer = planes.data[0];
377 339
378 const int dst_stride = planes.strides[0]; 340 const int dst_stride = planes.strides[0];
379 341
380 uint8* dst_pos = dst_buffer + dst_stride * dst_y; 342 uint8* dst_pos = dst_buffer + dst_stride * dst_y;
381 dst_pos += dst_x * kBytesPerPixel; 343 dst_pos += dst_x * kBytesPerPixel;
382 344
383 int height = rect.height(), row_bytes = rect.width() * kBytesPerPixel; 345 int height = rect.height(), row_bytes = rect.width() * kBytesPerPixel;
384 for (int y = 0; y < height; ++y) { 346 for (int y = 0; y < height; ++y) {
385 memcpy(dst_pos, src_pos, row_bytes); 347 memcpy(dst_pos, src_pos, row_bytes);
386 src_pos += src_stride; 348 src_pos += src_stride;
387 dst_pos += dst_stride; 349 dst_pos += dst_stride;
388 } 350 }
389 } 351 }
390 352
391 void CapturerLinuxPimpl::SlowBlit(uint8* image, const gfx::Rect& rect, 353 void CapturerLinux::SlowBlit(uint8* image, const gfx::Rect& rect,
392 CaptureData* capture_data) { 354 CaptureData* capture_data) {
393 DataPlanes planes = capture_data->data_planes(); 355 DataPlanes planes = capture_data->data_planes();
394 uint8* dst_buffer = planes.data[0]; 356 uint8* dst_buffer = planes.data[0];
395 const int dst_stride = planes.strides[0]; 357 const int dst_stride = planes.strides[0];
396 int src_stride = x_server_pixel_buffer_.GetStride(); 358 int src_stride = x_server_pixel_buffer_.GetStride();
397 int dst_x = rect.x(), dst_y = rect.y(); 359 int dst_x = rect.x(), dst_y = rect.y();
398 int width = rect.width(), height = rect.height(); 360 int width = rect.width(), height = rect.height();
399 361
400 unsigned int red_mask = x_server_pixel_buffer_.GetRedMask(); 362 unsigned int red_mask = x_server_pixel_buffer_.GetRedMask();
401 unsigned int blue_mask = x_server_pixel_buffer_.GetBlueMask(); 363 unsigned int blue_mask = x_server_pixel_buffer_.GetBlueMask();
(...skipping 30 matching lines...) Expand all
432 uint32_t b = (((pixel & blue_mask) >> blue_shift) * 255) / max_blue; 394 uint32_t b = (((pixel & blue_mask) >> blue_shift) * 255) / max_blue;
433 uint32_t g = (((pixel & green_mask) >> green_shift) * 255) / max_green; 395 uint32_t g = (((pixel & green_mask) >> green_shift) * 255) / max_green;
434 // Write as 32-bit RGB. 396 // Write as 32-bit RGB.
435 dst_pos_32[x] = r << 16 | g << 8 | b; 397 dst_pos_32[x] = r << 16 | g << 8 | b;
436 } 398 }
437 dst_pos += dst_stride; 399 dst_pos += dst_stride;
438 src_pos += src_stride; 400 src_pos += src_stride;
439 } 401 }
440 } 402 }
441 403
442 const gfx::Size& CapturerLinuxPimpl::size_most_recent() const { 404 const gfx::Size& CapturerLinux::size_most_recent() const {
443 return helper_.size_most_recent(); 405 return helper_.size_most_recent();
444 } 406 }
445 407
408 } // namespace
409
446 // static 410 // static
447 Capturer* Capturer::Create() { 411 Capturer* Capturer::Create() {
448 return new CapturerLinux(); 412 return new CapturerLinux();
449 } 413 }
450 414
451 } // namespace remoting 415 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698