Add DesktopCaptureOptions class.
The new class is used to pass configuration parameters to screen/window capturers. It also allows to share X Window connection between multiple objects. R=wez@chromium.org Review URL: https://webrtc-codereview.appspot.com/2374004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4952 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
f53622d42e
commit
894e6fe9ea
@ -22,6 +22,9 @@
|
||||
"desktop_frame_win.h",
|
||||
"desktop_geometry.cc",
|
||||
"desktop_geometry.h",
|
||||
"desktop_capture_options.h",
|
||||
"desktop_capture_options.cc",
|
||||
"desktop_capturer.h",
|
||||
"desktop_region.cc",
|
||||
"desktop_region.h",
|
||||
"differ.cc",
|
||||
@ -35,6 +38,7 @@
|
||||
"mouse_cursor_shape.h",
|
||||
"screen_capture_frame_queue.cc",
|
||||
"screen_capture_frame_queue.h",
|
||||
"screen_capturer.cc",
|
||||
"screen_capturer.h",
|
||||
"screen_capturer_helper.cc",
|
||||
"screen_capturer_helper.h",
|
||||
@ -52,10 +56,13 @@
|
||||
"win/scoped_gdi_object.h",
|
||||
"win/scoped_thread_desktop.cc",
|
||||
"win/scoped_thread_desktop.h",
|
||||
"window_capturer.cc",
|
||||
"window_capturer.h",
|
||||
"window_capturer_mac.cc",
|
||||
"window_capturer_win.cc",
|
||||
"window_capturer_x11.cc",
|
||||
"x11/shared_x_display.h",
|
||||
"x11/shared_x_display.cc",
|
||||
"x11/x_error_trap.cc",
|
||||
"x11/x_error_trap.h",
|
||||
"x11/x_server_pixel_buffer.cc",
|
||||
|
35
webrtc/modules/desktop_capture/desktop_capture_options.cc
Normal file
35
webrtc/modules/desktop_capture/desktop_capture_options.cc
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
DesktopCaptureOptions::DesktopCaptureOptions()
|
||||
: use_update_notifications_(true),
|
||||
disable_effects_(true) {
|
||||
#if defined(USE_X11)
|
||||
// XDamage is often broken, so don't use it by default.
|
||||
use_update_notifications_ = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
DesktopCaptureOptions::~DesktopCaptureOptions() {}
|
||||
|
||||
// static
|
||||
DesktopCaptureOptions DesktopCaptureOptions::CreateDefault() {
|
||||
DesktopCaptureOptions result;
|
||||
#if defined(USE_X11)
|
||||
result.set_x_display(SharedXDisplay::CreateDefault());
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
65
webrtc/modules/desktop_capture/desktop_capture_options.h
Normal file
65
webrtc/modules/desktop_capture/desktop_capture_options.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
|
||||
#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// An object that stores initialization parameters for screen and window
|
||||
// capturers.
|
||||
class DesktopCaptureOptions {
|
||||
public:
|
||||
// Creates an empty Options instance (e.g. without X display).
|
||||
DesktopCaptureOptions();
|
||||
~DesktopCaptureOptions();
|
||||
|
||||
// Returns instance of DesktopCaptureOptions with default parameters. On Linux
|
||||
// also initializes X window connection. x_display() will be set to null if
|
||||
// X11 connection failed (e.g. DISPLAY isn't set).
|
||||
static DesktopCaptureOptions CreateDefault();
|
||||
|
||||
#if defined(USE_X11)
|
||||
SharedXDisplay* x_display() const { return x_display_; }
|
||||
void set_x_display(scoped_refptr<SharedXDisplay> x_display) {
|
||||
x_display_ = x_display;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Flag indicating that the capturer should use screen change notifications.
|
||||
// Enables/disables use of XDAMAGE in the X11 capturer.
|
||||
bool use_update_notifications() const { return use_update_notifications_; }
|
||||
void set_use_update_notifications(bool use_update_notifications) {
|
||||
use_update_notifications_ = use_update_notifications;
|
||||
}
|
||||
|
||||
// Flag indicating if desktop effects (e.g. Aero) should be disabled when the
|
||||
// capturer is active. Currently used only on Windows.
|
||||
bool disable_effects() const { return disable_effects_; }
|
||||
void set_disable_effects(bool disable_effects) {
|
||||
disable_effects_ = disable_effects;
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(USE_X11)
|
||||
scoped_refptr<SharedXDisplay> x_display_;
|
||||
#endif
|
||||
bool use_update_notifications_;
|
||||
bool disable_effects_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
|
36
webrtc/modules/desktop_capture/screen_capturer.cc
Normal file
36
webrtc/modules/desktop_capture/screen_capturer.cc
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/desktop_capture/screen_capturer.h"
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ScreenCapturer* ScreenCapturer::Create() {
|
||||
return Create(DesktopCaptureOptions::CreateDefault());
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_LINUX)
|
||||
ScreenCapturer* ScreenCapturer::CreateWithXDamage(
|
||||
bool use_update_notifications) {
|
||||
DesktopCaptureOptions options;
|
||||
options.set_use_update_notifications(use_update_notifications);
|
||||
return Create(options);
|
||||
}
|
||||
#elif defined(WEBRTC_WIN)
|
||||
ScreenCapturer* ScreenCapturer::CreateWithDisableAero(bool disable_effects) {
|
||||
DesktopCaptureOptions options;
|
||||
options.set_disable_effects(disable_effects);
|
||||
return Create(options);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace webrtc
|
@ -17,6 +17,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class DesktopCaptureOptions;
|
||||
struct MouseCursorShape;
|
||||
|
||||
// Class used to capture video frames asynchronously.
|
||||
@ -57,6 +58,10 @@ class ScreenCapturer : public DesktopCapturer {
|
||||
virtual ~ScreenCapturer() {}
|
||||
|
||||
// Creates platform-specific capturer.
|
||||
//
|
||||
// TODO(sergeyu): Remove all Create() methods except the first one.
|
||||
// crbug.com/172183
|
||||
static ScreenCapturer* Create(const DesktopCaptureOptions& options);
|
||||
static ScreenCapturer* Create();
|
||||
|
||||
#if defined(WEBRTC_LINUX)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||
@ -895,7 +896,7 @@ void ScreenCapturerMac::DisplaysReconfiguredCallback(
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::Create() {
|
||||
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& context) {
|
||||
scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac());
|
||||
if (!capturer->Init())
|
||||
capturer.reset();
|
||||
|
@ -13,20 +13,8 @@
|
||||
namespace webrtc {
|
||||
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::Create() {
|
||||
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::CreateWithXDamage(bool use_x_damage) {
|
||||
return NULL;
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::CreateWithDisableAero(bool disable_aero) {
|
||||
return NULL;
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||
#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
|
||||
@ -29,6 +30,11 @@ class ScreenCapturerTest : public testing::Test {
|
||||
public:
|
||||
SharedMemory* CreateSharedMemory(size_t size);
|
||||
|
||||
virtual void SetUp() OVERRIDE {
|
||||
capturer_.reset(
|
||||
ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault()));
|
||||
}
|
||||
|
||||
protected:
|
||||
scoped_ptr<ScreenCapturer> capturer_;
|
||||
MockMouseShapeObserver mouse_observer_;
|
||||
@ -54,7 +60,6 @@ SharedMemory* ScreenCapturerTest::CreateSharedMemory(size_t size) {
|
||||
}
|
||||
|
||||
TEST_F(ScreenCapturerTest, StartCapturer) {
|
||||
capturer_.reset(ScreenCapturer::Create());
|
||||
capturer_->SetMouseShapeObserver(&mouse_observer_);
|
||||
capturer_->Start(&callback_);
|
||||
}
|
||||
@ -71,7 +76,6 @@ TEST_F(ScreenCapturerTest, Capture) {
|
||||
.Times(AnyNumber())
|
||||
.WillRepeatedly(Return(static_cast<SharedMemory*>(NULL)));
|
||||
|
||||
capturer_.reset(ScreenCapturer::Create());
|
||||
capturer_->Start(&callback_);
|
||||
capturer_->Capture(DesktopRegion());
|
||||
|
||||
@ -106,7 +110,6 @@ TEST_F(ScreenCapturerTest, UseSharedBuffers) {
|
||||
.Times(AnyNumber())
|
||||
.WillRepeatedly(Invoke(this, &ScreenCapturerTest::CreateSharedMemory));
|
||||
|
||||
capturer_.reset(ScreenCapturer::Create());
|
||||
capturer_->Start(&callback_);
|
||||
capturer_->Capture(DesktopRegion());
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||
@ -43,7 +44,7 @@ const wchar_t kDwmapiLibraryName[] = L"dwmapi.dll";
|
||||
// ScreenCapturerWin is double-buffered as required by ScreenCapturer.
|
||||
class ScreenCapturerWin : public ScreenCapturer {
|
||||
public:
|
||||
ScreenCapturerWin(bool disable_aero);
|
||||
ScreenCapturerWin(const DesktopCaptureOptions& options);
|
||||
virtual ~ScreenCapturerWin();
|
||||
|
||||
// Overridden from ScreenCapturer:
|
||||
@ -98,7 +99,7 @@ class ScreenCapturerWin : public ScreenCapturer {
|
||||
DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWin);
|
||||
};
|
||||
|
||||
ScreenCapturerWin::ScreenCapturerWin(bool disable_aero)
|
||||
ScreenCapturerWin::ScreenCapturerWin(const DesktopCaptureOptions& options)
|
||||
: callback_(NULL),
|
||||
mouse_shape_observer_(NULL),
|
||||
desktop_dc_(NULL),
|
||||
@ -106,7 +107,7 @@ ScreenCapturerWin::ScreenCapturerWin(bool disable_aero)
|
||||
dwmapi_library_(NULL),
|
||||
composition_func_(NULL),
|
||||
set_thread_execution_state_failed_(false) {
|
||||
if (disable_aero) {
|
||||
if (options.disable_effects()) {
|
||||
// Load dwmapi.dll dynamically since it is not available on XP.
|
||||
if (!dwmapi_library_)
|
||||
dwmapi_library_ = LoadLibrary(kDwmapiLibraryName);
|
||||
@ -353,13 +354,8 @@ void ScreenCapturerWin::CaptureCursor() {
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::Create() {
|
||||
return CreateWithDisableAero(true);
|
||||
}
|
||||
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::CreateWithDisableAero(bool disable_aero) {
|
||||
return new ScreenCapturerWin(disable_aero);
|
||||
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
|
||||
return new ScreenCapturerWin(options);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.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"
|
||||
#include "webrtc/modules/desktop_capture/mouse_cursor_shape.h"
|
||||
@ -46,7 +47,7 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
||||
virtual ~ScreenCapturerLinux();
|
||||
|
||||
// TODO(ajwong): Do we really want this to be synchronous?
|
||||
bool Init(bool use_x_damage);
|
||||
bool Init(const DesktopCaptureOptions& options);
|
||||
|
||||
// DesktopCapturer interface.
|
||||
virtual void Start(Callback* delegate) OVERRIDE;
|
||||
@ -57,6 +58,8 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
||||
MouseShapeObserver* mouse_shape_observer) OVERRIDE;
|
||||
|
||||
private:
|
||||
Display* display() { return options_.x_display()->display(); }
|
||||
|
||||
void InitXDamage();
|
||||
|
||||
// Read and handle all currently-pending XEvents.
|
||||
@ -88,11 +91,12 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
||||
|
||||
void DeinitXlib();
|
||||
|
||||
DesktopCaptureOptions options_;
|
||||
|
||||
Callback* callback_;
|
||||
MouseShapeObserver* mouse_shape_observer_;
|
||||
|
||||
// X11 graphics context.
|
||||
Display* display_;
|
||||
GC gc_;
|
||||
Window root_window_;
|
||||
|
||||
@ -131,7 +135,6 @@ class ScreenCapturerLinux : public ScreenCapturer {
|
||||
ScreenCapturerLinux::ScreenCapturerLinux()
|
||||
: callback_(NULL),
|
||||
mouse_shape_observer_(NULL),
|
||||
display_(NULL),
|
||||
gc_(NULL),
|
||||
root_window_(BadValue),
|
||||
has_xfixes_(false),
|
||||
@ -149,23 +152,17 @@ ScreenCapturerLinux::~ScreenCapturerLinux() {
|
||||
DeinitXlib();
|
||||
}
|
||||
|
||||
bool ScreenCapturerLinux::Init(bool use_x_damage) {
|
||||
// TODO(ajwong): We should specify the display string we are attaching to
|
||||
// in the constructor.
|
||||
display_ = XOpenDisplay(NULL);
|
||||
if (!display_) {
|
||||
LOG(LS_ERROR) << "Unable to open display";
|
||||
return false;
|
||||
}
|
||||
bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) {
|
||||
options_ = options;
|
||||
|
||||
root_window_ = RootWindow(display_, DefaultScreen(display_));
|
||||
root_window_ = RootWindow(display(), DefaultScreen(display()));
|
||||
if (root_window_ == BadValue) {
|
||||
LOG(LS_ERROR) << "Unable to get the root window";
|
||||
DeinitXlib();
|
||||
return false;
|
||||
}
|
||||
|
||||
gc_ = XCreateGC(display_, root_window_, 0, NULL);
|
||||
gc_ = XCreateGC(display(), root_window_, 0, NULL);
|
||||
if (gc_ == NULL) {
|
||||
LOG(LS_ERROR) << "Unable to get graphics context";
|
||||
DeinitXlib();
|
||||
@ -174,7 +171,7 @@ bool ScreenCapturerLinux::Init(bool use_x_damage) {
|
||||
|
||||
// Check for XFixes extension. This is required for cursor shape
|
||||
// notifications, and for our use of XDamage.
|
||||
if (XFixesQueryExtension(display_, &xfixes_event_base_,
|
||||
if (XFixesQueryExtension(display(), &xfixes_event_base_,
|
||||
&xfixes_error_base_)) {
|
||||
has_xfixes_ = true;
|
||||
} else {
|
||||
@ -182,20 +179,20 @@ bool ScreenCapturerLinux::Init(bool use_x_damage) {
|
||||
}
|
||||
|
||||
// Register for changes to the dimensions of the root window.
|
||||
XSelectInput(display_, root_window_, StructureNotifyMask);
|
||||
XSelectInput(display(), root_window_, StructureNotifyMask);
|
||||
|
||||
if (!x_server_pixel_buffer_.Init(display_, DefaultRootWindow(display_))) {
|
||||
if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) {
|
||||
LOG(LS_ERROR) << "Failed to initialize pixel buffer.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (has_xfixes_) {
|
||||
// Register for changes to the cursor shape.
|
||||
XFixesSelectCursorInput(display_, root_window_,
|
||||
XFixesSelectCursorInput(display(), root_window_,
|
||||
XFixesDisplayCursorNotifyMask);
|
||||
}
|
||||
|
||||
if (use_x_damage) {
|
||||
if (options_.use_update_notifications()) {
|
||||
InitXDamage();
|
||||
}
|
||||
|
||||
@ -209,7 +206,7 @@ void ScreenCapturerLinux::InitXDamage() {
|
||||
}
|
||||
|
||||
// Check for XDamage extension.
|
||||
if (!XDamageQueryExtension(display_, &damage_event_base_,
|
||||
if (!XDamageQueryExtension(display(), &damage_event_base_,
|
||||
&damage_error_base_)) {
|
||||
LOG(LS_INFO) << "X server does not support XDamage.";
|
||||
return;
|
||||
@ -221,7 +218,7 @@ void ScreenCapturerLinux::InitXDamage() {
|
||||
// properly.
|
||||
|
||||
// Request notifications every time the screen becomes damaged.
|
||||
damage_handle_ = XDamageCreate(display_, root_window_,
|
||||
damage_handle_ = XDamageCreate(display(), root_window_,
|
||||
XDamageReportNonEmpty);
|
||||
if (!damage_handle_) {
|
||||
LOG(LS_ERROR) << "Unable to initialize XDamage.";
|
||||
@ -229,9 +226,9 @@ void ScreenCapturerLinux::InitXDamage() {
|
||||
}
|
||||
|
||||
// Create an XFixes server-side region to collate damage into.
|
||||
damage_region_ = XFixesCreateRegion(display_, 0, 0);
|
||||
damage_region_ = XFixesCreateRegion(display(), 0, 0);
|
||||
if (!damage_region_) {
|
||||
XDamageDestroy(display_, damage_handle_);
|
||||
XDamageDestroy(display(), damage_handle_);
|
||||
LOG(LS_ERROR) << "Unable to create XFixes region.";
|
||||
return;
|
||||
}
|
||||
@ -303,11 +300,11 @@ void ScreenCapturerLinux::SetMouseShapeObserver(
|
||||
void ScreenCapturerLinux::ProcessPendingXEvents() {
|
||||
// Find the number of events that are outstanding "now." We don't just loop
|
||||
// on XPending because we want to guarantee this terminates.
|
||||
int events_to_process = XPending(display_);
|
||||
int events_to_process = XPending(display());
|
||||
XEvent e;
|
||||
|
||||
for (int i = 0; i < events_to_process; i++) {
|
||||
XNextEvent(display_, &e);
|
||||
XNextEvent(display(), &e);
|
||||
if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) {
|
||||
XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e);
|
||||
DCHECK(event->level == XDamageReportNonEmpty);
|
||||
@ -329,7 +326,7 @@ void ScreenCapturerLinux::ProcessPendingXEvents() {
|
||||
void ScreenCapturerLinux::CaptureCursor() {
|
||||
DCHECK(has_xfixes_);
|
||||
|
||||
XFixesCursorImage* img = XFixesGetCursorImage(display_);
|
||||
XFixesCursorImage* img = XFixesGetCursorImage(display());
|
||||
if (!img) {
|
||||
return;
|
||||
}
|
||||
@ -375,10 +372,10 @@ DesktopFrame* ScreenCapturerLinux::CaptureScreen() {
|
||||
x_server_pixel_buffer_.Synchronize();
|
||||
if (use_damage_ && queue_.previous_frame()) {
|
||||
// Atomically fetch and clear the damage region.
|
||||
XDamageSubtract(display_, damage_handle_, None, damage_region_);
|
||||
XDamageSubtract(display(), damage_handle_, None, damage_region_);
|
||||
int rects_num = 0;
|
||||
XRectangle bounds;
|
||||
XRectangle* rects = XFixesFetchRegionAndBounds(display_, damage_region_,
|
||||
XRectangle* rects = XFixesFetchRegionAndBounds(display(), damage_region_,
|
||||
&rects_num, &bounds);
|
||||
for (int i = 0; i < rects_num; ++i) {
|
||||
updated_region->AddRect(DesktopRect::MakeXYWH(
|
||||
@ -430,7 +427,7 @@ void ScreenCapturerLinux::ScreenConfigurationChanged() {
|
||||
queue_.Reset();
|
||||
|
||||
helper_.ClearInvalidRegion();
|
||||
if (!x_server_pixel_buffer_.Init(display_, DefaultRootWindow(display_))) {
|
||||
if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) {
|
||||
LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen "
|
||||
"configuration change.";
|
||||
}
|
||||
@ -465,38 +462,34 @@ void ScreenCapturerLinux::SynchronizeFrame() {
|
||||
|
||||
void ScreenCapturerLinux::DeinitXlib() {
|
||||
if (gc_) {
|
||||
XFreeGC(display_, gc_);
|
||||
XFreeGC(display(), gc_);
|
||||
gc_ = NULL;
|
||||
}
|
||||
|
||||
x_server_pixel_buffer_.Release();
|
||||
|
||||
if (display_) {
|
||||
if (damage_handle_)
|
||||
XDamageDestroy(display_, damage_handle_);
|
||||
if (damage_region_)
|
||||
XFixesDestroyRegion(display_, damage_region_);
|
||||
XCloseDisplay(display_);
|
||||
display_ = NULL;
|
||||
if (display()) {
|
||||
if (damage_handle_) {
|
||||
XDamageDestroy(display(), damage_handle_);
|
||||
damage_handle_ = 0;
|
||||
}
|
||||
|
||||
if (damage_region_) {
|
||||
XFixesDestroyRegion(display(), damage_region_);
|
||||
damage_region_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::Create() {
|
||||
scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
|
||||
if (!capturer->Init(false))
|
||||
capturer.reset();
|
||||
return capturer.release();
|
||||
}
|
||||
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
|
||||
if (!options.x_display())
|
||||
return NULL;
|
||||
|
||||
// static
|
||||
ScreenCapturer* ScreenCapturer::CreateWithXDamage(bool use_x_damage) {
|
||||
scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
|
||||
if (!capturer->Init(use_x_damage))
|
||||
if (!capturer->Init(options))
|
||||
capturer.reset();
|
||||
return capturer.release();
|
||||
}
|
||||
|
22
webrtc/modules/desktop_capture/window_capturer.cc
Normal file
22
webrtc/modules/desktop_capture/window_capturer.cc
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/desktop_capture/window_capturer.h"
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// static
|
||||
WindowCapturer* WindowCapturer::Create() {
|
||||
return Create(DesktopCaptureOptions::CreateDefault());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -20,6 +20,8 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class DesktopCaptureOptions;
|
||||
|
||||
class WindowCapturer : public DesktopCapturer {
|
||||
public:
|
||||
typedef intptr_t WindowId;
|
||||
@ -33,6 +35,9 @@ class WindowCapturer : public DesktopCapturer {
|
||||
|
||||
typedef std::vector<Window> WindowList;
|
||||
|
||||
static WindowCapturer* Create(const DesktopCaptureOptions& options);
|
||||
|
||||
// TODO(sergeyu): Remove this method. crbug.com/172183
|
||||
static WindowCapturer* Create();
|
||||
|
||||
virtual ~WindowCapturer() {}
|
||||
|
@ -196,7 +196,7 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
WindowCapturer* WindowCapturer::Create() {
|
||||
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||
return new WindowCapturerMac();
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ void WindowCapturerNull::Capture(const DesktopRegion& region) {
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
WindowCapturer* WindowCapturer::Create() {
|
||||
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||
return new WindowCapturerNull();
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
#include "webrtc/modules/desktop_capture/window_capturer.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_region.h"
|
||||
#include "webrtc/system_wrappers/interface/logging.h"
|
||||
@ -24,7 +23,8 @@ class WindowCapturerTest : public testing::Test,
|
||||
public DesktopCapturer::Callback {
|
||||
public:
|
||||
void SetUp() OVERRIDE {
|
||||
capturer_.reset(WindowCapturer::Create());
|
||||
capturer_.reset(
|
||||
WindowCapturer::Create(DesktopCaptureOptions::CreateDefault()));
|
||||
}
|
||||
|
||||
void TearDown() OVERRIDE {
|
||||
|
@ -248,7 +248,7 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
WindowCapturer* WindowCapturer::Create() {
|
||||
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||
return new WindowCapturerWin();
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,14 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||
#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
|
||||
#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
|
||||
#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
|
||||
#include "webrtc/system_wrappers/interface/logging.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_refptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -83,7 +86,7 @@ class XWindowProperty {
|
||||
|
||||
class WindowCapturerLinux : public WindowCapturer {
|
||||
public:
|
||||
WindowCapturerLinux();
|
||||
WindowCapturerLinux(const DesktopCaptureOptions& options);
|
||||
virtual ~WindowCapturerLinux();
|
||||
|
||||
// WindowCapturer interface.
|
||||
@ -95,6 +98,8 @@ class WindowCapturerLinux : public WindowCapturer {
|
||||
virtual void Capture(const DesktopRegion& region) OVERRIDE;
|
||||
|
||||
private:
|
||||
Display* display() { return x_display_->display(); }
|
||||
|
||||
// Iterates through |window| hierarchy to find first visible window, i.e. one
|
||||
// that has WM_STATE property set to NormalState.
|
||||
// See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
|
||||
@ -108,7 +113,7 @@ class WindowCapturerLinux : public WindowCapturer {
|
||||
|
||||
Callback* callback_;
|
||||
|
||||
Display* display_;
|
||||
scoped_refptr<SharedXDisplay> x_display_;
|
||||
|
||||
Atom wm_state_atom_;
|
||||
Atom window_type_atom_;
|
||||
@ -121,26 +126,20 @@ class WindowCapturerLinux : public WindowCapturer {
|
||||
DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux);
|
||||
};
|
||||
|
||||
WindowCapturerLinux::WindowCapturerLinux()
|
||||
WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options)
|
||||
: callback_(NULL),
|
||||
display_(NULL),
|
||||
x_display_(options.x_display()),
|
||||
has_composite_extension_(false),
|
||||
selected_window_(0) {
|
||||
display_ = XOpenDisplay(NULL);
|
||||
if (!display_) {
|
||||
LOG(LS_ERROR) << "Failed to open display.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Atoms so we don't need to do it every time they are used.
|
||||
wm_state_atom_ = XInternAtom(display_, "WM_STATE", True);
|
||||
window_type_atom_ = XInternAtom(display_, "_NET_WM_WINDOW_TYPE", True);
|
||||
wm_state_atom_ = XInternAtom(display(), "WM_STATE", True);
|
||||
window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True);
|
||||
normal_window_type_atom_ = XInternAtom(
|
||||
display_, "_NET_WM_WINDOW_TYPE_NORMAL", True);
|
||||
display(), "_NET_WM_WINDOW_TYPE_NORMAL", True);
|
||||
|
||||
int event_base, error_base, major_version, minor_version;
|
||||
if (XCompositeQueryExtension(display_, &event_base, &error_base) &&
|
||||
XCompositeQueryVersion(display_, &major_version, &minor_version) &&
|
||||
if (XCompositeQueryExtension(display(), &event_base, &error_base) &&
|
||||
XCompositeQueryVersion(display(), &major_version, &minor_version) &&
|
||||
// XCompositeNameWindowPixmap() requires version 0.2
|
||||
(major_version > 0 || minor_version >= 2)) {
|
||||
has_composite_extension_ = true;
|
||||
@ -149,26 +148,20 @@ WindowCapturerLinux::WindowCapturerLinux()
|
||||
}
|
||||
}
|
||||
|
||||
WindowCapturerLinux::~WindowCapturerLinux() {
|
||||
if (display_)
|
||||
XCloseDisplay(display_);
|
||||
}
|
||||
WindowCapturerLinux::~WindowCapturerLinux() {}
|
||||
|
||||
bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
||||
if (!display_)
|
||||
return false;
|
||||
|
||||
WindowList result;
|
||||
|
||||
XErrorTrap error_trap(display_);
|
||||
XErrorTrap error_trap(display());
|
||||
|
||||
int num_screens = XScreenCount(display_);
|
||||
int num_screens = XScreenCount(display());
|
||||
for (int screen = 0; screen < num_screens; ++screen) {
|
||||
::Window root_window = XRootWindow(display_, screen);
|
||||
::Window root_window = XRootWindow(display(), screen);
|
||||
::Window parent;
|
||||
::Window *children;
|
||||
unsigned int num_children;
|
||||
int status = XQueryTree(display_, root_window, &root_window, &parent,
|
||||
int status = XQueryTree(display(), root_window, &root_window, &parent,
|
||||
&children, &num_children);
|
||||
if (status == 0) {
|
||||
LOG(LS_ERROR) << "Failed to query for child windows for screen "
|
||||
@ -198,7 +191,7 @@ bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
||||
}
|
||||
|
||||
bool WindowCapturerLinux::SelectWindow(WindowId id) {
|
||||
if (!x_server_pixel_buffer_.Init(display_, id))
|
||||
if (!x_server_pixel_buffer_.Init(display(), id))
|
||||
return false;
|
||||
|
||||
selected_window_ = id;
|
||||
@ -210,7 +203,7 @@ bool WindowCapturerLinux::SelectWindow(WindowId id) {
|
||||
|
||||
// Redirect drawing to an offscreen buffer (ie, turn on compositing). X11
|
||||
// remembers who has requested this and will turn it off for us when we exit.
|
||||
XCompositeRedirectWindow(display_, id, CompositeRedirectAutomatic);
|
||||
XCompositeRedirectWindow(display(), id, CompositeRedirectAutomatic);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -244,7 +237,7 @@ void WindowCapturerLinux::Capture(const DesktopRegion& region) {
|
||||
|
||||
::Window WindowCapturerLinux::GetApplicationWindow(::Window window) {
|
||||
// Get WM_STATE property of the window.
|
||||
XWindowProperty<uint32_t> window_state(display_, window, wm_state_atom_);
|
||||
XWindowProperty<uint32_t> window_state(display(), window, wm_state_atom_);
|
||||
|
||||
// WM_STATE is considered to be set to WithdrawnState when it missing.
|
||||
int32_t state = window_state.is_valid() ?
|
||||
@ -262,7 +255,7 @@ void WindowCapturerLinux::Capture(const DesktopRegion& region) {
|
||||
::Window root, parent;
|
||||
::Window *children;
|
||||
unsigned int num_children;
|
||||
if (!XQueryTree(display_, window, &root, &parent, &children,
|
||||
if (!XQueryTree(display(), window, &root, &parent, &children,
|
||||
&num_children)) {
|
||||
LOG(LS_ERROR) << "Failed to query for child windows although window"
|
||||
<< "does not have a valid WM_STATE.";
|
||||
@ -289,7 +282,7 @@ bool WindowCapturerLinux::IsDesktopElement(::Window window) {
|
||||
// says this hint *should* be present on all windows, and we use the existence
|
||||
// of _NET_WM_WINDOW_TYPE_NORMAL in the property to indicate a window is not
|
||||
// a desktop element (that is, only "normal" windows should be shareable).
|
||||
XWindowProperty<uint32_t> window_type(display_, window, window_type_atom_);
|
||||
XWindowProperty<uint32_t> window_type(display(), window, window_type_atom_);
|
||||
if (window_type.is_valid() && window_type.size() > 0) {
|
||||
uint32_t* end = window_type.data() + window_type.size();
|
||||
bool is_normal = (end != std::find(
|
||||
@ -299,7 +292,7 @@ bool WindowCapturerLinux::IsDesktopElement(::Window window) {
|
||||
|
||||
// Fall back on using the hint.
|
||||
XClassHint class_hint;
|
||||
Status status = XGetClassHint(display_, window, &class_hint);
|
||||
Status status = XGetClassHint(display(), window, &class_hint);
|
||||
bool result = false;
|
||||
if (status == 0) {
|
||||
// No hints, assume this is a normal application window.
|
||||
@ -321,11 +314,11 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
|
||||
XTextProperty window_name;
|
||||
window_name.value = NULL;
|
||||
if (window) {
|
||||
status = XGetWMName(display_, window, &window_name);
|
||||
status = XGetWMName(display(), window, &window_name);
|
||||
if (status && window_name.value && window_name.nitems) {
|
||||
int cnt;
|
||||
char **list = NULL;
|
||||
status = Xutf8TextPropertyToTextList(display_, &window_name, &list,
|
||||
status = Xutf8TextPropertyToTextList(display(), &window_name, &list,
|
||||
&cnt);
|
||||
if (status >= Success && cnt && *list) {
|
||||
if (cnt > 1) {
|
||||
@ -347,8 +340,10 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
WindowCapturer* WindowCapturer::Create() {
|
||||
return new WindowCapturerLinux();
|
||||
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
|
||||
if (!options.x_display())
|
||||
return NULL;
|
||||
return new WindowCapturerLinux(options);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
43
webrtc/modules/desktop_capture/x11/shared_x_display.cc
Normal file
43
webrtc/modules/desktop_capture/x11/shared_x_display.cc
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
|
||||
|
||||
#include "webrtc/system_wrappers/interface/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
SharedXDisplay::SharedXDisplay(Display* display)
|
||||
: display_(display) {
|
||||
assert(display_);
|
||||
}
|
||||
|
||||
SharedXDisplay::~SharedXDisplay() {
|
||||
XCloseDisplay(display_);
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<SharedXDisplay> SharedXDisplay::Create(
|
||||
const std::string& display_name) {
|
||||
Display* display =
|
||||
XOpenDisplay(display_name.empty() ? NULL : display_name.c_str());
|
||||
if (!display) {
|
||||
LOG(LS_ERROR) << "Unable to open display";
|
||||
return NULL;
|
||||
}
|
||||
return new SharedXDisplay(display);
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<SharedXDisplay> SharedXDisplay::CreateDefault() {
|
||||
return Create(std::string());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
58
webrtc/modules/desktop_capture/x11/shared_x_display.h
Normal file
58
webrtc/modules/desktop_capture/x11/shared_x_display.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_
|
||||
#define WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_refptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// A ref-counted object to store XDisplay connection.
|
||||
class SharedXDisplay {
|
||||
public:
|
||||
// Takes ownership of |display|.
|
||||
explicit SharedXDisplay(Display* display);
|
||||
|
||||
void AddRef() { ++ref_count_; }
|
||||
void Release() {
|
||||
if (--ref_count_ == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
Display* display() { return display_; }
|
||||
|
||||
// Creates a new X11 Display for the |display_name|. NULL is returned if X11
|
||||
// connection failed. Equivalent to CreateDefault() when |display_name| is
|
||||
// empty.
|
||||
static scoped_refptr<SharedXDisplay> Create(const std::string& display_name);
|
||||
|
||||
// Creates X11 Display connection for the default display (e.g. specified in
|
||||
// DISPLAY). NULL is returned if X11 connection failed.
|
||||
static scoped_refptr<SharedXDisplay> CreateDefault();
|
||||
|
||||
private:
|
||||
~SharedXDisplay();
|
||||
|
||||
Atomic32 ref_count_;
|
||||
Display* display_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SharedXDisplay);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_
|
Loading…
Reference in New Issue
Block a user