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

Side by Side Diff: webrtc/modules/desktop_capture/screen_capturer_x11.cc

Issue 1988783003: Use std::unique_ptr<> to pass frame ownership in DesktopCapturer impls. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 6 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
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 // SharedXDisplay::XEventHandler interface. 59 // SharedXDisplay::XEventHandler interface.
60 bool HandleXEvent(const XEvent& event) override; 60 bool HandleXEvent(const XEvent& event) override;
61 61
62 void InitXDamage(); 62 void InitXDamage();
63 63
64 // Capture screen pixels to the current buffer in the queue. In the DAMAGE 64 // Capture screen pixels to the current buffer in the queue. In the DAMAGE
65 // case, the ScreenCapturerHelper already holds the list of invalid rectangles 65 // case, the ScreenCapturerHelper already holds the list of invalid rectangles
66 // from HandleXEvent(). In the non-DAMAGE case, this captures the 66 // from HandleXEvent(). In the non-DAMAGE case, this captures the
67 // whole screen, then calculates some invalid rectangles that include any 67 // whole screen, then calculates some invalid rectangles that include any
68 // differences between this and the previous capture. 68 // differences between this and the previous capture.
69 DesktopFrame* CaptureScreen(); 69 std::unique_ptr<DesktopFrame> CaptureScreen();
70 70
71 // Called when the screen configuration is changed. 71 // Called when the screen configuration is changed.
72 void ScreenConfigurationChanged(); 72 void ScreenConfigurationChanged();
73 73
74 // Synchronize the current buffer with |last_buffer_|, by copying pixels from 74 // Synchronize the current buffer with |last_buffer_|, by copying pixels from
75 // the area of |last_invalid_rects|. 75 // the area of |last_invalid_rects|.
76 // Note this only works on the assumption that kNumBuffers == 2, as 76 // Note this only works on the assumption that kNumBuffers == 2, as
77 // |last_invalid_rects| holds the differences from the previous buffer and 77 // |last_invalid_rects| holds the differences from the previous buffer and
78 // the one prior to that (which will then be the current buffer). 78 // the one prior to that (which will then be the current buffer).
79 void SynchronizeFrame(); 79 void SynchronizeFrame();
80 80
81 void DeinitXlib(); 81 void DeinitXlib();
82 82
83 DesktopCaptureOptions options_; 83 DesktopCaptureOptions options_;
84 84
85 Callback* callback_; 85 Callback* callback_ = nullptr;
86 86
87 // X11 graphics context. 87 // X11 graphics context.
88 GC gc_; 88 GC gc_ = nullptr;
89 Window root_window_; 89 Window root_window_ = BadValue;
90 90
91 // XFixes. 91 // XFixes.
92 bool has_xfixes_; 92 bool has_xfixes_ = false;
93 int xfixes_event_base_; 93 int xfixes_event_base_ = -1;
94 int xfixes_error_base_; 94 int xfixes_error_base_ = -1;
95 95
96 // XDamage information. 96 // XDamage information.
97 bool use_damage_; 97 bool use_damage_ = false;
98 Damage damage_handle_; 98 Damage damage_handle_ = 0;
99 int damage_event_base_; 99 int damage_event_base_ = -1;
100 int damage_error_base_; 100 int damage_error_base_ = -1;
101 XserverRegion damage_region_; 101 XserverRegion damage_region_ = 0;
102 102
103 // Access to the X Server's pixel buffer. 103 // Access to the X Server's pixel buffer.
104 XServerPixelBuffer x_server_pixel_buffer_; 104 XServerPixelBuffer x_server_pixel_buffer_;
105 105
106 // A thread-safe list of invalid rectangles, and the size of the most 106 // A thread-safe list of invalid rectangles, and the size of the most
107 // recently captured screen. 107 // recently captured screen.
108 ScreenCapturerHelper helper_; 108 ScreenCapturerHelper helper_;
109 109
110 // Queue of the frames buffers. 110 // Queue of the frames buffers.
111 ScreenCaptureFrameQueue<SharedDesktopFrame> queue_; 111 ScreenCaptureFrameQueue<SharedDesktopFrame> queue_;
112 112
113 // Invalid region from the previous capture. This is used to synchronize the 113 // Invalid region from the previous capture. This is used to synchronize the
114 // current with the last buffer used. 114 // current with the last buffer used.
115 DesktopRegion last_invalid_region_; 115 DesktopRegion last_invalid_region_;
116 116
117 // |Differ| for use when polling for changes. 117 // |Differ| for use when polling for changes.
118 std::unique_ptr<Differ> differ_; 118 std::unique_ptr<Differ> differ_;
119 119
120 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); 120 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux);
121 }; 121 };
122 122
123 ScreenCapturerLinux::ScreenCapturerLinux() 123 ScreenCapturerLinux::ScreenCapturerLinux() {
124 : callback_(NULL),
125 gc_(NULL),
126 root_window_(BadValue),
127 has_xfixes_(false),
128 xfixes_event_base_(-1),
129 xfixes_error_base_(-1),
130 use_damage_(false),
131 damage_handle_(0),
132 damage_event_base_(-1),
133 damage_error_base_(-1),
134 damage_region_(0) {
135 helper_.SetLogGridSize(4); 124 helper_.SetLogGridSize(4);
136 } 125 }
137 126
138 ScreenCapturerLinux::~ScreenCapturerLinux() { 127 ScreenCapturerLinux::~ScreenCapturerLinux() {
139 options_.x_display()->RemoveEventHandler(ConfigureNotify, this); 128 options_.x_display()->RemoveEventHandler(ConfigureNotify, this);
140 if (use_damage_) { 129 if (use_damage_) {
141 options_.x_display()->RemoveEventHandler( 130 options_.x_display()->RemoveEventHandler(
142 damage_event_base_ + XDamageNotify, this); 131 damage_event_base_ + XDamageNotify, this);
143 } 132 }
144 DeinitXlib(); 133 DeinitXlib();
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 RTC_DCHECK(!queue_.current_frame() || !queue_.current_frame()->IsShared()); 231 RTC_DCHECK(!queue_.current_frame() || !queue_.current_frame()->IsShared());
243 232
244 // Process XEvents for XDamage and cursor shape tracking. 233 // Process XEvents for XDamage and cursor shape tracking.
245 options_.x_display()->ProcessPendingXEvents(); 234 options_.x_display()->ProcessPendingXEvents();
246 235
247 // ProcessPendingXEvents() may call ScreenConfigurationChanged() which 236 // ProcessPendingXEvents() may call ScreenConfigurationChanged() which
248 // reinitializes |x_server_pixel_buffer_|. Check if the pixel buffer is still 237 // reinitializes |x_server_pixel_buffer_|. Check if the pixel buffer is still
249 // in a good shape. 238 // in a good shape.
250 if (!x_server_pixel_buffer_.is_initialized()) { 239 if (!x_server_pixel_buffer_.is_initialized()) {
251 // We failed to initialize pixel buffer. 240 // We failed to initialize pixel buffer.
252 callback_->OnCaptureCompleted(NULL); 241 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
253 return; 242 return;
254 } 243 }
255 244
256 // If the current frame is from an older generation then allocate a new one. 245 // If the current frame is from an older generation then allocate a new one.
257 // Note that we can't reallocate other buffers at this point, since the caller 246 // Note that we can't reallocate other buffers at this point, since the caller
258 // may still be reading from them. 247 // may still be reading from them.
259 if (!queue_.current_frame()) { 248 if (!queue_.current_frame()) {
260 std::unique_ptr<DesktopFrame> frame( 249 queue_.ReplaceCurrentFrame(
261 new BasicDesktopFrame(x_server_pixel_buffer_.window_size())); 250 SharedDesktopFrame::Wrap(std::unique_ptr<DesktopFrame>(
262 queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(frame.release())); 251 new BasicDesktopFrame(x_server_pixel_buffer_.window_size()))));
263 } 252 }
264 253
265 // Refresh the Differ helper used by CaptureFrame(), if needed. 254 // Refresh the Differ helper used by CaptureFrame(), if needed.
266 DesktopFrame* frame = queue_.current_frame(); 255 DesktopFrame* frame = queue_.current_frame();
267 if (!use_damage_ && ( 256 if (!use_damage_ &&
268 !differ_.get() || 257 (!differ_ || (differ_->width() != frame->size().width()) ||
269 (differ_->width() != frame->size().width()) || 258 (differ_->height() != frame->size().height()) ||
270 (differ_->height() != frame->size().height()) || 259 (differ_->bytes_per_row() != frame->stride()))) {
271 (differ_->bytes_per_row() != frame->stride()))) {
272 differ_.reset(new Differ(frame->size().width(), frame->size().height(), 260 differ_.reset(new Differ(frame->size().width(), frame->size().height(),
273 DesktopFrame::kBytesPerPixel, 261 DesktopFrame::kBytesPerPixel, frame->stride()));
274 frame->stride()));
275 } 262 }
276 263
277 DesktopFrame* result = CaptureScreen(); 264 std::unique_ptr<DesktopFrame> result = CaptureScreen();
278 last_invalid_region_ = result->updated_region(); 265 last_invalid_region_ = result->updated_region();
279 result->set_capture_time_ms( 266 result->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) /
280 (rtc::TimeNanos() - capture_start_time_nanos) / 267 rtc::kNumNanosecsPerMillisec);
281 rtc::kNumNanosecsPerMillisec); 268 callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
282 callback_->OnCaptureCompleted(result);
283 } 269 }
284 270
285 bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { 271 bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) {
286 RTC_DCHECK(screens->size() == 0); 272 RTC_DCHECK(screens->size() == 0);
287 // TODO(jiayl): implement screen enumeration. 273 // TODO(jiayl): implement screen enumeration.
288 Screen default_screen; 274 Screen default_screen;
289 default_screen.id = 0; 275 default_screen.id = 0;
290 screens->push_back(default_screen); 276 screens->push_back(default_screen);
291 return true; 277 return true;
292 } 278 }
(...skipping 11 matching lines...) Expand all
304 return false; 290 return false;
305 RTC_DCHECK(damage_event->level == XDamageReportNonEmpty); 291 RTC_DCHECK(damage_event->level == XDamageReportNonEmpty);
306 return true; 292 return true;
307 } else if (event.type == ConfigureNotify) { 293 } else if (event.type == ConfigureNotify) {
308 ScreenConfigurationChanged(); 294 ScreenConfigurationChanged();
309 return true; 295 return true;
310 } 296 }
311 return false; 297 return false;
312 } 298 }
313 299
314 DesktopFrame* ScreenCapturerLinux::CaptureScreen() { 300 std::unique_ptr<DesktopFrame> ScreenCapturerLinux::CaptureScreen() {
315 DesktopFrame* frame = queue_.current_frame()->Share(); 301 std::unique_ptr<SharedDesktopFrame> frame = queue_.current_frame()->Share();
316 assert(x_server_pixel_buffer_.window_size().equals(frame->size())); 302 assert(x_server_pixel_buffer_.window_size().equals(frame->size()));
317 303
318 // Pass the screen size to the helper, so it can clip the invalid region if it 304 // Pass the screen size to the helper, so it can clip the invalid region if it
319 // expands that region to a grid. 305 // expands that region to a grid.
320 helper_.set_size_most_recent(frame->size()); 306 helper_.set_size_most_recent(frame->size());
321 307
322 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame 308 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame
323 // if any. If there isn't a previous frame, that means a screen-resolution 309 // if any. If there isn't a previous frame, that means a screen-resolution
324 // change occurred, and |invalid_rects| will be updated to include the whole 310 // change occurred, and |invalid_rects| will be updated to include the whole
325 // screen. 311 // screen.
(...skipping 21 matching lines...) Expand all
347 helper_.TakeInvalidRegion(updated_region); 333 helper_.TakeInvalidRegion(updated_region);
348 334
349 // Clip the damaged portions to the current screen size, just in case some 335 // Clip the damaged portions to the current screen size, just in case some
350 // spurious XDamage notifications were received for a previous (larger) 336 // spurious XDamage notifications were received for a previous (larger)
351 // screen size. 337 // screen size.
352 updated_region->IntersectWith( 338 updated_region->IntersectWith(
353 DesktopRect::MakeSize(x_server_pixel_buffer_.window_size())); 339 DesktopRect::MakeSize(x_server_pixel_buffer_.window_size()));
354 340
355 for (DesktopRegion::Iterator it(*updated_region); 341 for (DesktopRegion::Iterator it(*updated_region);
356 !it.IsAtEnd(); it.Advance()) { 342 !it.IsAtEnd(); it.Advance()) {
357 x_server_pixel_buffer_.CaptureRect(it.rect(), frame); 343 x_server_pixel_buffer_.CaptureRect(it.rect(), frame.get());
358 } 344 }
359 } else { 345 } else {
360 // Doing full-screen polling, or this is the first capture after a 346 // Doing full-screen polling, or this is the first capture after a
361 // screen-resolution change. In either case, need a full-screen capture. 347 // screen-resolution change. In either case, need a full-screen capture.
362 DesktopRect screen_rect = DesktopRect::MakeSize(frame->size()); 348 DesktopRect screen_rect = DesktopRect::MakeSize(frame->size());
363 x_server_pixel_buffer_.CaptureRect(screen_rect, frame); 349 x_server_pixel_buffer_.CaptureRect(screen_rect, frame.get());
364 350
365 if (queue_.previous_frame()) { 351 if (queue_.previous_frame()) {
366 // Full-screen polling, so calculate the invalid rects here, based on the 352 // Full-screen polling, so calculate the invalid rects here, based on the
367 // changed pixels between current and previous buffers. 353 // changed pixels between current and previous buffers.
368 RTC_DCHECK(differ_.get() != NULL); 354 RTC_DCHECK(differ_);
369 RTC_DCHECK(queue_.previous_frame()->data()); 355 RTC_DCHECK(queue_.previous_frame()->data());
370 differ_->CalcDirtyRegion(queue_.previous_frame()->data(), 356 differ_->CalcDirtyRegion(queue_.previous_frame()->data(),
371 frame->data(), updated_region); 357 frame->data(), updated_region);
372 } else { 358 } else {
373 // No previous buffer, so always invalidate the whole screen, whether 359 // No previous buffer, so always invalidate the whole screen, whether
374 // or not DAMAGE is being used. DAMAGE doesn't necessarily send a 360 // or not DAMAGE is being used. DAMAGE doesn't necessarily send a
375 // full-screen notification after a screen-resolution change, so 361 // full-screen notification after a screen-resolution change, so
376 // this is done here. 362 // this is done here.
377 updated_region->SetRect(screen_rect); 363 updated_region->SetRect(screen_rect);
378 } 364 }
379 } 365 }
380 366
381 return frame; 367 return std::move(frame);
382 } 368 }
383 369
384 void ScreenCapturerLinux::ScreenConfigurationChanged() { 370 void ScreenCapturerLinux::ScreenConfigurationChanged() {
385 // Make sure the frame buffers will be reallocated. 371 // Make sure the frame buffers will be reallocated.
386 queue_.Reset(); 372 queue_.Reset();
387 373
388 helper_.ClearInvalidRegion(); 374 helper_.ClearInvalidRegion();
389 if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { 375 if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) {
390 LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen " 376 LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen "
391 "configuration change."; 377 "configuration change.";
(...skipping 16 matching lines...) Expand all
408 RTC_DCHECK(current != last); 394 RTC_DCHECK(current != last);
409 for (DesktopRegion::Iterator it(last_invalid_region_); 395 for (DesktopRegion::Iterator it(last_invalid_region_);
410 !it.IsAtEnd(); it.Advance()) { 396 !it.IsAtEnd(); it.Advance()) {
411 current->CopyPixelsFrom(*last, it.rect().top_left(), it.rect()); 397 current->CopyPixelsFrom(*last, it.rect().top_left(), it.rect());
412 } 398 }
413 } 399 }
414 400
415 void ScreenCapturerLinux::DeinitXlib() { 401 void ScreenCapturerLinux::DeinitXlib() {
416 if (gc_) { 402 if (gc_) {
417 XFreeGC(display(), gc_); 403 XFreeGC(display(), gc_);
418 gc_ = NULL; 404 gc_ = nullptr;
419 } 405 }
420 406
421 x_server_pixel_buffer_.Release(); 407 x_server_pixel_buffer_.Release();
422 408
423 if (display()) { 409 if (display()) {
424 if (damage_handle_) { 410 if (damage_handle_) {
425 XDamageDestroy(display(), damage_handle_); 411 XDamageDestroy(display(), damage_handle_);
426 damage_handle_ = 0; 412 damage_handle_ = 0;
427 } 413 }
428 414
429 if (damage_region_) { 415 if (damage_region_) {
430 XFixesDestroyRegion(display(), damage_region_); 416 XFixesDestroyRegion(display(), damage_region_);
431 damage_region_ = 0; 417 damage_region_ = 0;
432 } 418 }
433 } 419 }
434 } 420 }
435 421
436 } // namespace 422 } // namespace
437 423
438 // static 424 // static
439 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { 425 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
440 if (!options.x_display()) 426 if (!options.x_display())
441 return NULL; 427 return nullptr;
442 428
443 std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); 429 std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
444 if (!capturer->Init(options)) 430 if (!capturer->Init(options))
445 capturer.reset(); 431 capturer.reset();
446 return capturer.release(); 432 return capturer.release();
447 } 433 }
448 434
449 } // namespace webrtc 435 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/desktop_capture/screen_capturer_unittest.cc ('k') | webrtc/modules/desktop_capture/shared_desktop_frame.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698