OLD | NEW |
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 11 matching lines...) Expand all Loading... |
22 #include "webrtc/base/checks.h" | 22 #include "webrtc/base/checks.h" |
23 #include "webrtc/base/constructormagic.h" | 23 #include "webrtc/base/constructormagic.h" |
24 #include "webrtc/base/timeutils.h" | 24 #include "webrtc/base/timeutils.h" |
25 #include "webrtc/modules/desktop_capture/desktop_capturer.h" | 25 #include "webrtc/modules/desktop_capture/desktop_capturer.h" |
26 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" | 26 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" |
27 #include "webrtc/modules/desktop_capture/desktop_frame.h" | 27 #include "webrtc/modules/desktop_capture/desktop_frame.h" |
28 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" | 28 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" |
29 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" | 29 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" |
30 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" | 30 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" |
31 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" | 31 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" |
32 #include "webrtc/system_wrappers/include/logging.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 // | 37 // |
39 // If XDamage is used, this class sets DesktopFrame::updated_region() according | 38 // If XDamage is used, this class sets DesktopFrame::updated_region() according |
40 // to the areas reported by XDamage. Otherwise this class does not detect | 39 // to the areas reported by XDamage. Otherwise this class does not detect |
41 // DesktopFrame::updated_region(), the field is always set to the entire frame | 40 // DesktopFrame::updated_region(), the field is always set to the entire frame |
42 // rectangle. ScreenCapturerDifferWrapper should be used if that functionality | 41 // rectangle. ScreenCapturerDifferWrapper should be used if that functionality |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 damage_event_base_ + XDamageNotify, this); | 130 damage_event_base_ + XDamageNotify, this); |
132 } | 131 } |
133 DeinitXlib(); | 132 DeinitXlib(); |
134 } | 133 } |
135 | 134 |
136 bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { | 135 bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { |
137 options_ = options; | 136 options_ = options; |
138 | 137 |
139 root_window_ = RootWindow(display(), DefaultScreen(display())); | 138 root_window_ = RootWindow(display(), DefaultScreen(display())); |
140 if (root_window_ == BadValue) { | 139 if (root_window_ == BadValue) { |
141 LOG(LS_ERROR) << "Unable to get the root window"; | |
142 DeinitXlib(); | 140 DeinitXlib(); |
143 return false; | 141 return false; |
144 } | 142 } |
145 | 143 |
146 gc_ = XCreateGC(display(), root_window_, 0, NULL); | 144 gc_ = XCreateGC(display(), root_window_, 0, NULL); |
147 if (gc_ == NULL) { | 145 if (gc_ == NULL) { |
148 LOG(LS_ERROR) << "Unable to get graphics context"; | |
149 DeinitXlib(); | 146 DeinitXlib(); |
150 return false; | 147 return false; |
151 } | 148 } |
152 | 149 |
153 options_.x_display()->AddEventHandler(ConfigureNotify, this); | 150 options_.x_display()->AddEventHandler(ConfigureNotify, this); |
154 | 151 |
155 // Check for XFixes extension. This is required for cursor shape | 152 // Check for XFixes extension. This is required for cursor shape |
156 // notifications, and for our use of XDamage. | 153 // notifications, and for our use of XDamage. |
157 if (XFixesQueryExtension(display(), &xfixes_event_base_, | 154 if (XFixesQueryExtension(display(), &xfixes_event_base_, |
158 &xfixes_error_base_)) { | 155 &xfixes_error_base_)) { |
159 has_xfixes_ = true; | 156 has_xfixes_ = true; |
160 } else { | 157 } else { |
161 LOG(LS_INFO) << "X server does not support XFixes."; | |
162 } | 158 } |
163 | 159 |
164 // Register for changes to the dimensions of the root window. | 160 // Register for changes to the dimensions of the root window. |
165 XSelectInput(display(), root_window_, StructureNotifyMask); | 161 XSelectInput(display(), root_window_, StructureNotifyMask); |
166 | 162 |
167 if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { | 163 if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { |
168 LOG(LS_ERROR) << "Failed to initialize pixel buffer."; | |
169 return false; | 164 return false; |
170 } | 165 } |
171 | 166 |
172 if (options_.use_update_notifications()) { | 167 if (options_.use_update_notifications()) { |
173 InitXDamage(); | 168 InitXDamage(); |
174 } | 169 } |
175 | 170 |
176 return true; | 171 return true; |
177 } | 172 } |
178 | 173 |
179 void ScreenCapturerLinux::InitXDamage() { | 174 void ScreenCapturerLinux::InitXDamage() { |
180 // Our use of XDamage requires XFixes. | 175 // Our use of XDamage requires XFixes. |
181 if (!has_xfixes_) { | 176 if (!has_xfixes_) { |
182 return; | 177 return; |
183 } | 178 } |
184 | 179 |
185 // Check for XDamage extension. | 180 // Check for XDamage extension. |
186 if (!XDamageQueryExtension(display(), &damage_event_base_, | 181 if (!XDamageQueryExtension(display(), &damage_event_base_, |
187 &damage_error_base_)) { | 182 &damage_error_base_)) { |
188 LOG(LS_INFO) << "X server does not support XDamage."; | |
189 return; | 183 return; |
190 } | 184 } |
191 | 185 |
192 // TODO(lambroslambrou): Disable DAMAGE in situations where it is known | 186 // TODO(lambroslambrou): Disable DAMAGE in situations where it is known |
193 // to fail, such as when Desktop Effects are enabled, with graphics | 187 // to fail, such as when Desktop Effects are enabled, with graphics |
194 // drivers (nVidia, ATI) that fail to report DAMAGE notifications | 188 // drivers (nVidia, ATI) that fail to report DAMAGE notifications |
195 // properly. | 189 // properly. |
196 | 190 |
197 // Request notifications every time the screen becomes damaged. | 191 // Request notifications every time the screen becomes damaged. |
198 damage_handle_ = XDamageCreate(display(), root_window_, | 192 damage_handle_ = XDamageCreate(display(), root_window_, |
199 XDamageReportNonEmpty); | 193 XDamageReportNonEmpty); |
200 if (!damage_handle_) { | 194 if (!damage_handle_) { |
201 LOG(LS_ERROR) << "Unable to initialize XDamage."; | |
202 return; | 195 return; |
203 } | 196 } |
204 | 197 |
205 // Create an XFixes server-side region to collate damage into. | 198 // Create an XFixes server-side region to collate damage into. |
206 damage_region_ = XFixesCreateRegion(display(), 0, 0); | 199 damage_region_ = XFixesCreateRegion(display(), 0, 0); |
207 if (!damage_region_) { | 200 if (!damage_region_) { |
208 XDamageDestroy(display(), damage_handle_); | 201 XDamageDestroy(display(), damage_handle_); |
209 LOG(LS_ERROR) << "Unable to create XFixes region."; | |
210 return; | 202 return; |
211 } | 203 } |
212 | 204 |
213 options_.x_display()->AddEventHandler( | 205 options_.x_display()->AddEventHandler( |
214 damage_event_base_ + XDamageNotify, this); | 206 damage_event_base_ + XDamageNotify, this); |
215 | 207 |
216 use_damage_ = true; | 208 use_damage_ = true; |
217 LOG(LS_INFO) << "Using XDamage extension."; | |
218 } | 209 } |
219 | 210 |
220 void ScreenCapturerLinux::Start(Callback* callback) { | 211 void ScreenCapturerLinux::Start(Callback* callback) { |
221 RTC_DCHECK(!callback_); | 212 RTC_DCHECK(!callback_); |
222 RTC_DCHECK(callback); | 213 RTC_DCHECK(callback); |
223 | 214 |
224 callback_ = callback; | 215 callback_ = callback; |
225 } | 216 } |
226 | 217 |
227 void ScreenCapturerLinux::CaptureFrame() { | 218 void ScreenCapturerLinux::CaptureFrame() { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 | 338 |
348 return std::move(frame); | 339 return std::move(frame); |
349 } | 340 } |
350 | 341 |
351 void ScreenCapturerLinux::ScreenConfigurationChanged() { | 342 void ScreenCapturerLinux::ScreenConfigurationChanged() { |
352 // Make sure the frame buffers will be reallocated. | 343 // Make sure the frame buffers will be reallocated. |
353 queue_.Reset(); | 344 queue_.Reset(); |
354 | 345 |
355 helper_.ClearInvalidRegion(); | 346 helper_.ClearInvalidRegion(); |
356 if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { | 347 if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { |
357 LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen " | |
358 "configuration change."; | |
359 } | 348 } |
360 } | 349 } |
361 | 350 |
362 void ScreenCapturerLinux::SynchronizeFrame() { | 351 void ScreenCapturerLinux::SynchronizeFrame() { |
363 // Synchronize the current buffer with the previous one since we do not | 352 // Synchronize the current buffer with the previous one since we do not |
364 // capture the entire desktop. Note that encoder may be reading from the | 353 // capture the entire desktop. Note that encoder may be reading from the |
365 // previous buffer at this time so thread access complaints are false | 354 // previous buffer at this time so thread access complaints are false |
366 // positives. | 355 // positives. |
367 | 356 |
368 // TODO(hclam): We can reduce the amount of copying here by subtracting | 357 // TODO(hclam): We can reduce the amount of copying here by subtracting |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 | 399 |
411 std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); | 400 std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); |
412 if (!capturer.get()->Init(options)) { | 401 if (!capturer.get()->Init(options)) { |
413 return nullptr; | 402 return nullptr; |
414 } | 403 } |
415 | 404 |
416 return std::move(capturer); | 405 return std::move(capturer); |
417 } | 406 } |
418 | 407 |
419 } // namespace webrtc | 408 } // namespace webrtc |
OLD | NEW |