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

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

Issue 1882083002: Revert of Fix screen capturers to initialize on the same thread on which Start() is called. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 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
« no previous file with comments | « webrtc/modules/desktop_capture/screen_capturer_mac.mm ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
11 #include "webrtc/modules/desktop_capture/screen_capturer.h" 11 #include "webrtc/modules/desktop_capture/screen_capturer.h"
12 12
13 #include <string.h> 13 #include <string.h>
14 14
15 #include <memory> 15 #include <memory>
16 #include <set> 16 #include <set>
17 17
18 #include <X11/extensions/Xdamage.h> 18 #include <X11/extensions/Xdamage.h>
19 #include <X11/extensions/Xfixes.h> 19 #include <X11/extensions/Xfixes.h>
20 #include <X11/Xlib.h> 20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h> 21 #include <X11/Xutil.h>
22 22
23 #include "webrtc/base/checks.h" 23 #include "webrtc/base/checks.h"
24 #include "webrtc/base/thread_checker.h"
25 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" 24 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
26 #include "webrtc/modules/desktop_capture/desktop_frame.h" 25 #include "webrtc/modules/desktop_capture/desktop_frame.h"
27 #include "webrtc/modules/desktop_capture/differ.h" 26 #include "webrtc/modules/desktop_capture/differ.h"
28 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" 27 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
29 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" 28 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h"
30 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" 29 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
31 #include "webrtc/system_wrappers/include/logging.h" 30 #include "webrtc/system_wrappers/include/logging.h"
32 #include "webrtc/system_wrappers/include/tick_util.h" 31 #include "webrtc/system_wrappers/include/tick_util.h"
33 32
34 namespace webrtc { 33 namespace webrtc {
35 namespace { 34 namespace {
36 35
37 // A class to perform video frame capturing for Linux. 36 // A class to perform video frame capturing for Linux.
38 class ScreenCapturerLinux : public ScreenCapturer, 37 class ScreenCapturerLinux : public ScreenCapturer,
39 public SharedXDisplay::XEventHandler { 38 public SharedXDisplay::XEventHandler {
40 public: 39 public:
41 explicit ScreenCapturerLinux(const DesktopCaptureOptions& options); 40 ScreenCapturerLinux();
42 virtual ~ScreenCapturerLinux(); 41 virtual ~ScreenCapturerLinux();
43 42
43 // TODO(ajwong): Do we really want this to be synchronous?
44 bool Init(const DesktopCaptureOptions& options);
45
44 // DesktopCapturer interface. 46 // DesktopCapturer interface.
45 void Start(Callback* delegate) override; 47 void Start(Callback* delegate) override;
46 void Capture(const DesktopRegion& region) override; 48 void Capture(const DesktopRegion& region) override;
47 49
48 // ScreenCapturer interface. 50 // ScreenCapturer interface.
49 bool GetScreenList(ScreenList* screens) override; 51 bool GetScreenList(ScreenList* screens) override;
50 bool SelectScreen(ScreenId id) override; 52 bool SelectScreen(ScreenId id) override;
51 53
52 private: 54 private:
53 Display* display() { return options_.x_display()->display(); } 55 Display* display() { return options_.x_display()->display(); }
54 56
55 bool Initialize();
56
57 void InitXDamage();
58
59 // SharedXDisplay::XEventHandler interface. 57 // SharedXDisplay::XEventHandler interface.
60 bool HandleXEvent(const XEvent& event) override; 58 bool HandleXEvent(const XEvent& event) override;
61 59
60 void InitXDamage();
61
62 // Capture screen pixels to the current buffer in the queue. In the DAMAGE 62 // Capture screen pixels to the current buffer in the queue. In the DAMAGE
63 // case, the ScreenCapturerHelper already holds the list of invalid rectangles 63 // case, the ScreenCapturerHelper already holds the list of invalid rectangles
64 // from HandleXEvent(). In the non-DAMAGE case, this captures the 64 // from HandleXEvent(). In the non-DAMAGE case, this captures the
65 // whole screen, then calculates some invalid rectangles that include any 65 // whole screen, then calculates some invalid rectangles that include any
66 // differences between this and the previous capture. 66 // differences between this and the previous capture.
67 DesktopFrame* CaptureScreen(); 67 DesktopFrame* CaptureScreen();
68 68
69 // Called when the screen configuration is changed. 69 // Called when the screen configuration is changed.
70 void ScreenConfigurationChanged(); 70 void ScreenConfigurationChanged();
71 71
72 // Synchronize the current buffer with |last_buffer_|, by copying pixels from 72 // Synchronize the current buffer with |last_buffer_|, by copying pixels from
73 // the area of |last_invalid_rects|. 73 // the area of |last_invalid_rects|.
74 // Note this only works on the assumption that kNumBuffers == 2, as 74 // Note this only works on the assumption that kNumBuffers == 2, as
75 // |last_invalid_rects| holds the differences from the previous buffer and 75 // |last_invalid_rects| holds the differences from the previous buffer and
76 // the one prior to that (which will then be the current buffer). 76 // the one prior to that (which will then be the current buffer).
77 void SynchronizeFrame(); 77 void SynchronizeFrame();
78 78
79 void DeinitXlib(); 79 void DeinitXlib();
80 80
81 rtc::ThreadChecker thread_checker_;
82
83 DesktopCaptureOptions options_; 81 DesktopCaptureOptions options_;
84 82
85 Callback* callback_ = nullptr; 83 Callback* callback_;
86 84
87 // X11 graphics context. 85 // X11 graphics context.
88 GC gc_ = nullptr; 86 GC gc_;
89 Window root_window_ = BadValue; 87 Window root_window_;
90 88
91 // XFixes. 89 // XFixes.
92 bool has_xfixes_ = false; 90 bool has_xfixes_;
93 int xfixes_event_base_ = -1; 91 int xfixes_event_base_;
94 int xfixes_error_base_ = -1; 92 int xfixes_error_base_;
95 93
96 // XDamage information. 94 // XDamage information.
97 bool use_damage_ = false; 95 bool use_damage_;
98 Damage damage_handle_ = 0; 96 Damage damage_handle_;
99 int damage_event_base_ = -1; 97 int damage_event_base_;
100 int damage_error_base_ = -1; 98 int damage_error_base_;
101 XserverRegion damage_region_ = 0; 99 XserverRegion damage_region_;
102 100
103 // Access to the X Server's pixel buffer. 101 // Access to the X Server's pixel buffer.
104 XServerPixelBuffer x_server_pixel_buffer_; 102 XServerPixelBuffer x_server_pixel_buffer_;
105 103
106 // A thread-safe list of invalid rectangles, and the size of the most 104 // A thread-safe list of invalid rectangles, and the size of the most
107 // recently captured screen. 105 // recently captured screen.
108 ScreenCapturerHelper helper_; 106 ScreenCapturerHelper helper_;
109 107
110 // Queue of the frames buffers. 108 // Queue of the frames buffers.
111 ScreenCaptureFrameQueue queue_; 109 ScreenCaptureFrameQueue queue_;
112 110
113 // Invalid region from the previous capture. This is used to synchronize the 111 // Invalid region from the previous capture. This is used to synchronize the
114 // current with the last buffer used. 112 // current with the last buffer used.
115 DesktopRegion last_invalid_region_; 113 DesktopRegion last_invalid_region_;
116 114
117 // |Differ| for use when polling for changes. 115 // |Differ| for use when polling for changes.
118 std::unique_ptr<Differ> differ_; 116 std::unique_ptr<Differ> differ_;
119 117
120 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); 118 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux);
121 }; 119 };
122 120
123 ScreenCapturerLinux::ScreenCapturerLinux(const DesktopCaptureOptions& options) 121 ScreenCapturerLinux::ScreenCapturerLinux()
124 : options_(options) { 122 : callback_(NULL),
125 // ScreenCapturer can be used on a thread different from the thread on which 123 gc_(NULL),
126 // it's created. 124 root_window_(BadValue),
127 thread_checker_.DetachFromThread(); 125 has_xfixes_(false),
126 xfixes_event_base_(-1),
127 xfixes_error_base_(-1),
128 use_damage_(false),
129 damage_handle_(0),
130 damage_event_base_(-1),
131 damage_error_base_(-1),
132 damage_region_(0) {
133 helper_.SetLogGridSize(4);
128 } 134 }
129 135
130 ScreenCapturerLinux::~ScreenCapturerLinux() { 136 ScreenCapturerLinux::~ScreenCapturerLinux() {
131 RTC_DCHECK(thread_checker_.CalledOnValidThread());
132
133 options_.x_display()->RemoveEventHandler(ConfigureNotify, this); 137 options_.x_display()->RemoveEventHandler(ConfigureNotify, this);
134 if (use_damage_) { 138 if (use_damage_) {
135 options_.x_display()->RemoveEventHandler( 139 options_.x_display()->RemoveEventHandler(
136 damage_event_base_ + XDamageNotify, this); 140 damage_event_base_ + XDamageNotify, this);
137 } 141 }
138 DeinitXlib(); 142 DeinitXlib();
139 } 143 }
140 144
141 bool ScreenCapturerLinux::Initialize() { 145 bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) {
142 helper_.SetLogGridSize(4); 146 options_ = options;
143 147
144 root_window_ = RootWindow(display(), DefaultScreen(display())); 148 root_window_ = RootWindow(display(), DefaultScreen(display()));
145 if (root_window_ == BadValue) { 149 if (root_window_ == BadValue) {
146 LOG(LS_ERROR) << "Unable to get the root window"; 150 LOG(LS_ERROR) << "Unable to get the root window";
147 DeinitXlib(); 151 DeinitXlib();
148 return false; 152 return false;
149 } 153 }
150 154
151 gc_ = XCreateGC(display(), root_window_, 0, NULL); 155 gc_ = XCreateGC(display(), root_window_, 0, NULL);
152 if (gc_ == NULL) { 156 if (gc_ == NULL) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 return; 191 return;
188 } 192 }
189 193
190 // Check for XDamage extension. 194 // Check for XDamage extension.
191 if (!XDamageQueryExtension(display(), &damage_event_base_, 195 if (!XDamageQueryExtension(display(), &damage_event_base_,
192 &damage_error_base_)) { 196 &damage_error_base_)) {
193 LOG(LS_INFO) << "X server does not support XDamage."; 197 LOG(LS_INFO) << "X server does not support XDamage.";
194 return; 198 return;
195 } 199 }
196 200
201 // TODO(lambroslambrou): Disable DAMAGE in situations where it is known
202 // to fail, such as when Desktop Effects are enabled, with graphics
203 // drivers (nVidia, ATI) that fail to report DAMAGE notifications
204 // properly.
205
197 // Request notifications every time the screen becomes damaged. 206 // Request notifications every time the screen becomes damaged.
198 damage_handle_ = XDamageCreate(display(), root_window_, 207 damage_handle_ = XDamageCreate(display(), root_window_,
199 XDamageReportNonEmpty); 208 XDamageReportNonEmpty);
200 if (!damage_handle_) { 209 if (!damage_handle_) {
201 LOG(LS_ERROR) << "Unable to initialize XDamage."; 210 LOG(LS_ERROR) << "Unable to initialize XDamage.";
202 return; 211 return;
203 } 212 }
204 213
205 // Create an XFixes server-side region to collate damage into. 214 // Create an XFixes server-side region to collate damage into.
206 damage_region_ = XFixesCreateRegion(display(), 0, 0); 215 damage_region_ = XFixesCreateRegion(display(), 0, 0);
207 if (!damage_region_) { 216 if (!damage_region_) {
208 XDamageDestroy(display(), damage_handle_); 217 XDamageDestroy(display(), damage_handle_);
209 LOG(LS_ERROR) << "Unable to create XFixes region."; 218 LOG(LS_ERROR) << "Unable to create XFixes region.";
210 return; 219 return;
211 } 220 }
212 221
213 options_.x_display()->AddEventHandler( 222 options_.x_display()->AddEventHandler(
214 damage_event_base_ + XDamageNotify, this); 223 damage_event_base_ + XDamageNotify, this);
215 224
216 use_damage_ = true; 225 use_damage_ = true;
217 LOG(LS_INFO) << "Using XDamage extension."; 226 LOG(LS_INFO) << "Using XDamage extension.";
218 } 227 }
219 228
220 void ScreenCapturerLinux::Start(Callback* callback) { 229 void ScreenCapturerLinux::Start(Callback* callback) {
221 RTC_DCHECK(thread_checker_.CalledOnValidThread());
222 RTC_DCHECK(!callback_); 230 RTC_DCHECK(!callback_);
223 RTC_DCHECK(callback); 231 RTC_DCHECK(callback);
224 232
225 callback_ = callback; 233 callback_ = callback;
226
227 if (!Initialize()) {
228 callback_->OnInitializationFailed();
229 }
230 } 234 }
231 235
232 void ScreenCapturerLinux::Capture(const DesktopRegion& region) { 236 void ScreenCapturerLinux::Capture(const DesktopRegion& region) {
233 RTC_DCHECK(thread_checker_.CalledOnValidThread());
234
235 TickTime capture_start_time = TickTime::Now(); 237 TickTime capture_start_time = TickTime::Now();
236 238
237 queue_.MoveToNextFrame(); 239 queue_.MoveToNextFrame();
238 240
239 // Process XEvents for XDamage and cursor shape tracking. 241 // Process XEvents for XDamage and cursor shape tracking.
240 options_.x_display()->ProcessPendingXEvents(); 242 options_.x_display()->ProcessPendingXEvents();
241 243
242 // ProcessPendingXEvents() may call ScreenConfigurationChanged() which 244 // ProcessPendingXEvents() may call ScreenConfigurationChanged() which
243 // reinitializes |x_server_pixel_buffer_|. Check if the pixel buffer is still 245 // reinitializes |x_server_pixel_buffer_|. Check if the pixel buffer is still
244 // in a good shape. 246 // in a good shape.
(...skipping 25 matching lines...) Expand all
270 } 272 }
271 273
272 DesktopFrame* result = CaptureScreen(); 274 DesktopFrame* result = CaptureScreen();
273 last_invalid_region_ = result->updated_region(); 275 last_invalid_region_ = result->updated_region();
274 result->set_capture_time_ms( 276 result->set_capture_time_ms(
275 (TickTime::Now() - capture_start_time).Milliseconds()); 277 (TickTime::Now() - capture_start_time).Milliseconds());
276 callback_->OnCaptureCompleted(result); 278 callback_->OnCaptureCompleted(result);
277 } 279 }
278 280
279 bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { 281 bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) {
280 RTC_DCHECK(thread_checker_.CalledOnValidThread());
281 RTC_DCHECK(screens->size() == 0); 282 RTC_DCHECK(screens->size() == 0);
282
283 // TODO(jiayl): implement screen enumeration. 283 // TODO(jiayl): implement screen enumeration.
284 Screen default_screen; 284 Screen default_screen;
285 default_screen.id = 0; 285 default_screen.id = 0;
286 screens->push_back(default_screen); 286 screens->push_back(default_screen);
287 return true; 287 return true;
288 } 288 }
289 289
290 bool ScreenCapturerLinux::SelectScreen(ScreenId id) { 290 bool ScreenCapturerLinux::SelectScreen(ScreenId id) {
291 RTC_DCHECK(thread_checker_.CalledOnValidThread());
292 // TODO(jiayl): implement screen selection. 291 // TODO(jiayl): implement screen selection.
293 return true; 292 return true;
294 } 293 }
295 294
296 bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { 295 bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) {
297 RTC_DCHECK(thread_checker_.CalledOnValidThread());
298
299 if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) { 296 if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) {
300 const XDamageNotifyEvent* damage_event = 297 const XDamageNotifyEvent* damage_event =
301 reinterpret_cast<const XDamageNotifyEvent*>(&event); 298 reinterpret_cast<const XDamageNotifyEvent*>(&event);
302 if (damage_event->damage != damage_handle_) 299 if (damage_event->damage != damage_handle_)
303 return false; 300 return false;
304 RTC_DCHECK(damage_event->level == XDamageReportNonEmpty); 301 RTC_DCHECK(damage_event->level == XDamageReportNonEmpty);
305 return true; 302 return true;
306 } else if (event.type == ConfigureNotify) { 303 } else if (event.type == ConfigureNotify) {
307 ScreenConfigurationChanged(); 304 ScreenConfigurationChanged();
308 return true; 305 return true;
309 } 306 }
310 return false; 307 return false;
311 } 308 }
312 309
313 DesktopFrame* ScreenCapturerLinux::CaptureScreen() { 310 DesktopFrame* ScreenCapturerLinux::CaptureScreen() {
314 DesktopFrame* frame = queue_.current_frame()->Share(); 311 DesktopFrame* frame = queue_.current_frame()->Share();
315 RTC_DCHECK(x_server_pixel_buffer_.window_size().equals(frame->size())); 312 assert(x_server_pixel_buffer_.window_size().equals(frame->size()));
316 313
317 // Pass the screen size to the helper, so it can clip the invalid region if it 314 // Pass the screen size to the helper, so it can clip the invalid region if it
318 // expands that region to a grid. 315 // expands that region to a grid.
319 helper_.set_size_most_recent(frame->size()); 316 helper_.set_size_most_recent(frame->size());
320 317
321 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame 318 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame
322 // if any. If there isn't a previous frame, that means a screen-resolution 319 // if any. If there isn't a previous frame, that means a screen-resolution
323 // change occurred, and |invalid_rects| will be updated to include the whole 320 // change occurred, and |invalid_rects| will be updated to include the whole
324 // screen. 321 // screen.
325 if (use_damage_ && queue_.previous_frame()) 322 if (use_damage_ && queue_.previous_frame())
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 } 429 }
433 } 430 }
434 431
435 } // namespace 432 } // namespace
436 433
437 // static 434 // static
438 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { 435 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
439 if (!options.x_display()) 436 if (!options.x_display())
440 return NULL; 437 return NULL;
441 438
442 return new ScreenCapturerLinux(options); 439 std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
440 if (!capturer->Init(options))
441 capturer.reset();
442 return capturer.release();
443 } 443 }
444 444
445 } // namespace webrtc 445 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/desktop_capture/screen_capturer_mac.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698