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

Side by Side Diff: media/video/capture/screen/screen_capturer_linux.cc

Issue 12047101: Move screen capturers from remoting/capturer to media/video/capturer/screen (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/capturer/video_frame_capturer.h" 5 #include "media/video/capture/screen/screen_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 #include <X11/extensions/Xfixes.h> 10 #include <X11/extensions/Xfixes.h>
11 11
12 #include <set> 12 #include <set>
13 13
14 #include "base/basictypes.h" 14 #include "base/basictypes.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
17 #include "base/stl_util.h" 17 #include "base/stl_util.h"
18 #include "base/time.h" 18 #include "base/time.h"
19 #include "remoting/capturer/capture_data.h" 19 #include "media/video/capture/screen/differ.h"
20 #include "remoting/capturer/differ.h" 20 #include "media/video/capture/screen/linux/x_server_pixel_buffer.h"
21 #include "remoting/capturer/linux/x_server_pixel_buffer.h" 21 #include "media/video/capture/screen/mouse_cursor_shape.h"
22 #include "remoting/capturer/mouse_cursor_shape.h" 22 #include "media/video/capture/screen/screen_capture_data.h"
23 #include "remoting/capturer/video_frame.h" 23 #include "media/video/capture/screen/screen_capture_frame.h"
24 #include "remoting/capturer/video_frame_capturer_helper.h" 24 #include "media/video/capture/screen/screen_capture_frame_queue.h"
25 #include "remoting/capturer/video_frame_queue.h" 25 #include "media/video/capture/screen/screen_capturer_helper.h"
26 26
27 namespace remoting { 27 namespace media {
28 28
29 namespace { 29 namespace {
30 30
31 // Default to false, since many systems have broken XDamage support - see 31 // Default to false, since many systems have broken XDamage support - see
32 // http://crbug.com/73423. 32 // http://crbug.com/73423.
33 static bool g_should_use_x_damage = false; 33 static bool g_should_use_x_damage = false;
34 34
35 static bool ShouldUseXDamage() { 35 static bool ShouldUseXDamage() {
36 return g_should_use_x_damage; 36 return g_should_use_x_damage;
37 } 37 }
38 38
39 // A class representing a full-frame pixel buffer. 39 // A class representing a full-frame pixel buffer.
40 class VideoFrameLinux : public VideoFrame { 40 class ScreenCaptureFrameLinux : public ScreenCaptureFrame {
41 public: 41 public:
42 explicit VideoFrameLinux(const SkISize& window_size); 42 explicit ScreenCaptureFrameLinux(const SkISize& window_size);
43 virtual ~VideoFrameLinux(); 43 virtual ~ScreenCaptureFrameLinux();
44 44
45 private: 45 private:
46 // Allocated pixel buffer. 46 // Allocated pixel buffer.
47 scoped_array<uint8> data_; 47 scoped_array<uint8> data_;
48 48
49 DISALLOW_COPY_AND_ASSIGN(VideoFrameLinux); 49 DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrameLinux);
50 }; 50 };
51 51
52 // A class to perform video frame capturing for Linux. 52 // A class to perform video frame capturing for Linux.
53 class VideoFrameCapturerLinux : public VideoFrameCapturer { 53 class ScreenCapturerLinux : public ScreenCapturer {
54 public: 54 public:
55 VideoFrameCapturerLinux(); 55 ScreenCapturerLinux();
56 virtual ~VideoFrameCapturerLinux(); 56 virtual ~ScreenCapturerLinux();
57 57
58 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? 58 bool Init(); // TODO(ajwong): Do we really want this to be synchronous?
59 59
60 // Capturer interface. 60 // Capturer interface.
61 virtual void Start(Delegate* delegate) OVERRIDE; 61 virtual void Start(Delegate* delegate) OVERRIDE;
62 virtual void Stop() OVERRIDE; 62 virtual void Stop() OVERRIDE;
63 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; 63 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE;
64 virtual void CaptureFrame() OVERRIDE; 64 virtual void CaptureFrame() OVERRIDE;
65 65
66 private: 66 private:
67 void InitXDamage(); 67 void InitXDamage();
68 68
69 // Read and handle all currently-pending XEvents. 69 // Read and handle all currently-pending XEvents.
70 // In the DAMAGE case, process the XDamage events and store the resulting 70 // In the DAMAGE case, process the XDamage events and store the resulting
71 // damage rectangles in the VideoFrameCapturerHelper. 71 // damage rectangles in the ScreenCapturerHelper.
72 // In all cases, call ScreenConfigurationChanged() in response to any 72 // In all cases, call ScreenConfigurationChanged() in response to any
73 // ConfigNotify events. 73 // ConfigNotify events.
74 void ProcessPendingXEvents(); 74 void ProcessPendingXEvents();
75 75
76 // Capture the cursor image and notify the delegate if it was captured. 76 // Capture the cursor image and notify the delegate if it was captured.
77 void CaptureCursor(); 77 void CaptureCursor();
78 78
79 // Capture screen pixels, and return the data in a new CaptureData object, 79 // Capture screen pixels, and return the data in a new ScreenCaptureData
80 // to be freed by the caller. 80 // object, to be freed by the caller. In the DAMAGE case, the
81 // In the DAMAGE case, the VideoFrameCapturerHelper already holds the list of 81 // ScreenCapturerHelper already holds the list of invalid rectangles from
82 // invalid rectangles from ProcessPendingXEvents(). 82 // ProcessPendingXEvents(). In the non-DAMAGE case, this captures the whole
83 // In the non-DAMAGE case, this captures the whole screen, then calculates 83 // screen, then calculates some invalid rectangles that include any
84 // some invalid rectangles that include any differences between this and the 84 // differences between this and the previous capture.
85 // previous capture. 85 scoped_refptr<ScreenCaptureData> CaptureScreen();
86 scoped_refptr<CaptureData> CaptureScreen();
87 86
88 // Called when the screen configuration is changed. |root_window_size| 87 // Called when the screen configuration is changed. |root_window_size|
89 // specifies the most recent size of the root window. 88 // specifies the most recent size of the root window.
90 void ScreenConfigurationChanged(const SkISize& root_window_size); 89 void ScreenConfigurationChanged(const SkISize& root_window_size);
91 90
92 // Synchronize the current buffer with |last_buffer_|, by copying pixels from 91 // Synchronize the current buffer with |last_buffer_|, by copying pixels from
93 // the area of |last_invalid_rects|. 92 // the area of |last_invalid_rects|.
94 // Note this only works on the assumption that kNumBuffers == 2, as 93 // Note this only works on the assumption that kNumBuffers == 2, as
95 // |last_invalid_rects| holds the differences from the previous buffer and 94 // |last_invalid_rects| holds the differences from the previous buffer and
96 // the one prior to that (which will then be the current buffer). 95 // the one prior to that (which will then be the current buffer).
97 void SynchronizeFrame(); 96 void SynchronizeFrame();
98 97
99 void DeinitXlib(); 98 void DeinitXlib();
100 99
101 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into 100 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into
102 // |capture_data|. 101 // |capture_data|.
103 void CaptureRect(const SkIRect& rect, CaptureData* capture_data); 102 void CaptureRect(const SkIRect& rect, ScreenCaptureData* capture_data);
104 103
105 // We expose two forms of blitting to handle variations in the pixel format. 104 // We expose two forms of blitting to handle variations in the pixel format.
106 // In FastBlit, the operation is effectively a memcpy. 105 // In FastBlit, the operation is effectively a memcpy.
107 void FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); 106 void FastBlit(uint8* image,
108 void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); 107 const SkIRect& rect,
108 ScreenCaptureData* capture_data);
109 void SlowBlit(uint8* image,
110 const SkIRect& rect,
111 ScreenCaptureData* capture_data);
109 112
110 Delegate* delegate_; 113 Delegate* delegate_;
111 114
112 // X11 graphics context. 115 // X11 graphics context.
113 Display* display_; 116 Display* display_;
114 GC gc_; 117 GC gc_;
115 Window root_window_; 118 Window root_window_;
116 119
117 // Last known dimensions of the root window. 120 // Last known dimensions of the root window.
118 SkISize root_window_size_; 121 SkISize root_window_size_;
119 122
120 // XFixes. 123 // XFixes.
121 bool has_xfixes_; 124 bool has_xfixes_;
122 int xfixes_event_base_; 125 int xfixes_event_base_;
123 int xfixes_error_base_; 126 int xfixes_error_base_;
124 127
125 // XDamage information. 128 // XDamage information.
126 bool use_damage_; 129 bool use_damage_;
127 Damage damage_handle_; 130 Damage damage_handle_;
128 int damage_event_base_; 131 int damage_event_base_;
129 int damage_error_base_; 132 int damage_error_base_;
130 XserverRegion damage_region_; 133 XserverRegion damage_region_;
131 134
132 // Access to the X Server's pixel buffer. 135 // Access to the X Server's pixel buffer.
133 XServerPixelBuffer x_server_pixel_buffer_; 136 XServerPixelBuffer x_server_pixel_buffer_;
134 137
135 // A thread-safe list of invalid rectangles, and the size of the most 138 // A thread-safe list of invalid rectangles, and the size of the most
136 // recently captured screen. 139 // recently captured screen.
137 VideoFrameCapturerHelper helper_; 140 ScreenCapturerHelper helper_;
138 141
139 // Queue of the frames buffers. 142 // Queue of the frames buffers.
140 VideoFrameQueue queue_; 143 ScreenCaptureFrameQueue queue_;
141 144
142 // Invalid region from the previous capture. This is used to synchronize the 145 // Invalid region from the previous capture. This is used to synchronize the
143 // current with the last buffer used. 146 // current with the last buffer used.
144 SkRegion last_invalid_region_; 147 SkRegion last_invalid_region_;
145 148
146 // |Differ| for use when polling for changes. 149 // |Differ| for use when polling for changes.
147 scoped_ptr<Differ> differ_; 150 scoped_ptr<Differ> differ_;
148 151
149 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerLinux); 152 DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux);
150 }; 153 };
151 154
152 VideoFrameLinux::VideoFrameLinux(const SkISize& window_size) { 155 ScreenCaptureFrameLinux::ScreenCaptureFrameLinux(const SkISize& window_size) {
153 set_bytes_per_row(window_size.width() * CaptureData::kBytesPerPixel); 156 set_bytes_per_row(window_size.width() * ScreenCaptureData::kBytesPerPixel);
154 set_dimensions(window_size); 157 set_dimensions(window_size);
155 158
156 size_t buffer_size = bytes_per_row() * window_size.height(); 159 size_t buffer_size = bytes_per_row() * window_size.height();
157 data_.reset(new uint8[buffer_size]); 160 data_.reset(new uint8[buffer_size]);
158 set_pixels(data_.get()); 161 set_pixels(data_.get());
159 } 162 }
160 163
161 VideoFrameLinux::~VideoFrameLinux() { 164 ScreenCaptureFrameLinux::~ScreenCaptureFrameLinux() {
162 } 165 }
163 166
164 VideoFrameCapturerLinux::VideoFrameCapturerLinux() 167 ScreenCapturerLinux::ScreenCapturerLinux()
165 : delegate_(NULL), 168 : delegate_(NULL),
166 display_(NULL), 169 display_(NULL),
167 gc_(NULL), 170 gc_(NULL),
168 root_window_(BadValue), 171 root_window_(BadValue),
169 root_window_size_(SkISize::Make(0, 0)), 172 root_window_size_(SkISize::Make(0, 0)),
170 has_xfixes_(false), 173 has_xfixes_(false),
171 xfixes_event_base_(-1), 174 xfixes_event_base_(-1),
172 xfixes_error_base_(-1), 175 xfixes_error_base_(-1),
173 use_damage_(false), 176 use_damage_(false),
174 damage_handle_(0), 177 damage_handle_(0),
175 damage_event_base_(-1), 178 damage_event_base_(-1),
176 damage_error_base_(-1), 179 damage_error_base_(-1),
177 damage_region_(0) { 180 damage_region_(0) {
178 helper_.SetLogGridSize(4); 181 helper_.SetLogGridSize(4);
179 } 182 }
180 183
181 VideoFrameCapturerLinux::~VideoFrameCapturerLinux() { 184 ScreenCapturerLinux::~ScreenCapturerLinux() {
182 DeinitXlib(); 185 DeinitXlib();
183 } 186 }
184 187
185 bool VideoFrameCapturerLinux::Init() { 188 bool ScreenCapturerLinux::Init() {
186 // TODO(ajwong): We should specify the display string we are attaching to 189 // TODO(ajwong): We should specify the display string we are attaching to
187 // in the constructor. 190 // in the constructor.
188 display_ = XOpenDisplay(NULL); 191 display_ = XOpenDisplay(NULL);
189 if (!display_) { 192 if (!display_) {
190 LOG(ERROR) << "Unable to open display"; 193 LOG(ERROR) << "Unable to open display";
191 return false; 194 return false;
192 } 195 }
193 196
194 root_window_ = RootWindow(display_, DefaultScreen(display_)); 197 root_window_ = RootWindow(display_, DefaultScreen(display_));
195 if (root_window_ == BadValue) { 198 if (root_window_ == BadValue) {
(...skipping 30 matching lines...) Expand all
226 XFixesDisplayCursorNotifyMask); 229 XFixesDisplayCursorNotifyMask);
227 } 230 }
228 231
229 if (ShouldUseXDamage()) { 232 if (ShouldUseXDamage()) {
230 InitXDamage(); 233 InitXDamage();
231 } 234 }
232 235
233 return true; 236 return true;
234 } 237 }
235 238
236 void VideoFrameCapturerLinux::InitXDamage() { 239 void ScreenCapturerLinux::InitXDamage() {
237 // Our use of XDamage requires XFixes. 240 // Our use of XDamage requires XFixes.
238 if (!has_xfixes_) { 241 if (!has_xfixes_) {
239 return; 242 return;
240 } 243 }
241 244
242 // Check for XDamage extension. 245 // Check for XDamage extension.
243 if (!XDamageQueryExtension(display_, &damage_event_base_, 246 if (!XDamageQueryExtension(display_, &damage_event_base_,
244 &damage_error_base_)) { 247 &damage_error_base_)) {
245 LOG(INFO) << "X server does not support XDamage."; 248 LOG(INFO) << "X server does not support XDamage.";
246 return; 249 return;
(...skipping 17 matching lines...) Expand all
264 if (!damage_region_) { 267 if (!damage_region_) {
265 XDamageDestroy(display_, damage_handle_); 268 XDamageDestroy(display_, damage_handle_);
266 LOG(ERROR) << "Unable to create XFixes region."; 269 LOG(ERROR) << "Unable to create XFixes region.";
267 return; 270 return;
268 } 271 }
269 272
270 use_damage_ = true; 273 use_damage_ = true;
271 LOG(INFO) << "Using XDamage extension."; 274 LOG(INFO) << "Using XDamage extension.";
272 } 275 }
273 276
274 void VideoFrameCapturerLinux::Start(Delegate* delegate) { 277 void ScreenCapturerLinux::Start(Delegate* delegate) {
275 DCHECK(delegate_ == NULL); 278 DCHECK(delegate_ == NULL);
276 279
277 delegate_ = delegate; 280 delegate_ = delegate;
278 } 281 }
279 282
280 void VideoFrameCapturerLinux::Stop() { 283 void ScreenCapturerLinux::Stop() {
281 } 284 }
282 285
283 void VideoFrameCapturerLinux::InvalidateRegion(const SkRegion& invalid_region) { 286 void ScreenCapturerLinux::InvalidateRegion(const SkRegion& invalid_region) {
284 helper_.InvalidateRegion(invalid_region); 287 helper_.InvalidateRegion(invalid_region);
285 } 288 }
286 289
287 void VideoFrameCapturerLinux::CaptureFrame() { 290 void ScreenCapturerLinux::CaptureFrame() {
288 base::Time capture_start_time = base::Time::Now(); 291 base::Time capture_start_time = base::Time::Now();
289 292
290 // Process XEvents for XDamage and cursor shape tracking. 293 // Process XEvents for XDamage and cursor shape tracking.
291 ProcessPendingXEvents(); 294 ProcessPendingXEvents();
292 295
293 // If the current buffer is from an older generation then allocate a new one. 296 // If the current buffer is from an older generation then allocate a new one.
294 // Note that we can't reallocate other buffers at this point, since the caller 297 // Note that we can't reallocate other buffers at this point, since the caller
295 // may still be reading from them. 298 // may still be reading from them.
296 if (queue_.current_frame_needs_update()) { 299 if (queue_.current_frame_needs_update()) {
297 scoped_ptr<VideoFrameLinux> buffer(new VideoFrameLinux( 300 scoped_ptr<ScreenCaptureFrameLinux> buffer(new ScreenCaptureFrameLinux(
298 root_window_size_)); 301 root_window_size_));
299 queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>()); 302 queue_.ReplaceCurrentFrame(buffer.PassAs<ScreenCaptureFrame>());
300 } 303 }
301 304
302 // Refresh the Differ helper used by CaptureFrame(), if needed. 305 // Refresh the Differ helper used by CaptureFrame(), if needed.
303 const VideoFrame* current_buffer = queue_.current_frame(); 306 const ScreenCaptureFrame* current_buffer = queue_.current_frame();
304 if (!use_damage_ && ( 307 if (!use_damage_ && (
305 !differ_.get() || 308 !differ_.get() ||
306 (differ_->width() != current_buffer->dimensions().width()) || 309 (differ_->width() != current_buffer->dimensions().width()) ||
307 (differ_->height() != current_buffer->dimensions().height()) || 310 (differ_->height() != current_buffer->dimensions().height()) ||
308 (differ_->bytes_per_row() != current_buffer->bytes_per_row()))) { 311 (differ_->bytes_per_row() != current_buffer->bytes_per_row()))) {
309 differ_.reset(new Differ(current_buffer->dimensions().width(), 312 differ_.reset(new Differ(current_buffer->dimensions().width(),
310 current_buffer->dimensions().height(), 313 current_buffer->dimensions().height(),
311 CaptureData::kBytesPerPixel, 314 ScreenCaptureData::kBytesPerPixel,
312 current_buffer->bytes_per_row())); 315 current_buffer->bytes_per_row()));
313 } 316 }
314 317
315 scoped_refptr<CaptureData> capture_data(CaptureScreen()); 318 scoped_refptr<ScreenCaptureData> capture_data(CaptureScreen());
316 319
317 // Swap the current & previous buffers ready for the next capture. 320 // Swap the current & previous buffers ready for the next capture.
318 last_invalid_region_ = capture_data->dirty_region(); 321 last_invalid_region_ = capture_data->dirty_region();
319 322
320 queue_.DoneWithCurrentFrame(); 323 queue_.DoneWithCurrentFrame();
321 324
322 capture_data->set_capture_time_ms( 325 capture_data->set_capture_time_ms(
323 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); 326 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp());
324 delegate_->OnCaptureCompleted(capture_data); 327 delegate_->OnCaptureCompleted(capture_data);
325 } 328 }
326 329
327 void VideoFrameCapturerLinux::ProcessPendingXEvents() { 330 void ScreenCapturerLinux::ProcessPendingXEvents() {
328 // Find the number of events that are outstanding "now." We don't just loop 331 // Find the number of events that are outstanding "now." We don't just loop
329 // on XPending because we want to guarantee this terminates. 332 // on XPending because we want to guarantee this terminates.
330 int events_to_process = XPending(display_); 333 int events_to_process = XPending(display_);
331 XEvent e; 334 XEvent e;
332 335
333 for (int i = 0; i < events_to_process; i++) { 336 for (int i = 0; i < events_to_process; i++) {
334 XNextEvent(display_, &e); 337 XNextEvent(display_, &e);
335 if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) { 338 if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) {
336 XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e); 339 XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e);
337 DCHECK(event->level == XDamageReportNonEmpty); 340 DCHECK(event->level == XDamageReportNonEmpty);
338 } else if (e.type == ConfigureNotify) { 341 } else if (e.type == ConfigureNotify) {
339 const XConfigureEvent& event = e.xconfigure; 342 const XConfigureEvent& event = e.xconfigure;
340 ScreenConfigurationChanged(SkISize::Make(event.width, event.height)); 343 ScreenConfigurationChanged(SkISize::Make(event.width, event.height));
341 } else if (has_xfixes_ && 344 } else if (has_xfixes_ &&
342 e.type == xfixes_event_base_ + XFixesCursorNotify) { 345 e.type == xfixes_event_base_ + XFixesCursorNotify) {
343 XFixesCursorNotifyEvent* cne; 346 XFixesCursorNotifyEvent* cne;
344 cne = reinterpret_cast<XFixesCursorNotifyEvent*>(&e); 347 cne = reinterpret_cast<XFixesCursorNotifyEvent*>(&e);
345 if (cne->subtype == XFixesDisplayCursorNotify) { 348 if (cne->subtype == XFixesDisplayCursorNotify) {
346 CaptureCursor(); 349 CaptureCursor();
347 } 350 }
348 } else { 351 } else {
349 LOG(WARNING) << "Got unknown event type: " << e.type; 352 LOG(WARNING) << "Got unknown event type: " << e.type;
350 } 353 }
351 } 354 }
352 } 355 }
353 356
354 void VideoFrameCapturerLinux::CaptureCursor() { 357 void ScreenCapturerLinux::CaptureCursor() {
355 DCHECK(has_xfixes_); 358 DCHECK(has_xfixes_);
356 359
357 XFixesCursorImage* img = XFixesGetCursorImage(display_); 360 XFixesCursorImage* img = XFixesGetCursorImage(display_);
358 if (!img) { 361 if (!img) {
359 return; 362 return;
360 } 363 }
361 364
362 scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape()); 365 scoped_ptr<MouseCursorShape> cursor(new MouseCursorShape());
363 cursor->size.set(img->width, img->height); 366 cursor->size.set(img->width, img->height);
364 cursor->hotspot.set(img->xhot, img->yhot); 367 cursor->hotspot.set(img->xhot, img->yhot);
365 368
366 int total_bytes = cursor->size.width() * cursor->size.height() * 369 int total_bytes = cursor->size.width() * cursor->size.height() *
367 CaptureData::kBytesPerPixel; 370 ScreenCaptureData::kBytesPerPixel;
368 cursor->data.resize(total_bytes); 371 cursor->data.resize(total_bytes);
369 372
370 // Xlib stores 32-bit data in longs, even if longs are 64-bits long. 373 // Xlib stores 32-bit data in longs, even if longs are 64-bits long.
371 unsigned long* src = img->pixels; 374 unsigned long* src = img->pixels;
372 uint32* dst = reinterpret_cast<uint32*>(string_as_array(&cursor->data)); 375 uint32* dst = reinterpret_cast<uint32*>(string_as_array(&cursor->data));
373 uint32* dst_end = dst + (img->width * img->height); 376 uint32* dst_end = dst + (img->width * img->height);
374 while (dst < dst_end) { 377 while (dst < dst_end) {
375 *dst++ = static_cast<uint32>(*src++); 378 *dst++ = static_cast<uint32>(*src++);
376 } 379 }
377 XFree(img); 380 XFree(img);
378 381
379 delegate_->OnCursorShapeChanged(cursor.Pass()); 382 delegate_->OnCursorShapeChanged(cursor.Pass());
380 } 383 }
381 384
382 scoped_refptr<CaptureData> VideoFrameCapturerLinux::CaptureScreen() { 385 scoped_refptr<ScreenCaptureData> ScreenCapturerLinux::CaptureScreen() {
383 VideoFrame* frame = queue_.current_frame(); 386 ScreenCaptureFrame* frame = queue_.current_frame();
384 scoped_refptr<CaptureData> capture_data(new CaptureData( 387 scoped_refptr<ScreenCaptureData> capture_data(new ScreenCaptureData(
385 frame->pixels(), frame->bytes_per_row(), frame->dimensions())); 388 frame->pixels(), frame->bytes_per_row(), frame->dimensions()));
386 389
387 // Pass the screen size to the helper, so it can clip the invalid region if it 390 // Pass the screen size to the helper, so it can clip the invalid region if it
388 // expands that region to a grid. 391 // expands that region to a grid.
389 helper_.set_size_most_recent(capture_data->size()); 392 helper_.set_size_most_recent(capture_data->size());
390 393
391 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame 394 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame
392 // if any. If there isn't a previous frame, that means a screen-resolution 395 // if any. If there isn't a previous frame, that means a screen-resolution
393 // change occurred, and |invalid_rects| will be updated to include the whole 396 // change occurred, and |invalid_rects| will be updated to include the whole
394 // screen. 397 // screen.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 // full-screen notification after a screen-resolution change, so 446 // full-screen notification after a screen-resolution change, so
444 // this is done here. 447 // this is done here.
445 invalid_region.op(screen_rect, SkRegion::kUnion_Op); 448 invalid_region.op(screen_rect, SkRegion::kUnion_Op);
446 } 449 }
447 } 450 }
448 451
449 capture_data->mutable_dirty_region() = invalid_region; 452 capture_data->mutable_dirty_region() = invalid_region;
450 return capture_data; 453 return capture_data;
451 } 454 }
452 455
453 void VideoFrameCapturerLinux::ScreenConfigurationChanged( 456 void ScreenCapturerLinux::ScreenConfigurationChanged(
454 const SkISize& root_window_size) { 457 const SkISize& root_window_size) {
455 root_window_size_ = root_window_size; 458 root_window_size_ = root_window_size;
456 459
457 // Make sure the frame buffers will be reallocated. 460 // Make sure the frame buffers will be reallocated.
458 queue_.SetAllFramesNeedUpdate(); 461 queue_.SetAllFramesNeedUpdate();
459 462
460 helper_.ClearInvalidRegion(); 463 helper_.ClearInvalidRegion();
461 x_server_pixel_buffer_.Init(display_, root_window_size_); 464 x_server_pixel_buffer_.Init(display_, root_window_size_);
462 } 465 }
463 466
464 void VideoFrameCapturerLinux::SynchronizeFrame() { 467 void ScreenCapturerLinux::SynchronizeFrame() {
465 // Synchronize the current buffer with the previous one since we do not 468 // Synchronize the current buffer with the previous one since we do not
466 // capture the entire desktop. Note that encoder may be reading from the 469 // capture the entire desktop. Note that encoder may be reading from the
467 // previous buffer at this time so thread access complaints are false 470 // previous buffer at this time so thread access complaints are false
468 // positives. 471 // positives.
469 472
470 // TODO(hclam): We can reduce the amount of copying here by subtracting 473 // TODO(hclam): We can reduce the amount of copying here by subtracting
471 // |capturer_helper_|s region from |last_invalid_region_|. 474 // |capturer_helper_|s region from |last_invalid_region_|.
472 // http://crbug.com/92354 475 // http://crbug.com/92354
473 DCHECK(queue_.previous_frame()); 476 DCHECK(queue_.previous_frame());
474 477
475 VideoFrame* current = queue_.current_frame(); 478 ScreenCaptureFrame* current = queue_.current_frame();
476 VideoFrame* last = queue_.previous_frame(); 479 ScreenCaptureFrame* last = queue_.previous_frame();
477 DCHECK_NE(current, last); 480 DCHECK_NE(current, last);
478 for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) { 481 for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) {
479 const SkIRect& r = it.rect(); 482 const SkIRect& r = it.rect();
480 int offset = r.fTop * current->bytes_per_row() + 483 int offset = r.fTop * current->bytes_per_row() +
481 r.fLeft * CaptureData::kBytesPerPixel; 484 r.fLeft * ScreenCaptureData::kBytesPerPixel;
482 for (int i = 0; i < r.height(); ++i) { 485 for (int i = 0; i < r.height(); ++i) {
483 memcpy(current->pixels() + offset, last->pixels() + offset, 486 memcpy(current->pixels() + offset, last->pixels() + offset,
484 r.width() * CaptureData::kBytesPerPixel); 487 r.width() * ScreenCaptureData::kBytesPerPixel);
485 offset += current->dimensions().width() * CaptureData::kBytesPerPixel; 488 offset += current->dimensions().width() *
489 ScreenCaptureData::kBytesPerPixel;
486 } 490 }
487 } 491 }
488 } 492 }
489 493
490 void VideoFrameCapturerLinux::DeinitXlib() { 494 void ScreenCapturerLinux::DeinitXlib() {
491 if (gc_) { 495 if (gc_) {
492 XFreeGC(display_, gc_); 496 XFreeGC(display_, gc_);
493 gc_ = NULL; 497 gc_ = NULL;
494 } 498 }
495 499
496 x_server_pixel_buffer_.Release(); 500 x_server_pixel_buffer_.Release();
497 501
498 if (display_) { 502 if (display_) {
499 if (damage_handle_) 503 if (damage_handle_)
500 XDamageDestroy(display_, damage_handle_); 504 XDamageDestroy(display_, damage_handle_);
501 if (damage_region_) 505 if (damage_region_)
502 XFixesDestroyRegion(display_, damage_region_); 506 XFixesDestroyRegion(display_, damage_region_);
503 XCloseDisplay(display_); 507 XCloseDisplay(display_);
504 display_ = NULL; 508 display_ = NULL;
505 damage_handle_ = 0; 509 damage_handle_ = 0;
506 damage_region_ = 0; 510 damage_region_ = 0;
507 } 511 }
508 } 512 }
509 513
510 void VideoFrameCapturerLinux::CaptureRect(const SkIRect& rect, 514 void ScreenCapturerLinux::CaptureRect(const SkIRect& rect,
511 CaptureData* capture_data) { 515 ScreenCaptureData* capture_data) {
512 uint8* image = x_server_pixel_buffer_.CaptureRect(rect); 516 uint8* image = x_server_pixel_buffer_.CaptureRect(rect);
513 int depth = x_server_pixel_buffer_.GetDepth(); 517 int depth = x_server_pixel_buffer_.GetDepth();
514 int bpp = x_server_pixel_buffer_.GetBitsPerPixel(); 518 int bpp = x_server_pixel_buffer_.GetBitsPerPixel();
515 bool is_rgb = x_server_pixel_buffer_.IsRgb(); 519 bool is_rgb = x_server_pixel_buffer_.IsRgb();
516 if ((depth == 24 || depth == 32) && bpp == 32 && is_rgb) { 520 if ((depth == 24 || depth == 32) && bpp == 32 && is_rgb) {
517 DVLOG(3) << "Fast blitting"; 521 DVLOG(3) << "Fast blitting";
518 FastBlit(image, rect, capture_data); 522 FastBlit(image, rect, capture_data);
519 } else { 523 } else {
520 DVLOG(3) << "Slow blitting"; 524 DVLOG(3) << "Slow blitting";
521 SlowBlit(image, rect, capture_data); 525 SlowBlit(image, rect, capture_data);
522 } 526 }
523 } 527 }
524 528
525 void VideoFrameCapturerLinux::FastBlit(uint8* image, const SkIRect& rect, 529 void ScreenCapturerLinux::FastBlit(uint8* image, const SkIRect& rect,
526 CaptureData* capture_data) { 530 ScreenCaptureData* capture_data) {
527 uint8* src_pos = image; 531 uint8* src_pos = image;
528 int src_stride = x_server_pixel_buffer_.GetStride(); 532 int src_stride = x_server_pixel_buffer_.GetStride();
529 int dst_x = rect.fLeft, dst_y = rect.fTop; 533 int dst_x = rect.fLeft, dst_y = rect.fTop;
530 534
531 uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y; 535 uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y;
532 dst_pos += dst_x * CaptureData::kBytesPerPixel; 536 dst_pos += dst_x * ScreenCaptureData::kBytesPerPixel;
533 537
534 int height = rect.height(); 538 int height = rect.height();
535 int row_bytes = rect.width() * CaptureData::kBytesPerPixel; 539 int row_bytes = rect.width() * ScreenCaptureData::kBytesPerPixel;
536 for (int y = 0; y < height; ++y) { 540 for (int y = 0; y < height; ++y) {
537 memcpy(dst_pos, src_pos, row_bytes); 541 memcpy(dst_pos, src_pos, row_bytes);
538 src_pos += src_stride; 542 src_pos += src_stride;
539 dst_pos += capture_data->stride(); 543 dst_pos += capture_data->stride();
540 } 544 }
541 } 545 }
542 546
543 void VideoFrameCapturerLinux::SlowBlit(uint8* image, const SkIRect& rect, 547 void ScreenCapturerLinux::SlowBlit(uint8* image, const SkIRect& rect,
544 CaptureData* capture_data) { 548 ScreenCaptureData* capture_data) {
545 int src_stride = x_server_pixel_buffer_.GetStride(); 549 int src_stride = x_server_pixel_buffer_.GetStride();
546 int dst_x = rect.fLeft, dst_y = rect.fTop; 550 int dst_x = rect.fLeft, dst_y = rect.fTop;
547 int width = rect.width(), height = rect.height(); 551 int width = rect.width(), height = rect.height();
548 552
549 unsigned int red_mask = x_server_pixel_buffer_.GetRedMask(); 553 unsigned int red_mask = x_server_pixel_buffer_.GetRedMask();
550 unsigned int blue_mask = x_server_pixel_buffer_.GetBlueMask(); 554 unsigned int blue_mask = x_server_pixel_buffer_.GetBlueMask();
551 unsigned int green_mask = x_server_pixel_buffer_.GetGreenMask(); 555 unsigned int green_mask = x_server_pixel_buffer_.GetGreenMask();
552 unsigned int red_shift = x_server_pixel_buffer_.GetRedShift(); 556 unsigned int red_shift = x_server_pixel_buffer_.GetRedShift();
553 unsigned int blue_shift = x_server_pixel_buffer_.GetBlueShift(); 557 unsigned int blue_shift = x_server_pixel_buffer_.GetBlueShift();
554 unsigned int green_shift = x_server_pixel_buffer_.GetGreenShift(); 558 unsigned int green_shift = x_server_pixel_buffer_.GetGreenShift();
555 559
556 unsigned int max_red = red_mask >> red_shift; 560 unsigned int max_red = red_mask >> red_shift;
557 unsigned int max_blue = blue_mask >> blue_shift; 561 unsigned int max_blue = blue_mask >> blue_shift;
558 unsigned int max_green = green_mask >> green_shift; 562 unsigned int max_green = green_mask >> green_shift;
559 563
560 unsigned int bits_per_pixel = x_server_pixel_buffer_.GetBitsPerPixel(); 564 unsigned int bits_per_pixel = x_server_pixel_buffer_.GetBitsPerPixel();
561 565
562 uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y; 566 uint8* dst_pos = capture_data->data() + capture_data->stride() * dst_y;
563 uint8* src_pos = image; 567 uint8* src_pos = image;
564 dst_pos += dst_x * CaptureData::kBytesPerPixel; 568 dst_pos += dst_x * ScreenCaptureData::kBytesPerPixel;
565 // TODO(hclam): Optimize, perhaps using MMX code or by converting to 569 // TODO(hclam): Optimize, perhaps using MMX code or by converting to
566 // YUV directly 570 // YUV directly
567 for (int y = 0; y < height; y++) { 571 for (int y = 0; y < height; y++) {
568 uint32_t* dst_pos_32 = reinterpret_cast<uint32_t*>(dst_pos); 572 uint32_t* dst_pos_32 = reinterpret_cast<uint32_t*>(dst_pos);
569 uint32_t* src_pos_32 = reinterpret_cast<uint32_t*>(src_pos); 573 uint32_t* src_pos_32 = reinterpret_cast<uint32_t*>(src_pos);
570 uint16_t* src_pos_16 = reinterpret_cast<uint16_t*>(src_pos); 574 uint16_t* src_pos_16 = reinterpret_cast<uint16_t*>(src_pos);
571 for (int x = 0; x < width; x++) { 575 for (int x = 0; x < width; x++) {
572 // Dereference through an appropriately-aligned pointer. 576 // Dereference through an appropriately-aligned pointer.
573 uint32_t pixel; 577 uint32_t pixel;
574 if (bits_per_pixel == 32) 578 if (bits_per_pixel == 32)
575 pixel = src_pos_32[x]; 579 pixel = src_pos_32[x];
576 else if (bits_per_pixel == 16) 580 else if (bits_per_pixel == 16)
577 pixel = src_pos_16[x]; 581 pixel = src_pos_16[x];
578 else 582 else
579 pixel = src_pos[x]; 583 pixel = src_pos[x];
580 uint32_t r = (((pixel & red_mask) >> red_shift) * 255) / max_red; 584 uint32_t r = (((pixel & red_mask) >> red_shift) * 255) / max_red;
581 uint32_t b = (((pixel & blue_mask) >> blue_shift) * 255) / max_blue; 585 uint32_t b = (((pixel & blue_mask) >> blue_shift) * 255) / max_blue;
582 uint32_t g = (((pixel & green_mask) >> green_shift) * 255) / max_green; 586 uint32_t g = (((pixel & green_mask) >> green_shift) * 255) / max_green;
583 // Write as 32-bit RGB. 587 // Write as 32-bit RGB.
584 dst_pos_32[x] = r << 16 | g << 8 | b; 588 dst_pos_32[x] = r << 16 | g << 8 | b;
585 } 589 }
586 dst_pos += capture_data->stride(); 590 dst_pos += capture_data->stride();
587 src_pos += src_stride; 591 src_pos += src_stride;
588 } 592 }
589 } 593 }
590 594
591 } // namespace 595 } // namespace
592 596
593 // static 597 // static
594 scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::Create() { 598 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() {
595 scoped_ptr<VideoFrameCapturerLinux> capturer(new VideoFrameCapturerLinux()); 599 scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
596 if (!capturer->Init()) 600 if (!capturer->Init())
597 capturer.reset(); 601 capturer.reset();
598 return capturer.PassAs<VideoFrameCapturer>(); 602 return capturer.PassAs<ScreenCapturer>();
599 } 603 }
600 604
601 // static 605 // static
602 scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::CreateWithFactory( 606 scoped_ptr<ScreenCapturer> ScreenCapturer::CreateWithFactory(
603 SharedBufferFactory* shared_buffer_factory) { 607 SharedBufferFactory* shared_buffer_factory) {
604 NOTIMPLEMENTED(); 608 NOTIMPLEMENTED();
605 return scoped_ptr<VideoFrameCapturer>(); 609 return scoped_ptr<ScreenCapturer>();
606 } 610 }
607 611
608 // static 612 // static
609 void VideoFrameCapturer::EnableXDamage(bool enable) { 613 void ScreenCapturer::EnableXDamage(bool enable) {
610 g_should_use_x_damage = enable; 614 g_should_use_x_damage = enable;
611 } 615 }
612 616
613 } // namespace remoting 617 } // namespace media
OLDNEW
« no previous file with comments | « media/video/capture/screen/screen_capturer_helper_unittest.cc ('k') | media/video/capture/screen/screen_capturer_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698