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

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

Issue 11363128: Converted VideoFrameCapturer callbacks into a VideoFrameCapturer::Delegate interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More Mac compilation issues. Created 8 years, 1 month 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
« no previous file with comments | « remoting/host/video_frame_capturer_fake.cc ('k') | remoting/host/video_frame_capturer_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/host/video_frame_capturer.h" 5 #include "remoting/host/video_frame_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>
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 76
77 // A class to perform video frame capturing for Linux. 77 // A class to perform video frame capturing for Linux.
78 class VideoFrameCapturerLinux : public VideoFrameCapturer { 78 class VideoFrameCapturerLinux : public VideoFrameCapturer {
79 public: 79 public:
80 VideoFrameCapturerLinux(); 80 VideoFrameCapturerLinux();
81 virtual ~VideoFrameCapturerLinux(); 81 virtual ~VideoFrameCapturerLinux();
82 82
83 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? 83 bool Init(); // TODO(ajwong): Do we really want this to be synchronous?
84 84
85 // Capturer interface. 85 // Capturer interface.
86 virtual void Start(const CursorShapeChangedCallback& callback) OVERRIDE; 86 virtual void Start(Delegate* delegate) OVERRIDE;
87 virtual void Stop() OVERRIDE; 87 virtual void Stop() OVERRIDE;
88 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; 88 virtual media::VideoFrame::Format pixel_format() const OVERRIDE;
89 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; 89 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE;
90 virtual void CaptureInvalidRegion( 90 virtual void CaptureInvalidRegion() OVERRIDE;
91 const CaptureCompletedCallback& callback) OVERRIDE;
92 virtual const SkISize& size_most_recent() const OVERRIDE; 91 virtual const SkISize& size_most_recent() const OVERRIDE;
93 92
94 private: 93 private:
95 void InitXDamage(); 94 void InitXDamage();
96 95
97 // Read and handle all currently-pending XEvents. 96 // Read and handle all currently-pending XEvents.
98 // In the DAMAGE case, process the XDamage events and store the resulting 97 // In the DAMAGE case, process the XDamage events and store the resulting
99 // damage rectangles in the VideoFrameCapturerHelper. 98 // damage rectangles in the VideoFrameCapturerHelper.
100 // In all cases, call ScreenConfigurationChanged() in response to any 99 // In all cases, call ScreenConfigurationChanged() in response to any
101 // ConfigNotify events. 100 // ConfigNotify events.
102 void ProcessPendingXEvents(); 101 void ProcessPendingXEvents();
103 102
104 // Capture screen pixels, and return the data in a new CaptureData object, 103 // Capture screen pixels, and return the data in a new CaptureData object,
105 // to be freed by the caller. 104 // to be freed by the caller.
106 // In the DAMAGE case, the VideoFrameCapturerHelper already holds the list of 105 // In the DAMAGE case, the VideoFrameCapturerHelper already holds the list of
107 // invalid rectangles from ProcessPendingXEvents(). 106 // invalid rectangles from ProcessPendingXEvents().
108 // In the non-DAMAGE case, this captures the whole screen, then calculates 107 // In the non-DAMAGE case, this captures the whole screen, then calculates
109 // some invalid rectangles that include any differences between this and the 108 // some invalid rectangles that include any differences between this and the
110 // previous capture. 109 // previous capture.
111 CaptureData* CaptureFrame(); 110 CaptureData* CaptureFrame();
112 111
113 // Capture the cursor image and call the CursorShapeChangedCallback if it 112 // Capture the cursor image and notify the delegate if it was captured.
114 // has been set (using SetCursorShapeChangedCallback).
115 void CaptureCursor(); 113 void CaptureCursor();
116 114
117 // Called when the screen configuration is changed. 115 // Called when the screen configuration is changed.
118 void ScreenConfigurationChanged(); 116 void ScreenConfigurationChanged();
119 117
120 // Synchronize the current buffer with |last_buffer_|, by copying pixels from 118 // Synchronize the current buffer with |last_buffer_|, by copying pixels from
121 // the area of |last_invalid_rects|. 119 // the area of |last_invalid_rects|.
122 // Note this only works on the assumption that kNumBuffers == 2, as 120 // Note this only works on the assumption that kNumBuffers == 2, as
123 // |last_invalid_rects| holds the differences from the previous buffer and 121 // |last_invalid_rects| holds the differences from the previous buffer and
124 // the one prior to that (which will then be the current buffer). 122 // the one prior to that (which will then be the current buffer).
125 void SynchronizeFrame(); 123 void SynchronizeFrame();
126 124
127 void DeinitXlib(); 125 void DeinitXlib();
128 126
129 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into 127 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into
130 // |capture_data|. 128 // |capture_data|.
131 void CaptureRect(const SkIRect& rect, CaptureData* capture_data); 129 void CaptureRect(const SkIRect& rect, CaptureData* capture_data);
132 130
133 // We expose two forms of blitting to handle variations in the pixel format. 131 // We expose two forms of blitting to handle variations in the pixel format.
134 // In FastBlit, the operation is effectively a memcpy. 132 // In FastBlit, the operation is effectively a memcpy.
135 void FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); 133 void FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data);
136 void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); 134 void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data);
137 135
136 Delegate* delegate_;
137
138 // X11 graphics context. 138 // X11 graphics context.
139 Display* display_; 139 Display* display_;
140 GC gc_; 140 GC gc_;
141 Window root_window_; 141 Window root_window_;
142 142
143 // XFixes. 143 // XFixes.
144 bool has_xfixes_; 144 bool has_xfixes_;
145 int xfixes_event_base_; 145 int xfixes_event_base_;
146 int xfixes_error_base_; 146 int xfixes_error_base_;
147 147
148 // XDamage information. 148 // XDamage information.
149 bool use_damage_; 149 bool use_damage_;
150 Damage damage_handle_; 150 Damage damage_handle_;
151 int damage_event_base_; 151 int damage_event_base_;
152 int damage_error_base_; 152 int damage_error_base_;
153 XserverRegion damage_region_; 153 XserverRegion damage_region_;
154 154
155 // Access to the X Server's pixel buffer. 155 // Access to the X Server's pixel buffer.
156 XServerPixelBuffer x_server_pixel_buffer_; 156 XServerPixelBuffer x_server_pixel_buffer_;
157 157
158 // A thread-safe list of invalid rectangles, and the size of the most 158 // A thread-safe list of invalid rectangles, and the size of the most
159 // recently captured screen. 159 // recently captured screen.
160 VideoFrameCapturerHelper helper_; 160 VideoFrameCapturerHelper helper_;
161 161
162 // Callback notified whenever the cursor shape is changed.
163 CursorShapeChangedCallback cursor_shape_changed_callback_;
164
165 // Capture state. 162 // Capture state.
166 static const int kNumBuffers = 2; 163 static const int kNumBuffers = 2;
167 VideoFrameBuffer buffers_[kNumBuffers]; 164 VideoFrameBuffer buffers_[kNumBuffers];
168 int current_buffer_; 165 int current_buffer_;
169 166
170 // Format of pixels returned in buffer. 167 // Format of pixels returned in buffer.
171 media::VideoFrame::Format pixel_format_; 168 media::VideoFrame::Format pixel_format_;
172 169
173 // Invalid region from the previous capture. This is used to synchronize the 170 // Invalid region from the previous capture. This is used to synchronize the
174 // current with the last buffer used. 171 // current with the last buffer used.
175 SkRegion last_invalid_region_; 172 SkRegion last_invalid_region_;
176 173
177 // Last capture buffer used. 174 // Last capture buffer used.
178 int last_buffer_; 175 int last_buffer_;
179 176
180 // |Differ| for use when polling for changes. 177 // |Differ| for use when polling for changes.
181 scoped_ptr<Differ> differ_; 178 scoped_ptr<Differ> differ_;
182 179
183 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerLinux); 180 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerLinux);
184 }; 181 };
185 182
186 VideoFrameCapturerLinux::VideoFrameCapturerLinux() 183 VideoFrameCapturerLinux::VideoFrameCapturerLinux()
187 : display_(NULL), 184 : delegate_(NULL),
185 display_(NULL),
188 gc_(NULL), 186 gc_(NULL),
189 root_window_(BadValue), 187 root_window_(BadValue),
190 has_xfixes_(false), 188 has_xfixes_(false),
191 xfixes_event_base_(-1), 189 xfixes_event_base_(-1),
192 xfixes_error_base_(-1), 190 xfixes_error_base_(-1),
193 use_damage_(false), 191 use_damage_(false),
194 damage_handle_(0), 192 damage_handle_(0),
195 damage_event_base_(-1), 193 damage_event_base_(-1),
196 damage_error_base_(-1), 194 damage_error_base_(-1),
197 damage_region_(0), 195 damage_region_(0),
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 if (!damage_region_) { 284 if (!damage_region_) {
287 XDamageDestroy(display_, damage_handle_); 285 XDamageDestroy(display_, damage_handle_);
288 LOG(ERROR) << "Unable to create XFixes region."; 286 LOG(ERROR) << "Unable to create XFixes region.";
289 return; 287 return;
290 } 288 }
291 289
292 use_damage_ = true; 290 use_damage_ = true;
293 LOG(INFO) << "Using XDamage extension."; 291 LOG(INFO) << "Using XDamage extension.";
294 } 292 }
295 293
296 void VideoFrameCapturerLinux::Start( 294 void VideoFrameCapturerLinux::Start(Delegate* delegate) {
297 const CursorShapeChangedCallback& callback) { 295 DCHECK(delegate_ == NULL);
298 cursor_shape_changed_callback_ = callback; 296
297 delegate_ = delegate;
299 } 298 }
300 299
301 void VideoFrameCapturerLinux::Stop() { 300 void VideoFrameCapturerLinux::Stop() {
302 } 301 }
303 302
304 media::VideoFrame::Format VideoFrameCapturerLinux::pixel_format() const { 303 media::VideoFrame::Format VideoFrameCapturerLinux::pixel_format() const {
305 return pixel_format_; 304 return pixel_format_;
306 } 305 }
307 306
308 void VideoFrameCapturerLinux::InvalidateRegion(const SkRegion& invalid_region) { 307 void VideoFrameCapturerLinux::InvalidateRegion(const SkRegion& invalid_region) {
309 helper_.InvalidateRegion(invalid_region); 308 helper_.InvalidateRegion(invalid_region);
310 } 309 }
311 310
312 void VideoFrameCapturerLinux::CaptureInvalidRegion( 311 void VideoFrameCapturerLinux::CaptureInvalidRegion() {
313 const CaptureCompletedCallback& callback) {
314 // Process XEvents for XDamage and cursor shape tracking. 312 // Process XEvents for XDamage and cursor shape tracking.
315 ProcessPendingXEvents(); 313 ProcessPendingXEvents();
316 314
317 // Resize the current buffer if there was a recent change of 315 // Resize the current buffer if there was a recent change of
318 // screen-resolution. 316 // screen-resolution.
319 VideoFrameBuffer &current = buffers_[current_buffer_]; 317 VideoFrameBuffer &current = buffers_[current_buffer_];
320 current.Update(display_, root_window_); 318 current.Update(display_, root_window_);
321 319
322 // Mark the previous frame for update if its dimensions no longer match. 320 // Mark the previous frame for update if its dimensions no longer match.
323 if (buffers_[last_buffer_].size() != current.size()) { 321 if (buffers_[last_buffer_].size() != current.size()) {
324 buffers_[last_buffer_].set_needs_update(); 322 buffers_[last_buffer_].set_needs_update();
325 323
326 // Also refresh the Differ helper used by CaptureFrame(), if needed. 324 // Also refresh the Differ helper used by CaptureFrame(), if needed.
327 if (!use_damage_) { 325 if (!use_damage_) {
328 differ_.reset(new Differ(current.size().width(), current.size().height(), 326 differ_.reset(new Differ(current.size().width(), current.size().height(),
329 kBytesPerPixel, current.bytes_per_row())); 327 kBytesPerPixel, current.bytes_per_row()));
330 } 328 }
331 } 329 }
332 330
333 scoped_refptr<CaptureData> capture_data(CaptureFrame()); 331 scoped_refptr<CaptureData> capture_data(CaptureFrame());
334 332
335 // Swap the current & previous buffers ready for the next capture. 333 // Swap the current & previous buffers ready for the next capture.
336 last_invalid_region_ = capture_data->dirty_region(); 334 last_invalid_region_ = capture_data->dirty_region();
337 last_buffer_ = current_buffer_; 335 last_buffer_ = current_buffer_;
338 current_buffer_ = (current_buffer_ + 1) % kNumBuffers; 336 current_buffer_ = (current_buffer_ + 1) % kNumBuffers;
339 337
340 callback.Run(capture_data); 338 delegate_->OnCaptureCompleted(capture_data);
341 } 339 }
342 340
343 void VideoFrameCapturerLinux::ProcessPendingXEvents() { 341 void VideoFrameCapturerLinux::ProcessPendingXEvents() {
344 // Find the number of events that are outstanding "now." We don't just loop 342 // Find the number of events that are outstanding "now." We don't just loop
345 // on XPending because we want to guarantee this terminates. 343 // on XPending because we want to guarantee this terminates.
346 int events_to_process = XPending(display_); 344 int events_to_process = XPending(display_);
347 XEvent e; 345 XEvent e;
348 346
349 for (int i = 0; i < events_to_process; i++) { 347 for (int i = 0; i < events_to_process; i++) {
350 XNextEvent(display_, &e); 348 XNextEvent(display_, &e);
(...skipping 10 matching lines...) Expand all
361 CaptureCursor(); 359 CaptureCursor();
362 } 360 }
363 } else { 361 } else {
364 LOG(WARNING) << "Got unknown event type: " << e.type; 362 LOG(WARNING) << "Got unknown event type: " << e.type;
365 } 363 }
366 } 364 }
367 } 365 }
368 366
369 void VideoFrameCapturerLinux::CaptureCursor() { 367 void VideoFrameCapturerLinux::CaptureCursor() {
370 DCHECK(has_xfixes_); 368 DCHECK(has_xfixes_);
371 if (cursor_shape_changed_callback_.is_null())
372 return;
373 369
374 XFixesCursorImage* img = XFixesGetCursorImage(display_); 370 XFixesCursorImage* img = XFixesGetCursorImage(display_);
375 if (!img) { 371 if (!img) {
376 return; 372 return;
377 } 373 }
378 374
379 int width = img->width; 375 int width = img->width;
380 int height = img->height; 376 int height = img->height;
381 int total_bytes = width * height * kBytesPerPixel; 377 int total_bytes = width * height * kBytesPerPixel;
382 378
(...skipping 10 matching lines...) Expand all
393 389
394 // Xlib stores 32-bit data in longs, even if longs are 64-bits long. 390 // Xlib stores 32-bit data in longs, even if longs are 64-bits long.
395 unsigned long* src = img->pixels; 391 unsigned long* src = img->pixels;
396 uint32* dst = reinterpret_cast<uint32*>(proto_data); 392 uint32* dst = reinterpret_cast<uint32*>(proto_data);
397 uint32* dst_end = dst + (width * height); 393 uint32* dst_end = dst + (width * height);
398 while (dst < dst_end) { 394 while (dst < dst_end) {
399 *dst++ = static_cast<uint32>(*src++); 395 *dst++ = static_cast<uint32>(*src++);
400 } 396 }
401 XFree(img); 397 XFree(img);
402 398
403 cursor_shape_changed_callback_.Run(cursor_proto.Pass()); 399 delegate_->OnCursorShapeChanged(cursor_proto.Pass());
404 } 400 }
405 401
406 CaptureData* VideoFrameCapturerLinux::CaptureFrame() { 402 CaptureData* VideoFrameCapturerLinux::CaptureFrame() {
407 VideoFrameBuffer& buffer = buffers_[current_buffer_]; 403 VideoFrameBuffer& buffer = buffers_[current_buffer_];
408 DataPlanes planes; 404 DataPlanes planes;
409 planes.data[0] = buffer.ptr(); 405 planes.data[0] = buffer.ptr();
410 planes.strides[0] = buffer.bytes_per_row(); 406 planes.strides[0] = buffer.bytes_per_row();
411 407
412 CaptureData* capture_data = new CaptureData(planes, buffer.size(), 408 CaptureData* capture_data = new CaptureData(planes, buffer.size(),
413 media::VideoFrame::RGB32); 409 media::VideoFrame::RGB32);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 } 624 }
629 return capturer; 625 return capturer;
630 } 626 }
631 627
632 // static 628 // static
633 void VideoFrameCapturer::EnableXDamage(bool enable) { 629 void VideoFrameCapturer::EnableXDamage(bool enable) {
634 g_should_use_x_damage = enable; 630 g_should_use_x_damage = enable;
635 } 631 }
636 632
637 } // namespace remoting 633 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/video_frame_capturer_fake.cc ('k') | remoting/host/video_frame_capturer_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698