Index: webrtc/modules/desktop_capture/screen_capturer_x11.cc |
diff --git a/webrtc/modules/desktop_capture/screen_capturer_x11.cc b/webrtc/modules/desktop_capture/screen_capturer_x11.cc |
index 65e682b6f8bdc1bd28ba99d515077122fc105adb..986fe2155f7abd62a7644c18be73fd0d91842496 100644 |
--- a/webrtc/modules/desktop_capture/screen_capturer_x11.cc |
+++ b/webrtc/modules/desktop_capture/screen_capturer_x11.cc |
@@ -21,6 +21,7 @@ |
#include <X11/Xutil.h> |
#include "webrtc/base/checks.h" |
+#include "webrtc/base/thread_checker.h" |
#include "webrtc/modules/desktop_capture/desktop_capture_options.h" |
#include "webrtc/modules/desktop_capture/desktop_frame.h" |
#include "webrtc/modules/desktop_capture/differ.h" |
@@ -37,12 +38,9 @@ namespace { |
class ScreenCapturerLinux : public ScreenCapturer, |
public SharedXDisplay::XEventHandler { |
public: |
- ScreenCapturerLinux(); |
+ explicit ScreenCapturerLinux(const DesktopCaptureOptions& options); |
virtual ~ScreenCapturerLinux(); |
- // TODO(ajwong): Do we really want this to be synchronous? |
- bool Init(const DesktopCaptureOptions& options); |
- |
// DesktopCapturer interface. |
void Start(Callback* delegate) override; |
void Capture(const DesktopRegion& region) override; |
@@ -54,11 +52,13 @@ class ScreenCapturerLinux : public ScreenCapturer, |
private: |
Display* display() { return options_.x_display()->display(); } |
- // SharedXDisplay::XEventHandler interface. |
- bool HandleXEvent(const XEvent& event) override; |
+ bool Initialize(); |
void InitXDamage(); |
+ // SharedXDisplay::XEventHandler interface. |
+ bool HandleXEvent(const XEvent& event) override; |
+ |
// Capture screen pixels to the current buffer in the queue. In the DAMAGE |
// case, the ScreenCapturerHelper already holds the list of invalid rectangles |
// from HandleXEvent(). In the non-DAMAGE case, this captures the |
@@ -78,25 +78,27 @@ class ScreenCapturerLinux : public ScreenCapturer, |
void DeinitXlib(); |
+ rtc::ThreadChecker thread_checker_; |
+ |
DesktopCaptureOptions options_; |
- Callback* callback_; |
+ Callback* callback_ = nullptr; |
// X11 graphics context. |
- GC gc_; |
- Window root_window_; |
+ GC gc_ = nullptr; |
+ Window root_window_ = BadValue; |
// XFixes. |
- bool has_xfixes_; |
- int xfixes_event_base_; |
- int xfixes_error_base_; |
+ bool has_xfixes_ = false; |
+ int xfixes_event_base_ = -1; |
+ int xfixes_error_base_ = -1; |
// XDamage information. |
- bool use_damage_; |
- Damage damage_handle_; |
- int damage_event_base_; |
- int damage_error_base_; |
- XserverRegion damage_region_; |
+ bool use_damage_ = false; |
+ Damage damage_handle_ = 0; |
+ int damage_event_base_ = -1; |
+ int damage_error_base_ = -1; |
+ XserverRegion damage_region_ = 0; |
// Access to the X Server's pixel buffer. |
XServerPixelBuffer x_server_pixel_buffer_; |
@@ -118,22 +120,16 @@ class ScreenCapturerLinux : public ScreenCapturer, |
RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); |
}; |
-ScreenCapturerLinux::ScreenCapturerLinux() |
- : callback_(NULL), |
- gc_(NULL), |
- root_window_(BadValue), |
- has_xfixes_(false), |
- xfixes_event_base_(-1), |
- xfixes_error_base_(-1), |
- use_damage_(false), |
- damage_handle_(0), |
- damage_event_base_(-1), |
- damage_error_base_(-1), |
- damage_region_(0) { |
- helper_.SetLogGridSize(4); |
+ScreenCapturerLinux::ScreenCapturerLinux(const DesktopCaptureOptions& options) |
+ : options_(options) { |
+ // ScreenCapturer can be used on a thread different from the thread on which |
+ // it's created. |
+ thread_checker_.DetachFromThread(); |
} |
ScreenCapturerLinux::~ScreenCapturerLinux() { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
options_.x_display()->RemoveEventHandler(ConfigureNotify, this); |
if (use_damage_) { |
options_.x_display()->RemoveEventHandler( |
@@ -142,8 +138,8 @@ ScreenCapturerLinux::~ScreenCapturerLinux() { |
DeinitXlib(); |
} |
-bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { |
- options_ = options; |
+bool ScreenCapturerLinux::Initialize() { |
+ helper_.SetLogGridSize(4); |
root_window_ = RootWindow(display(), DefaultScreen(display())); |
if (root_window_ == BadValue) { |
@@ -198,11 +194,6 @@ void ScreenCapturerLinux::InitXDamage() { |
return; |
} |
- // TODO(lambroslambrou): Disable DAMAGE in situations where it is known |
- // to fail, such as when Desktop Effects are enabled, with graphics |
- // drivers (nVidia, ATI) that fail to report DAMAGE notifications |
- // properly. |
- |
// Request notifications every time the screen becomes damaged. |
damage_handle_ = XDamageCreate(display(), root_window_, |
XDamageReportNonEmpty); |
@@ -227,13 +218,20 @@ void ScreenCapturerLinux::InitXDamage() { |
} |
void ScreenCapturerLinux::Start(Callback* callback) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
RTC_DCHECK(!callback_); |
RTC_DCHECK(callback); |
callback_ = callback; |
+ |
+ if (!Initialize()) { |
+ callback_->OnInitializationFailed(); |
+ } |
} |
void ScreenCapturerLinux::Capture(const DesktopRegion& region) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
TickTime capture_start_time = TickTime::Now(); |
queue_.MoveToNextFrame(); |
@@ -279,7 +277,9 @@ void ScreenCapturerLinux::Capture(const DesktopRegion& region) { |
} |
bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
RTC_DCHECK(screens->size() == 0); |
+ |
// TODO(jiayl): implement screen enumeration. |
Screen default_screen; |
default_screen.id = 0; |
@@ -288,11 +288,14 @@ bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { |
} |
bool ScreenCapturerLinux::SelectScreen(ScreenId id) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
// TODO(jiayl): implement screen selection. |
return true; |
} |
bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) { |
const XDamageNotifyEvent* damage_event = |
reinterpret_cast<const XDamageNotifyEvent*>(&event); |
@@ -309,7 +312,7 @@ bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { |
DesktopFrame* ScreenCapturerLinux::CaptureScreen() { |
DesktopFrame* frame = queue_.current_frame()->Share(); |
- assert(x_server_pixel_buffer_.window_size().equals(frame->size())); |
+ RTC_DCHECK(x_server_pixel_buffer_.window_size().equals(frame->size())); |
// Pass the screen size to the helper, so it can clip the invalid region if it |
// expands that region to a grid. |
@@ -436,10 +439,7 @@ ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { |
if (!options.x_display()) |
return NULL; |
- std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); |
- if (!capturer->Init(options)) |
- capturer.reset(); |
- return capturer.release(); |
+ return new ScreenCapturerLinux(options); |
} |
} // namespace webrtc |