Use std::unique_ptr<> to pass frame ownership in DesktopCapturer impls.

Previously raw pointers were used for owned DesktopFrame instances.
Updated all screen and window capturer implementations to use
std::unique_ptr<>.

Also includes some other cleanups in the capturers:
 - s/NULL/nullptr
 - moved default initializers to class definition.

BUG=webrtc:5950

Review-Url: https://codereview.webrtc.org/1988783003
Cr-Commit-Position: refs/heads/master@{#13058}
This commit is contained in:
sergeyu
2016-06-07 16:41:58 -07:00
committed by Commit bot
parent 6ebdf6b2cc
commit 5d910286e1
29 changed files with 386 additions and 447 deletions

View File

@ -19,7 +19,8 @@ namespace webrtc {
// A DesktopFrame that is a sub-rect of another DesktopFrame. // A DesktopFrame that is a sub-rect of another DesktopFrame.
class CroppedDesktopFrame : public DesktopFrame { class CroppedDesktopFrame : public DesktopFrame {
public: public:
CroppedDesktopFrame(DesktopFrame* frame, const DesktopRect& rect); CroppedDesktopFrame(std::unique_ptr<DesktopFrame> frame,
const DesktopRect& rect);
private: private:
std::unique_ptr<DesktopFrame> frame_; std::unique_ptr<DesktopFrame> frame_;
@ -27,23 +28,23 @@ class CroppedDesktopFrame : public DesktopFrame {
RTC_DISALLOW_COPY_AND_ASSIGN(CroppedDesktopFrame); RTC_DISALLOW_COPY_AND_ASSIGN(CroppedDesktopFrame);
}; };
DesktopFrame* std::unique_ptr<DesktopFrame> CreateCroppedDesktopFrame(
CreateCroppedDesktopFrame(DesktopFrame* frame, const DesktopRect& rect) { std::unique_ptr<DesktopFrame> frame,
if (!DesktopRect::MakeSize(frame->size()).ContainsRect(rect)) { const DesktopRect& rect) {
delete frame; if (!DesktopRect::MakeSize(frame->size()).ContainsRect(rect))
return NULL; return nullptr;
return std::unique_ptr<DesktopFrame>(
new CroppedDesktopFrame(std::move(frame), rect));
} }
return new CroppedDesktopFrame(frame, rect); CroppedDesktopFrame::CroppedDesktopFrame(std::unique_ptr<DesktopFrame> frame,
}
CroppedDesktopFrame::CroppedDesktopFrame(DesktopFrame* frame,
const DesktopRect& rect) const DesktopRect& rect)
: DesktopFrame(rect.size(), : DesktopFrame(rect.size(),
frame->stride(), frame->stride(),
frame->GetFrameDataAtPos(rect.top_left()), frame->GetFrameDataAtPos(rect.top_left()),
frame->shared_memory()), frame->shared_memory()) {
frame_(frame) { frame_ = std::move(frame);
} }
} // namespace webrtc } // namespace webrtc

View File

@ -15,10 +15,11 @@
namespace webrtc { namespace webrtc {
// Always takes ownership of |frame|. Returns NULL if |rect| is not contained // Returns nullptr frame if |rect| is not contained by the bounds of |frame|.
// by the bounds of |frame|. std::unique_ptr<DesktopFrame> CreateCroppedDesktopFrame(
DesktopFrame* CreateCroppedDesktopFrame(DesktopFrame* frame, std::unique_ptr<DesktopFrame> frame,
const DesktopRect& rect); const DesktopRect& rect);
} // namespace webrtc } // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_CROPPED_DESKTOP_FRAME_H_ #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_CROPPED_DESKTOP_FRAME_H_

View File

@ -74,31 +74,31 @@ bool CroppingWindowCapturer::BringSelectedWindowToFront() {
return window_capturer_->BringSelectedWindowToFront(); return window_capturer_->BringSelectedWindowToFront();
} }
void CroppingWindowCapturer::OnCaptureCompleted(DesktopFrame* frame) { void CroppingWindowCapturer::OnCaptureResult(
std::unique_ptr<DesktopFrame> screen_frame(frame); DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> screen_frame) {
if (!ShouldUseScreenCapturer()) { if (!ShouldUseScreenCapturer()) {
LOG(LS_INFO) << "Window no longer on top when ScreenCapturer finishes"; LOG(LS_INFO) << "Window no longer on top when ScreenCapturer finishes";
window_capturer_->Capture(DesktopRegion()); window_capturer_->Capture(DesktopRegion());
return; return;
} }
if (!frame) { if (result != Result::SUCCESS) {
LOG(LS_WARNING) << "ScreenCapturer failed to capture a frame"; LOG(LS_WARNING) << "ScreenCapturer failed to capture a frame";
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(result, nullptr);
return; return;
} }
DesktopRect window_rect = GetWindowRectInVirtualScreen(); DesktopRect window_rect = GetWindowRectInVirtualScreen();
if (window_rect.is_empty()) { if (window_rect.is_empty()) {
LOG(LS_WARNING) << "Window rect is empty"; LOG(LS_WARNING) << "Window rect is empty";
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
std::unique_ptr<DesktopFrame> window_frame( callback_->OnCaptureResult(
CreateCroppedDesktopFrame(screen_frame.release(), window_rect)); Result::SUCCESS,
callback_->OnCaptureCompleted(window_frame.release()); CreateCroppedDesktopFrame(std::move(screen_frame), window_rect));
} }
#if !defined(WEBRTC_WIN) #if !defined(WEBRTC_WIN)

View File

@ -42,7 +42,8 @@ class CroppingWindowCapturer : public WindowCapturer,
// DesktopCapturer::Callback implementation, passed to |screen_capturer_| to // DesktopCapturer::Callback implementation, passed to |screen_capturer_| to
// intercept the capture result. // intercept the capture result.
void OnCaptureCompleted(DesktopFrame* frame) override; void OnCaptureResult(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> frame) override;
protected: protected:
explicit CroppingWindowCapturer(const DesktopCaptureOptions& options); explicit CroppingWindowCapturer(const DesktopCaptureOptions& options);

View File

@ -57,7 +57,7 @@ void AlphaBlend(uint8_t* dest, int dest_stride,
class DesktopFrameWithCursor : public DesktopFrame { class DesktopFrameWithCursor : public DesktopFrame {
public: public:
// Takes ownership of |frame|. // Takes ownership of |frame|.
DesktopFrameWithCursor(DesktopFrame* frame, DesktopFrameWithCursor(std::unique_ptr<DesktopFrame> frame,
const MouseCursor& cursor, const MouseCursor& cursor,
const DesktopVector& position); const DesktopVector& position);
virtual ~DesktopFrameWithCursor(); virtual ~DesktopFrameWithCursor();
@ -71,15 +71,18 @@ class DesktopFrameWithCursor : public DesktopFrame {
RTC_DISALLOW_COPY_AND_ASSIGN(DesktopFrameWithCursor); RTC_DISALLOW_COPY_AND_ASSIGN(DesktopFrameWithCursor);
}; };
DesktopFrameWithCursor::DesktopFrameWithCursor(DesktopFrame* frame, DesktopFrameWithCursor::DesktopFrameWithCursor(
std::unique_ptr<DesktopFrame> frame,
const MouseCursor& cursor, const MouseCursor& cursor,
const DesktopVector& position) const DesktopVector& position)
: DesktopFrame(frame->size(), frame->stride(), : DesktopFrame(frame->size(),
frame->data(), frame->shared_memory()), frame->stride(),
original_frame_(frame) { frame->data(),
frame->shared_memory()) {
set_dpi(frame->dpi()); set_dpi(frame->dpi());
set_capture_time_ms(frame->capture_time_ms()); set_capture_time_ms(frame->capture_time_ms());
mutable_updated_region()->Swap(frame->mutable_updated_region()); mutable_updated_region()->Swap(frame->mutable_updated_region());
original_frame_ = std::move(frame);
DesktopVector image_pos = position.subtract(cursor.hotspot()); DesktopVector image_pos = position.subtract(cursor.hotspot());
DesktopRect target_rect = DesktopRect::MakeSize(cursor.image()->size()); DesktopRect target_rect = DesktopRect::MakeSize(cursor.image()->size());
@ -152,14 +155,15 @@ void DesktopAndCursorComposer::SetExcludedWindow(WindowId window) {
desktop_capturer_->SetExcludedWindow(window); desktop_capturer_->SetExcludedWindow(window);
} }
void DesktopAndCursorComposer::OnCaptureCompleted(DesktopFrame* frame) { void DesktopAndCursorComposer::OnCaptureResult(
if (frame && cursor_.get() && cursor_state_ == MouseCursorMonitor::INSIDE) { DesktopCapturer::Result result,
DesktopFrameWithCursor* frame_with_cursor = std::unique_ptr<DesktopFrame> frame) {
new DesktopFrameWithCursor(frame, *cursor_, cursor_position_); if (frame && cursor_ && cursor_state_ == MouseCursorMonitor::INSIDE) {
frame = frame_with_cursor; frame = std::unique_ptr<DesktopFrameWithCursor>(new DesktopFrameWithCursor(
std::move(frame), *cursor_, cursor_position_));
} }
callback_->OnCaptureCompleted(frame); callback_->OnCaptureResult(result, std::move(frame));
} }
void DesktopAndCursorComposer::OnMouseCursor(MouseCursor* cursor) { void DesktopAndCursorComposer::OnMouseCursor(MouseCursor* cursor) {

View File

@ -42,7 +42,8 @@ class DesktopAndCursorComposer : public DesktopCapturer,
private: private:
// DesktopCapturer::Callback interface. // DesktopCapturer::Callback interface.
void OnCaptureCompleted(DesktopFrame* frame) override; void OnCaptureResult(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> frame) override;
// MouseCursorMonitor::Callback interface. // MouseCursorMonitor::Callback interface.
void OnMouseCursor(MouseCursor* cursor) override; void OnMouseCursor(MouseCursor* cursor) override;

View File

@ -78,15 +78,17 @@ class FakeScreenCapturer : public DesktopCapturer {
void Start(Callback* callback) override { callback_ = callback; } void Start(Callback* callback) override { callback_ = callback; }
void Capture(const DesktopRegion& region) override { void Capture(const DesktopRegion& region) override {
callback_->OnCaptureCompleted(next_frame_.release()); callback_->OnCaptureResult(
next_frame_ ? Result::SUCCESS : Result::ERROR_TEMPORARY,
std::move(next_frame_));
} }
void SetNextFrame(DesktopFrame* next_frame) { void SetNextFrame(std::unique_ptr<DesktopFrame> next_frame) {
next_frame_.reset(next_frame); next_frame_ = std::move(next_frame);
} }
private: private:
Callback* callback_; Callback* callback_ = nullptr;
std::unique_ptr<DesktopFrame> next_frame_; std::unique_ptr<DesktopFrame> next_frame_;
}; };
@ -165,11 +167,13 @@ class DesktopAndCursorComposerTest : public testing::Test,
DesktopAndCursorComposerTest() DesktopAndCursorComposerTest()
: fake_screen_(new FakeScreenCapturer()), : fake_screen_(new FakeScreenCapturer()),
fake_cursor_(new FakeMouseMonitor()), fake_cursor_(new FakeMouseMonitor()),
blender_(fake_screen_, fake_cursor_) { blender_(fake_screen_, fake_cursor_) {}
}
// DesktopCapturer::Callback interface // DesktopCapturer::Callback interface
void OnCaptureCompleted(DesktopFrame* frame) override { frame_.reset(frame); } void OnCaptureResult(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> frame) override {
frame_ = std::move(frame);
}
protected: protected:
// Owned by |blender_|. // Owned by |blender_|.
@ -187,7 +191,7 @@ TEST_F(DesktopAndCursorComposerTest, Error) {
fake_cursor_->SetHotspot(DesktopVector()); fake_cursor_->SetHotspot(DesktopVector());
fake_cursor_->SetState(MouseCursorMonitor::INSIDE, DesktopVector()); fake_cursor_->SetState(MouseCursorMonitor::INSIDE, DesktopVector());
fake_screen_->SetNextFrame(NULL); fake_screen_->SetNextFrame(nullptr);
blender_.Capture(DesktopRegion()); blender_.Capture(DesktopRegion());

View File

@ -15,24 +15,45 @@
#include <memory> #include <memory>
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/desktop_capture_types.h" #include "webrtc/modules/desktop_capture/desktop_capture_types.h"
#include "webrtc/modules/desktop_capture/shared_memory.h" #include "webrtc/modules/desktop_capture/shared_memory.h"
namespace webrtc { namespace webrtc {
class DesktopFrame; class DesktopFrame;
class DesktopRegion;
// Abstract interface for screen and window capturers. // Abstract interface for screen and window capturers.
class DesktopCapturer { class DesktopCapturer {
public: public:
enum class Result {
// The frame was captured successfully.
SUCCESS,
// There was a temporary error. The caller should continue calling
// Capture(), in the expectation that it will eventually recover.
ERROR_TEMPORARY,
// Capture has failed and will keep failing if the caller tries calling
// Capture() again.
ERROR_PERMANENT,
};
// Interface that must be implemented by the DesktopCapturer consumers. // Interface that must be implemented by the DesktopCapturer consumers.
class Callback { class Callback {
public: public:
// Called after a frame has been captured. Handler must take ownership of // Called after a frame has been captured. |frame| is not nullptr if and
// |frame|. If capture has failed for any reason |frame| is set to NULL // only if |result| is SUCCESS.
// (e.g. the window has been closed). virtual void OnCaptureResult(Result result,
virtual void OnCaptureCompleted(DesktopFrame* frame) = 0; std::unique_ptr<DesktopFrame> frame) {
OnCaptureCompleted(frame.release());
}
// Deprecated version of the method above that uses raw pointer instead of
// std::unique_ptr<>.
// TODO(sergeyu): Remove this method and make OnCaptureResult() pure
// virtual. crbug.com/webrtc/5950
virtual void OnCaptureCompleted(DesktopFrame* frame) { delete frame; };
protected: protected:
virtual ~Callback() {} virtual ~Callback() {}

View File

@ -30,7 +30,7 @@ DesktopFrameWin::~DesktopFrameWin() {
} }
// static // static
DesktopFrameWin* DesktopFrameWin::Create( std::unique_ptr<DesktopFrameWin> DesktopFrameWin::Create(
DesktopSize size, DesktopSize size,
SharedMemoryFactory* shared_memory_factory, SharedMemoryFactory* shared_memory_factory,
HDC hdc) { HDC hdc) {
@ -60,9 +60,9 @@ DesktopFrameWin* DesktopFrameWin::Create(
return nullptr; return nullptr;
} }
return new DesktopFrameWin(size, bytes_per_row, return std::unique_ptr<DesktopFrameWin>(
reinterpret_cast<uint8_t*>(data), new DesktopFrameWin(size, bytes_per_row, reinterpret_cast<uint8_t*>(data),
std::move(shared_memory), bitmap); std::move(shared_memory), bitmap));
} }
} // namespace webrtc } // namespace webrtc

View File

@ -26,9 +26,9 @@ namespace webrtc {
class DesktopFrameWin : public DesktopFrame { class DesktopFrameWin : public DesktopFrame {
public: public:
virtual ~DesktopFrameWin(); virtual ~DesktopFrameWin();
static DesktopFrameWin* Create(DesktopSize size,
SharedMemoryFactory* shared_memory_factory, static std::unique_ptr<DesktopFrameWin>
HDC hdc); Create(DesktopSize size, SharedMemoryFactory* shared_memory_factory, HDC hdc);
HBITMAP bitmap() { return bitmap_; } HBITMAP bitmap() { return bitmap_; }

View File

@ -49,8 +49,8 @@ class ScreenCaptureFrameQueue {
// Replaces the current frame with a new one allocated by the caller. The // Replaces the current frame with a new one allocated by the caller. The
// existing frame (if any) is destroyed. Takes ownership of |frame|. // existing frame (if any) is destroyed. Takes ownership of |frame|.
void ReplaceCurrentFrame(FrameType* frame) { void ReplaceCurrentFrame(std::unique_ptr<FrameType> frame) {
frames_[current_].reset(frame); frames_[current_] = std::move(frame);
} }
// Marks all frames obsolete and resets the previous frame pointer. No // Marks all frames obsolete and resets the previous frame pointer. No

View File

@ -96,15 +96,15 @@ void CopyRect(const uint8_t* src_plane,
// caller should release the returned CFArrayRef. // caller should release the returned CFArrayRef.
CFArrayRef CreateWindowListWithExclusion(CGWindowID window_to_exclude) { CFArrayRef CreateWindowListWithExclusion(CGWindowID window_to_exclude) {
if (!window_to_exclude) if (!window_to_exclude)
return NULL; return nullptr;
CFArrayRef all_windows = CGWindowListCopyWindowInfo( CFArrayRef all_windows = CGWindowListCopyWindowInfo(
kCGWindowListOptionOnScreenOnly, kCGNullWindowID); kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
if (!all_windows) if (!all_windows)
return NULL; return nullptr;
CFMutableArrayRef returned_array = CFArrayCreateMutable( CFMutableArrayRef returned_array =
NULL, CFArrayGetCount(all_windows), NULL); CFArrayCreateMutable(nullptr, CFArrayGetCount(all_windows), nullptr);
bool found = false; bool found = false;
for (CFIndex i = 0; i < CFArrayGetCount(all_windows); ++i) { for (CFIndex i = 0; i < CFArrayGetCount(all_windows); ++i) {
@ -126,7 +126,7 @@ CFArrayRef CreateWindowListWithExclusion(CGWindowID window_to_exclude) {
if (!found) { if (!found) {
CFRelease(returned_array); CFRelease(returned_array);
returned_array = NULL; returned_array = nullptr;
} }
return returned_array; return returned_array;
} }
@ -143,7 +143,7 @@ DesktopRect GetExcludedWindowPixelBounds(CGWindowID window,
ids[0] = window; ids[0] = window;
CFArrayRef window_id_array = CFArrayRef window_id_array =
CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL); CFArrayCreate(nullptr, reinterpret_cast<const void**>(&ids), 1, nullptr);
CFArrayRef window_array = CFArrayRef window_array =
CGWindowListCreateDescriptionFromArray(window_id_array); CGWindowListCreateDescriptionFromArray(window_id_array);
@ -229,11 +229,11 @@ class ScreenCapturerMac : public ScreenCapturer {
void *user_parameter); void *user_parameter);
void ReleaseBuffers(); void ReleaseBuffers();
DesktopFrame* CreateFrame(); std::unique_ptr<DesktopFrame> CreateFrame();
Callback* callback_; Callback* callback_ = nullptr;
CGLContextObj cgl_context_; CGLContextObj cgl_context_ = nullptr;
ScopedPixelBufferObject pixel_buffer_object_; ScopedPixelBufferObject pixel_buffer_object_;
// Queue of the frames buffers. // Queue of the frames buffers.
@ -244,13 +244,13 @@ class ScreenCapturerMac : public ScreenCapturer {
// Currently selected display, or 0 if the full desktop is selected. On OS X // Currently selected display, or 0 if the full desktop is selected. On OS X
// 10.6 and before, this is always 0. // 10.6 and before, this is always 0.
CGDirectDisplayID current_display_; CGDirectDisplayID current_display_ = 0;
// The physical pixel bounds of the current screen. // The physical pixel bounds of the current screen.
DesktopRect screen_pixel_bounds_; DesktopRect screen_pixel_bounds_;
// The dip to physical pixel scale of the current screen. // The dip to physical pixel scale of the current screen.
float dip_to_pixel_scale_; float dip_to_pixel_scale_ = 1.0f;
// A thread-safe list of invalid rectangles, and the size of the most // A thread-safe list of invalid rectangles, and the size of the most
// recently captured screen. // recently captured screen.
@ -263,20 +263,20 @@ class ScreenCapturerMac : public ScreenCapturer {
rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor_; rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor_;
// Power management assertion to prevent the screen from sleeping. // Power management assertion to prevent the screen from sleeping.
IOPMAssertionID power_assertion_id_display_; IOPMAssertionID power_assertion_id_display_ = kIOPMNullAssertionID;
// Power management assertion to indicate that the user is active. // Power management assertion to indicate that the user is active.
IOPMAssertionID power_assertion_id_user_; IOPMAssertionID power_assertion_id_user_ = kIOPMNullAssertionID;
// Dynamically link to deprecated APIs for Mac OS X 10.6 support. // Dynamically link to deprecated APIs for Mac OS X 10.6 support.
void* app_services_library_; void* app_services_library_ = nullptr;
CGDisplayBaseAddressFunc cg_display_base_address_; CGDisplayBaseAddressFunc cg_display_base_address_ = nullptr;
CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; CGDisplayBytesPerRowFunc cg_display_bytes_per_row_ = nullptr;
CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_ = nullptr;
void* opengl_library_; void* opengl_library_ = nullptr;
CGLSetFullScreenFunc cgl_set_full_screen_; CGLSetFullScreenFunc cgl_set_full_screen_ = nullptr;
CGWindowID excluded_window_; CGWindowID excluded_window_ = 0;
RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac); RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac);
}; };
@ -285,16 +285,16 @@ class ScreenCapturerMac : public ScreenCapturer {
// stride. // stride.
class InvertedDesktopFrame : public DesktopFrame { class InvertedDesktopFrame : public DesktopFrame {
public: public:
// Takes ownership of |frame|. InvertedDesktopFrame(std::unique_ptr<DesktopFrame> frame)
InvertedDesktopFrame(DesktopFrame* frame)
: DesktopFrame( : DesktopFrame(
frame->size(), -frame->stride(), frame->size(),
-frame->stride(),
frame->data() + (frame->size().height() - 1) * frame->stride(), frame->data() + (frame->size().height() - 1) * frame->stride(),
frame->shared_memory()), frame->shared_memory()) {
original_frame_(frame) { original_frame_ = std::move(frame);
set_dpi(frame->dpi()); set_dpi(original_frame_->dpi());
set_capture_time_ms(frame->capture_time_ms()); set_capture_time_ms(original_frame_->capture_time_ms());
mutable_updated_region()->Swap(frame->mutable_updated_region()); mutable_updated_region()->Swap(original_frame_->mutable_updated_region());
} }
virtual ~InvertedDesktopFrame() {} virtual ~InvertedDesktopFrame() {}
@ -306,21 +306,7 @@ class InvertedDesktopFrame : public DesktopFrame {
ScreenCapturerMac::ScreenCapturerMac( ScreenCapturerMac::ScreenCapturerMac(
rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor) rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor)
: callback_(NULL), : desktop_config_monitor_(desktop_config_monitor) {}
cgl_context_(NULL),
current_display_(0),
dip_to_pixel_scale_(1.0f),
desktop_config_monitor_(desktop_config_monitor),
power_assertion_id_display_(kIOPMNullAssertionID),
power_assertion_id_user_(kIOPMNullAssertionID),
app_services_library_(NULL),
cg_display_base_address_(NULL),
cg_display_bytes_per_row_(NULL),
cg_display_bits_per_pixel_(NULL),
opengl_library_(NULL),
cgl_set_full_screen_(NULL),
excluded_window_(0) {
}
ScreenCapturerMac::~ScreenCapturerMac() { ScreenCapturerMac::~ScreenCapturerMac() {
if (power_assertion_id_display_ != kIOPMNullAssertionID) { if (power_assertion_id_display_ != kIOPMNullAssertionID) {
@ -353,7 +339,7 @@ void ScreenCapturerMac::ReleaseBuffers() {
if (cgl_context_) { if (cgl_context_) {
pixel_buffer_object_.Release(); pixel_buffer_object_.Release();
CGLDestroyContext(cgl_context_); CGLDestroyContext(cgl_context_);
cgl_context_ = NULL; cgl_context_ = nullptr;
} }
// The buffers might be in use by the encoder, so don't delete them here. // The buffers might be in use by the encoder, so don't delete them here.
// Instead, mark them as "needs update"; next time the buffers are used by // Instead, mark them as "needs update"; next time the buffers are used by
@ -419,7 +405,7 @@ void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) {
// APIS currently crash on 10.6.8 if there is no monitor attached. // APIS currently crash on 10.6.8 if there is no monitor attached.
if (!CgBlitPostLion(*current_frame, region)) { if (!CgBlitPostLion(*current_frame, region)) {
desktop_config_monitor_->Unlock(); desktop_config_monitor_->Unlock();
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
} else if (cgl_context_) { } else if (cgl_context_) {
@ -435,11 +421,11 @@ void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) {
CgBlitPreLion(*current_frame, region); CgBlitPreLion(*current_frame, region);
} }
DesktopFrame* new_frame = queue_.current_frame()->Share(); std::unique_ptr<DesktopFrame> new_frame = queue_.current_frame()->Share();
*new_frame->mutable_updated_region() = region; *new_frame->mutable_updated_region() = region;
if (flip) if (flip)
new_frame = new InvertedDesktopFrame(new_frame); new_frame.reset(new InvertedDesktopFrame(std::move(new_frame)));
helper_.set_size_most_recent(new_frame->size()); helper_.set_size_most_recent(new_frame->size());
@ -447,10 +433,9 @@ void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) {
// and accessing display structures. // and accessing display structures.
desktop_config_monitor_->Unlock(); desktop_config_monitor_->Unlock();
new_frame->set_capture_time_ms( new_frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) /
(rtc::TimeNanos() - capture_start_time_nanos) /
rtc::kNumNanosecsPerMillisec); rtc::kNumNanosecsPerMillisec);
callback_->OnCaptureCompleted(new_frame); callback_->OnCaptureResult(Result::SUCCESS, std::move(new_frame));
} }
void ScreenCapturerMac::SetExcludedWindow(WindowId window) { void ScreenCapturerMac::SetExcludedWindow(WindowId window) {
@ -534,7 +519,7 @@ void ScreenCapturerMac::GlBlitFast(const DesktopFrame& frame,
GL_UNSIGNED_BYTE, 0); GL_UNSIGNED_BYTE, 0);
GLubyte* ptr = static_cast<GLubyte*>( GLubyte* ptr = static_cast<GLubyte*>(
glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB)); glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB));
if (ptr == NULL) { if (!ptr) {
// If the buffer can't be mapped, assume that it's no longer valid and // If the buffer can't be mapped, assume that it's no longer valid and
// release it. // release it.
pixel_buffer_object_.Release(); pixel_buffer_object_.Release();
@ -642,8 +627,7 @@ bool ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame,
// TODO(wez): Get rid of this as per crbug.com/145064, or implement // TODO(wez): Get rid of this as per crbug.com/145064, or implement
// crbug.com/92354. // crbug.com/92354.
if (queue_.previous_frame()) { if (queue_.previous_frame()) {
memcpy(frame.data(), memcpy(frame.data(), queue_.previous_frame()->data(),
queue_.previous_frame()->data(),
frame.stride() * frame.size().height()); frame.stride() * frame.size().height());
} }
@ -692,7 +676,7 @@ bool ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame,
copy_region.Translate(-display_bounds.left(), -display_bounds.top()); copy_region.Translate(-display_bounds.left(), -display_bounds.top());
DesktopRect excluded_window_bounds; DesktopRect excluded_window_bounds;
CGImageRef excluded_image = NULL; CGImageRef excluded_image = nullptr;
if (excluded_window_ && window_list) { if (excluded_window_ && window_list) {
// Get the region of the excluded window relative the primary display. // Get the region of the excluded window relative the primary display.
excluded_window_bounds = GetExcludedWindowPixelBounds( excluded_window_bounds = GetExcludedWindowPixelBounds(
@ -710,7 +694,7 @@ bool ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame,
// Create an image containing a snapshot of the display. // Create an image containing a snapshot of the display.
CGImageRef image = CGDisplayCreateImage(display_config.id); CGImageRef image = CGDisplayCreateImage(display_config.id);
if (image == NULL) { if (!image) {
if (excluded_image) if (excluded_image)
CFRelease(excluded_image); CFRelease(excluded_image);
continue; continue;
@ -874,13 +858,13 @@ void ScreenCapturerMac::ScreenConfigurationChanged() {
(CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice), (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice),
(CGLPixelFormatAttribute)0 (CGLPixelFormatAttribute)0
}; };
CGLPixelFormatObj pixel_format = NULL; CGLPixelFormatObj pixel_format = nullptr;
GLint matching_pixel_format_count = 0; GLint matching_pixel_format_count = 0;
CGLError err = CGLChoosePixelFormat(attributes, CGLError err = CGLChoosePixelFormat(attributes,
&pixel_format, &pixel_format,
&matching_pixel_format_count); &matching_pixel_format_count);
assert(err == kCGLNoError); assert(err == kCGLNoError);
err = CGLCreateContext(pixel_format, NULL, &cgl_context_); err = CGLCreateContext(pixel_format, nullptr, &cgl_context_);
assert(err == kCGLNoError); assert(err == kCGLNoError);
CGLDestroyPixelFormat(pixel_format); CGLDestroyPixelFormat(pixel_format);
(*cgl_set_full_screen_)(cgl_context_); (*cgl_set_full_screen_)(cgl_context_);
@ -969,13 +953,12 @@ void ScreenCapturerMac::ScreenUpdateMoveCallback(
capturer->ScreenUpdateMove(delta, count, rect_array); capturer->ScreenUpdateMove(delta, count, rect_array);
} }
DesktopFrame* ScreenCapturerMac::CreateFrame() { std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() {
std::unique_ptr<DesktopFrame> frame( std::unique_ptr<DesktopFrame> frame(
new BasicDesktopFrame(screen_pixel_bounds_.size())); new BasicDesktopFrame(screen_pixel_bounds_.size()));
frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_, frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_,
kStandardDPI * dip_to_pixel_scale_)); kStandardDPI * dip_to_pixel_scale_));
return frame.release(); return frame;
} }
} // namespace } // namespace
@ -983,7 +966,7 @@ DesktopFrame* ScreenCapturerMac::CreateFrame() {
// static // static
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
if (!options.configuration_monitor()) if (!options.configuration_monitor())
return NULL; return nullptr;
std::unique_ptr<ScreenCapturerMac> capturer( std::unique_ptr<ScreenCapturerMac> capturer(
new ScreenCapturerMac(options.configuration_monitor())); new ScreenCapturerMac(options.configuration_monitor()));

View File

@ -32,11 +32,13 @@ namespace webrtc {
class ScreenCapturerMacTest : public testing::Test { class ScreenCapturerMacTest : public testing::Test {
public: public:
// Verifies that the whole screen is initially dirty. // Verifies that the whole screen is initially dirty.
void CaptureDoneCallback1(DesktopFrame* frame); void CaptureDoneCallback1(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame>* frame);
// Verifies that a rectangle explicitly marked as dirty is propagated // Verifies that a rectangle explicitly marked as dirty is propagated
// correctly. // correctly.
void CaptureDoneCallback2(DesktopFrame* frame); void CaptureDoneCallback2(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame>* frame);
protected: protected:
void SetUp() override { void SetUp() override {
@ -49,37 +51,40 @@ class ScreenCapturerMacTest : public testing::Test {
}; };
void ScreenCapturerMacTest::CaptureDoneCallback1( void ScreenCapturerMacTest::CaptureDoneCallback1(
DesktopFrame* frame) { DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> owned_frame(frame); std::unique_ptr<DesktopFrame>* frame) {
EXPECT_EQ(result, DesktopCapturer::Result::SUCCESS);
MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent( MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent(
MacDesktopConfiguration::BottomLeftOrigin); MacDesktopConfiguration::BottomLeftOrigin);
// Verify that the region contains full frame. // Verify that the region contains full frame.
DesktopRegion::Iterator it(frame->updated_region()); DesktopRegion::Iterator it((*frame)->updated_region());
EXPECT_TRUE(!it.IsAtEnd() && it.rect().equals(config.pixel_bounds)); EXPECT_TRUE(!it.IsAtEnd() && it.rect().equals(config.pixel_bounds));
} }
void ScreenCapturerMacTest::CaptureDoneCallback2( void ScreenCapturerMacTest::CaptureDoneCallback2(
DesktopFrame* frame) { DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> owned_frame(frame); std::unique_ptr<DesktopFrame>* frame) {
EXPECT_EQ(result, DesktopCapturer::Result::SUCCESS);
MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent( MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent(
MacDesktopConfiguration::BottomLeftOrigin); MacDesktopConfiguration::BottomLeftOrigin);
int width = config.pixel_bounds.width(); int width = config.pixel_bounds.width();
int height = config.pixel_bounds.height(); int height = config.pixel_bounds.height();
EXPECT_EQ(width, frame->size().width()); EXPECT_EQ(width, (*frame)->size().width());
EXPECT_EQ(height, frame->size().height()); EXPECT_EQ(height, (*frame)->size().height());
EXPECT_TRUE(frame->data() != NULL); EXPECT_TRUE((*frame)->data() != NULL);
// Depending on the capture method, the screen may be flipped or not, so // Depending on the capture method, the screen may be flipped or not, so
// the stride may be positive or negative. // the stride may be positive or negative.
EXPECT_EQ(static_cast<int>(sizeof(uint32_t) * width), EXPECT_EQ(static_cast<int>(sizeof(uint32_t) * width),
abs(frame->stride())); abs((*frame)->stride()));
} }
TEST_F(ScreenCapturerMacTest, Capture) { TEST_F(ScreenCapturerMacTest, Capture) {
EXPECT_CALL(callback_, OnCaptureCompleted(_)) EXPECT_CALL(callback_,
OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
.Times(2) .Times(2)
.WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback1)) .WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback1))
.WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback2)); .WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback2));

View File

@ -36,7 +36,13 @@ class MockScreenCapturerCallback : public ScreenCapturer::Callback {
MockScreenCapturerCallback() {} MockScreenCapturerCallback() {}
virtual ~MockScreenCapturerCallback() {} virtual ~MockScreenCapturerCallback() {}
MOCK_METHOD1(OnCaptureCompleted, void(DesktopFrame*)); MOCK_METHOD2(OnCaptureResultPtr,
void(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame>* frame));
void OnCaptureResult(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> frame) override {
OnCaptureResultPtr(result, &frame);
}
private: private:
RTC_DISALLOW_COPY_AND_ASSIGN(MockScreenCapturerCallback); RTC_DISALLOW_COPY_AND_ASSIGN(MockScreenCapturerCallback);

View File

@ -23,7 +23,6 @@
using ::testing::_; using ::testing::_;
using ::testing::AnyNumber; using ::testing::AnyNumber;
using ::testing::Return; using ::testing::Return;
using ::testing::SaveArg;
const int kTestSharedMemoryId = 123; const int kTestSharedMemoryId = 123;
@ -69,6 +68,10 @@ class FakeSharedMemoryFactory : public SharedMemoryFactory {
RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory); RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory);
}; };
ACTION_P(SaveUniquePtrArg, dest) {
*dest = std::move(*arg1);
}
TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) { TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) {
webrtc::ScreenCapturer::ScreenList screens; webrtc::ScreenCapturer::ScreenList screens;
EXPECT_TRUE(capturer_->GetScreenList(&screens)); EXPECT_TRUE(capturer_->GetScreenList(&screens));
@ -84,9 +87,10 @@ TEST_F(ScreenCapturerTest, StartCapturer) {
TEST_F(ScreenCapturerTest, Capture) { TEST_F(ScreenCapturerTest, Capture) {
// Assume that Start() treats the screen as invalid initially. // Assume that Start() treats the screen as invalid initially.
DesktopFrame* frame = NULL; std::unique_ptr<DesktopFrame> frame;
EXPECT_CALL(callback_, OnCaptureCompleted(_)) EXPECT_CALL(callback_,
.WillOnce(SaveArg<0>(&frame)); OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
.WillOnce(SaveUniquePtrArg(&frame));
capturer_->Start(&callback_); capturer_->Start(&callback_);
capturer_->Capture(DesktopRegion()); capturer_->Capture(DesktopRegion());
@ -105,16 +109,15 @@ TEST_F(ScreenCapturerTest, Capture) {
EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size()))); EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size())));
it.Advance(); it.Advance();
EXPECT_TRUE(it.IsAtEnd()); EXPECT_TRUE(it.IsAtEnd());
delete frame;
} }
#if defined(WEBRTC_WIN) #if defined(WEBRTC_WIN)
TEST_F(ScreenCapturerTest, UseSharedBuffers) { TEST_F(ScreenCapturerTest, UseSharedBuffers) {
DesktopFrame* frame = NULL; std::unique_ptr<DesktopFrame> frame;
EXPECT_CALL(callback_, OnCaptureCompleted(_)) EXPECT_CALL(callback_,
.WillOnce(SaveArg<0>(&frame)); OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
.WillOnce(SaveUniquePtrArg(&frame));
capturer_->Start(&callback_); capturer_->Start(&callback_);
capturer_->SetSharedMemoryFactory( capturer_->SetSharedMemoryFactory(
@ -124,8 +127,6 @@ TEST_F(ScreenCapturerTest, UseSharedBuffers) {
ASSERT_TRUE(frame); ASSERT_TRUE(frame);
ASSERT_TRUE(frame->shared_memory()); ASSERT_TRUE(frame->shared_memory());
EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
delete frame;
} }
TEST_F(ScreenCapturerTest, UseMagnifier) { TEST_F(ScreenCapturerTest, UseMagnifier) {
@ -133,13 +134,14 @@ TEST_F(ScreenCapturerTest, UseMagnifier) {
options.set_allow_use_magnification_api(true); options.set_allow_use_magnification_api(true);
capturer_.reset(ScreenCapturer::Create(options)); capturer_.reset(ScreenCapturer::Create(options));
DesktopFrame* frame = NULL; std::unique_ptr<DesktopFrame> frame;
EXPECT_CALL(callback_, OnCaptureCompleted(_)).WillOnce(SaveArg<0>(&frame)); EXPECT_CALL(callback_,
OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
.WillOnce(SaveUniquePtrArg(&frame));
capturer_->Start(&callback_); capturer_->Start(&callback_);
capturer_->Capture(DesktopRegion()); capturer_->Capture(DesktopRegion());
ASSERT_TRUE(frame); ASSERT_TRUE(frame);
delete frame;
} }
#endif // defined(WEBRTC_WIN) #endif // defined(WEBRTC_WIN)

View File

@ -66,7 +66,7 @@ class ScreenCapturerLinux : public ScreenCapturer,
// from HandleXEvent(). In the non-DAMAGE case, this captures the // from HandleXEvent(). In the non-DAMAGE case, this captures the
// whole screen, then calculates some invalid rectangles that include any // whole screen, then calculates some invalid rectangles that include any
// differences between this and the previous capture. // differences between this and the previous capture.
DesktopFrame* CaptureScreen(); std::unique_ptr<DesktopFrame> CaptureScreen();
// Called when the screen configuration is changed. // Called when the screen configuration is changed.
void ScreenConfigurationChanged(); void ScreenConfigurationChanged();
@ -82,23 +82,23 @@ class ScreenCapturerLinux : public ScreenCapturer,
DesktopCaptureOptions options_; DesktopCaptureOptions options_;
Callback* callback_; Callback* callback_ = nullptr;
// X11 graphics context. // X11 graphics context.
GC gc_; GC gc_ = nullptr;
Window root_window_; Window root_window_ = BadValue;
// XFixes. // XFixes.
bool has_xfixes_; bool has_xfixes_ = false;
int xfixes_event_base_; int xfixes_event_base_ = -1;
int xfixes_error_base_; int xfixes_error_base_ = -1;
// XDamage information. // XDamage information.
bool use_damage_; bool use_damage_ = false;
Damage damage_handle_; Damage damage_handle_ = 0;
int damage_event_base_; int damage_event_base_ = -1;
int damage_error_base_; int damage_error_base_ = -1;
XserverRegion damage_region_; XserverRegion damage_region_ = 0;
// Access to the X Server's pixel buffer. // Access to the X Server's pixel buffer.
XServerPixelBuffer x_server_pixel_buffer_; XServerPixelBuffer x_server_pixel_buffer_;
@ -120,18 +120,7 @@ class ScreenCapturerLinux : public ScreenCapturer,
RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux);
}; };
ScreenCapturerLinux::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); helper_.SetLogGridSize(4);
} }
@ -249,7 +238,7 @@ void ScreenCapturerLinux::Capture(const DesktopRegion& region) {
// in a good shape. // in a good shape.
if (!x_server_pixel_buffer_.is_initialized()) { if (!x_server_pixel_buffer_.is_initialized()) {
// We failed to initialize pixel buffer. // We failed to initialize pixel buffer.
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
@ -257,29 +246,26 @@ void ScreenCapturerLinux::Capture(const DesktopRegion& region) {
// Note that we can't reallocate other buffers at this point, since the caller // Note that we can't reallocate other buffers at this point, since the caller
// may still be reading from them. // may still be reading from them.
if (!queue_.current_frame()) { if (!queue_.current_frame()) {
std::unique_ptr<DesktopFrame> frame( queue_.ReplaceCurrentFrame(
new BasicDesktopFrame(x_server_pixel_buffer_.window_size())); SharedDesktopFrame::Wrap(std::unique_ptr<DesktopFrame>(
queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(frame.release())); new BasicDesktopFrame(x_server_pixel_buffer_.window_size()))));
} }
// Refresh the Differ helper used by CaptureFrame(), if needed. // Refresh the Differ helper used by CaptureFrame(), if needed.
DesktopFrame* frame = queue_.current_frame(); DesktopFrame* frame = queue_.current_frame();
if (!use_damage_ && ( if (!use_damage_ &&
!differ_.get() || (!differ_ || (differ_->width() != frame->size().width()) ||
(differ_->width() != frame->size().width()) ||
(differ_->height() != frame->size().height()) || (differ_->height() != frame->size().height()) ||
(differ_->bytes_per_row() != frame->stride()))) { (differ_->bytes_per_row() != frame->stride()))) {
differ_.reset(new Differ(frame->size().width(), frame->size().height(), differ_.reset(new Differ(frame->size().width(), frame->size().height(),
DesktopFrame::kBytesPerPixel, DesktopFrame::kBytesPerPixel, frame->stride()));
frame->stride()));
} }
DesktopFrame* result = CaptureScreen(); std::unique_ptr<DesktopFrame> result = CaptureScreen();
last_invalid_region_ = result->updated_region(); last_invalid_region_ = result->updated_region();
result->set_capture_time_ms( result->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) /
(rtc::TimeNanos() - capture_start_time_nanos) /
rtc::kNumNanosecsPerMillisec); rtc::kNumNanosecsPerMillisec);
callback_->OnCaptureCompleted(result); callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
} }
bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) {
@ -311,8 +297,8 @@ bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) {
return false; return false;
} }
DesktopFrame* ScreenCapturerLinux::CaptureScreen() { std::unique_ptr<DesktopFrame> ScreenCapturerLinux::CaptureScreen() {
DesktopFrame* frame = queue_.current_frame()->Share(); std::unique_ptr<SharedDesktopFrame> frame = queue_.current_frame()->Share();
assert(x_server_pixel_buffer_.window_size().equals(frame->size())); assert(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 // Pass the screen size to the helper, so it can clip the invalid region if it
@ -354,18 +340,18 @@ DesktopFrame* ScreenCapturerLinux::CaptureScreen() {
for (DesktopRegion::Iterator it(*updated_region); for (DesktopRegion::Iterator it(*updated_region);
!it.IsAtEnd(); it.Advance()) { !it.IsAtEnd(); it.Advance()) {
x_server_pixel_buffer_.CaptureRect(it.rect(), frame); x_server_pixel_buffer_.CaptureRect(it.rect(), frame.get());
} }
} else { } else {
// Doing full-screen polling, or this is the first capture after a // Doing full-screen polling, or this is the first capture after a
// screen-resolution change. In either case, need a full-screen capture. // screen-resolution change. In either case, need a full-screen capture.
DesktopRect screen_rect = DesktopRect::MakeSize(frame->size()); DesktopRect screen_rect = DesktopRect::MakeSize(frame->size());
x_server_pixel_buffer_.CaptureRect(screen_rect, frame); x_server_pixel_buffer_.CaptureRect(screen_rect, frame.get());
if (queue_.previous_frame()) { if (queue_.previous_frame()) {
// Full-screen polling, so calculate the invalid rects here, based on the // Full-screen polling, so calculate the invalid rects here, based on the
// changed pixels between current and previous buffers. // changed pixels between current and previous buffers.
RTC_DCHECK(differ_.get() != NULL); RTC_DCHECK(differ_);
RTC_DCHECK(queue_.previous_frame()->data()); RTC_DCHECK(queue_.previous_frame()->data());
differ_->CalcDirtyRegion(queue_.previous_frame()->data(), differ_->CalcDirtyRegion(queue_.previous_frame()->data(),
frame->data(), updated_region); frame->data(), updated_region);
@ -378,7 +364,7 @@ DesktopFrame* ScreenCapturerLinux::CaptureScreen() {
} }
} }
return frame; return std::move(frame);
} }
void ScreenCapturerLinux::ScreenConfigurationChanged() { void ScreenCapturerLinux::ScreenConfigurationChanged() {
@ -415,7 +401,7 @@ void ScreenCapturerLinux::SynchronizeFrame() {
void ScreenCapturerLinux::DeinitXlib() { void ScreenCapturerLinux::DeinitXlib() {
if (gc_) { if (gc_) {
XFreeGC(display(), gc_); XFreeGC(display(), gc_);
gc_ = NULL; gc_ = nullptr;
} }
x_server_pixel_buffer_.Release(); x_server_pixel_buffer_.Release();
@ -438,7 +424,7 @@ void ScreenCapturerLinux::DeinitXlib() {
// static // static
ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
if (!options.x_display()) if (!options.x_display())
return NULL; return nullptr;
std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
if (!capturer->Init(options)) if (!capturer->Init(options))

View File

@ -17,49 +17,25 @@
namespace webrtc { namespace webrtc {
class SharedDesktopFrame::Core {
public:
Core(DesktopFrame* frame) : frame_(frame) {}
DesktopFrame* frame() { return frame_.get(); }
bool HasOneRef() { return ref_count_.Value() == 1; }
virtual int32_t AddRef() {
return ++ref_count_;
}
virtual int32_t Release() {
int32_t ref_count;
ref_count = --ref_count_;
if (ref_count == 0)
delete this;
return ref_count;
}
private:
virtual ~Core() {}
Atomic32 ref_count_;
std::unique_ptr<DesktopFrame> frame_;
RTC_DISALLOW_COPY_AND_ASSIGN(Core);
};
SharedDesktopFrame::~SharedDesktopFrame() {} SharedDesktopFrame::~SharedDesktopFrame() {}
// static // static
std::unique_ptr<SharedDesktopFrame> SharedDesktopFrame::Wrap(
std::unique_ptr<DesktopFrame> desktop_frame) {
return std::unique_ptr<SharedDesktopFrame>(
new SharedDesktopFrame(new Core(desktop_frame.release())));
}
SharedDesktopFrame* SharedDesktopFrame::Wrap(DesktopFrame* desktop_frame) { SharedDesktopFrame* SharedDesktopFrame::Wrap(DesktopFrame* desktop_frame) {
rtc::scoped_refptr<Core> core(new Core(desktop_frame)); return Wrap(std::unique_ptr<DesktopFrame>(desktop_frame)).release();
return new SharedDesktopFrame(core);
} }
DesktopFrame* SharedDesktopFrame::GetUnderlyingFrame() { DesktopFrame* SharedDesktopFrame::GetUnderlyingFrame() {
return core_->frame(); return core_->get();
} }
SharedDesktopFrame* SharedDesktopFrame::Share() { std::unique_ptr<SharedDesktopFrame> SharedDesktopFrame::Share() {
SharedDesktopFrame* result = new SharedDesktopFrame(core_); std::unique_ptr<SharedDesktopFrame> result(new SharedDesktopFrame(core_));
result->set_dpi(dpi()); result->set_dpi(dpi());
result->set_capture_time_ms(capture_time_ms()); result->set_capture_time_ms(capture_time_ms());
*result->mutable_updated_region() = updated_region(); *result->mutable_updated_region() = updated_region();
@ -71,11 +47,10 @@ bool SharedDesktopFrame::IsShared() {
} }
SharedDesktopFrame::SharedDesktopFrame(rtc::scoped_refptr<Core> core) SharedDesktopFrame::SharedDesktopFrame(rtc::scoped_refptr<Core> core)
: DesktopFrame(core->frame()->size(), : DesktopFrame((*core)->size(),
core->frame()->stride(), (*core)->stride(),
core->frame()->data(), (*core)->data(),
core->frame()->shared_memory()), (*core)->shared_memory()),
core_(core) { core_(core) {}
}
} // namespace webrtc } // namespace webrtc

View File

@ -12,6 +12,7 @@
#define WEBRTC_MODULES_DESKTOP_CAPTURE_SHARED_DESKTOP_FRAME_H_ #define WEBRTC_MODULES_DESKTOP_CAPTURE_SHARED_DESKTOP_FRAME_H_
#include "webrtc/base/constructormagic.h" #include "webrtc/base/constructormagic.h"
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/modules/desktop_capture/desktop_frame.h" #include "webrtc/modules/desktop_capture/desktop_frame.h"
@ -23,20 +24,25 @@ class SharedDesktopFrame : public DesktopFrame {
public: public:
virtual ~SharedDesktopFrame(); virtual ~SharedDesktopFrame();
static std::unique_ptr<SharedDesktopFrame> Wrap(
std::unique_ptr<DesktopFrame> desktop_frame);
// Deprecated.
// TODO(sergeyu): remove this method.
static SharedDesktopFrame* Wrap(DesktopFrame* desktop_frame); static SharedDesktopFrame* Wrap(DesktopFrame* desktop_frame);
// Returns the underlying instance of DesktopFrame. // Returns the underlying instance of DesktopFrame.
DesktopFrame* GetUnderlyingFrame(); DesktopFrame* GetUnderlyingFrame();
// Creates a clone of this object. // Creates a clone of this object.
SharedDesktopFrame* Share(); std::unique_ptr<SharedDesktopFrame> Share();
// Checks if the frame is currently shared. If it returns false it's // Checks if the frame is currently shared. If it returns false it's
// guaranteed that there are no clones of the object. // guaranteed that there are no clones of the object.
bool IsShared(); bool IsShared();
private: private:
class Core; typedef rtc::RefCountedObject<std::unique_ptr<DesktopFrame>> Core;
SharedDesktopFrame(rtc::scoped_refptr<Core> core); SharedDesktopFrame(rtc::scoped_refptr<Core> core);

View File

@ -413,7 +413,14 @@ bool ScreenCapturerWinDirectx::DuplicateOutput() {
_com_error error = g_container->output1->DuplicateOutput( _com_error error = g_container->output1->DuplicateOutput(
static_cast<IUnknown*>(g_container->device), static_cast<IUnknown*>(g_container->device),
g_container->duplication.GetAddressOf()); g_container->duplication.GetAddressOf());
if (error.Error() == S_OK && g_container->duplication) { if (error.Error() != S_OK || !g_container->duplication) {
g_container->duplication.Reset();
LOG(LS_WARNING) << "Failed to duplicate output from IDXGIOutput1, error "
<< error.ErrorMessage() << ", with code "
<< error.Error();
return false;
}
memset(&g_container->duplication_desc, 0, sizeof(DXGI_OUTDUPL_DESC)); memset(&g_container->duplication_desc, 0, sizeof(DXGI_OUTDUPL_DESC));
g_container->duplication->GetDesc(&g_container->duplication_desc); g_container->duplication->GetDesc(&g_container->duplication_desc);
if (g_container->duplication_desc.ModeDesc.Format != if (g_container->duplication_desc.ModeDesc.Format !=
@ -425,16 +432,8 @@ bool ScreenCapturerWinDirectx::DuplicateOutput() {
<< g_container->duplication_desc.ModeDesc.Format; << g_container->duplication_desc.ModeDesc.Format;
return false; return false;
} }
return true;
} else {
// Make sure we have correct signal and duplicate the output next time.
g_container->duplication.Reset();
LOG(LS_WARNING) << "Failed to duplicate output from IDXGIOutput1, error "
<< error.ErrorMessage() << ", with code "
<< error.Error();
}
return false; return true;
} }
bool ScreenCapturerWinDirectx::ForceDuplicateOutput() { bool ScreenCapturerWinDirectx::ForceDuplicateOutput() {
@ -458,8 +457,8 @@ ScreenCapturerWinDirectx::ScreenCapturerWinDirectx(
// Texture instance won't change forever. // Texture instance won't change forever.
while (!surfaces_.current_frame()) { while (!surfaces_.current_frame()) {
surfaces_.ReplaceCurrentFrame( surfaces_.ReplaceCurrentFrame(std::unique_ptr<rtc::scoped_refptr<Texture>>(
new rtc::scoped_refptr<Texture>(new Texture())); new rtc::scoped_refptr<Texture>(new Texture())));
surfaces_.MoveToNextFrame(); surfaces_.MoveToNextFrame();
} }
} }
@ -593,9 +592,9 @@ std::unique_ptr<DesktopFrame> ScreenCapturerWinDirectx::ProcessFrame(
return std::unique_ptr<DesktopFrame>(); return std::unique_ptr<DesktopFrame>();
} }
frames_.ReplaceCurrentFrame( frames_.ReplaceCurrentFrame(
SharedDesktopFrame::Wrap(new_frame.release())); SharedDesktopFrame::Wrap(std::move(new_frame)));
} }
result.reset(frames_.current_frame()->Share()); result = frames_.current_frame()->Share();
std::unique_ptr<DesktopFrame> frame( std::unique_ptr<DesktopFrame> frame(
new DxgiDesktopFrame(*surfaces_.current_frame())); new DxgiDesktopFrame(*surfaces_.current_frame()));
@ -620,9 +619,8 @@ void ScreenCapturerWinDirectx::Capture(const DesktopRegion& region) {
RTC_DCHECK(callback_); RTC_DCHECK(callback_);
if (!g_container->duplication && !DuplicateOutput()) { if (!g_container->duplication && !DuplicateOutput()) {
// Receive a capture request when application is shutting down, or between // Failed to initialize desktop duplication.
// mode change. callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
callback_->OnCaptureCompleted(nullptr);
return; return;
} }
@ -656,7 +654,7 @@ void ScreenCapturerWinDirectx::Capture(const DesktopRegion& region) {
if (ForceDuplicateOutput()) { if (ForceDuplicateOutput()) {
EmitCurrentFrame(); EmitCurrentFrame();
} else { } else {
callback_->OnCaptureCompleted(nullptr); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
} }
return; return;
} }
@ -677,14 +675,14 @@ void ScreenCapturerWinDirectx::Capture(const DesktopRegion& region) {
g_container->duplication->ReleaseFrame(); g_container->duplication->ReleaseFrame();
} }
if (!result) { if (!result) {
callback_->OnCaptureCompleted(nullptr); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
result->set_capture_time_ms( result->set_capture_time_ms(
(rtc::TimeNanos() - capture_start_time_nanos) / (rtc::TimeNanos() - capture_start_time_nanos) /
rtc::kNumNanosecsPerMillisec); rtc::kNumNanosecsPerMillisec);
callback_->OnCaptureCompleted(result.release()); callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
} }
bool ScreenCapturerWinDirectx::GetScreenList(ScreenList* screens) { bool ScreenCapturerWinDirectx::GetScreenList(ScreenList* screens) {
@ -699,7 +697,7 @@ bool ScreenCapturerWinDirectx::SelectScreen(ScreenId id) {
void ScreenCapturerWinDirectx::EmitCurrentFrame() { void ScreenCapturerWinDirectx::EmitCurrentFrame() {
if (!surfaces_.current_frame()->get()->bits()) { if (!surfaces_.current_frame()->get()->bits()) {
// At the very begining, we have not captured any frames. // At the very begining, we have not captured any frames.
callback_->OnCaptureCompleted(nullptr); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
@ -708,12 +706,12 @@ void ScreenCapturerWinDirectx::EmitCurrentFrame() {
// queue. If there is not an existing frame (at the very begining), we can // queue. If there is not an existing frame (at the very begining), we can
// only return a nullptr. // only return a nullptr.
if (frames_.current_frame()) { if (frames_.current_frame()) {
std::unique_ptr<SharedDesktopFrame> frame( std::unique_ptr<SharedDesktopFrame> frame =
frames_.current_frame()->Share()); frames_.current_frame()->Share();
frame->mutable_updated_region()->Clear(); frame->mutable_updated_region()->Clear();
callback_->OnCaptureCompleted(frame.release()); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} else { } else {
callback_->OnCaptureCompleted(nullptr); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
} }
return; return;
} }
@ -722,7 +720,7 @@ void ScreenCapturerWinDirectx::EmitCurrentFrame() {
// queue. // queue.
std::unique_ptr<DesktopFrame> frame( std::unique_ptr<DesktopFrame> frame(
new DxgiDesktopFrame(*surfaces_.current_frame())); new DxgiDesktopFrame(*surfaces_.current_frame()));
callback_->OnCaptureCompleted(frame.release()); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} }
} // namespace webrtc } // namespace webrtc

View File

@ -82,9 +82,7 @@ class ScreenCapturerWinDirectx : public ScreenCapturer {
const char* stage); const char* stage);
// Processes one frame received from AcquireNextFrame function, returns a // Processes one frame received from AcquireNextFrame function, returns a
// nullptr if anything wrong, and Capture function will call // nullptr if anything wrong.
// callback_->OnCaptureCompleted(nullptr), otherwise
// callback_->OnCaptureCompleted(frame) will be called.
std::unique_ptr<DesktopFrame> ProcessFrame( std::unique_ptr<DesktopFrame> ProcessFrame(
const DXGI_OUTDUPL_FRAME_INFO& frame_info, const DXGI_OUTDUPL_FRAME_INFO& frame_info,
IDXGIResource* resource); IDXGIResource* resource);

View File

@ -39,14 +39,8 @@ const wchar_t kDwmapiLibraryName[] = L"dwmapi.dll";
} // namespace } // namespace
ScreenCapturerWinGdi::ScreenCapturerWinGdi(const DesktopCaptureOptions& options) ScreenCapturerWinGdi::ScreenCapturerWinGdi(
: callback_(NULL), const DesktopCaptureOptions& options) {
current_screen_id_(kFullDesktopScreenId),
desktop_dc_(NULL),
memory_dc_(NULL),
dwmapi_library_(NULL),
composition_func_(NULL),
set_thread_execution_state_failed_(false) {
if (options.disable_effects()) { if (options.disable_effects()) {
// Load dwmapi.dll dynamically since it is not available on XP. // Load dwmapi.dll dynamically since it is not available on XP.
if (!dwmapi_library_) if (!dwmapi_library_)
@ -97,7 +91,7 @@ void ScreenCapturerWinGdi::Capture(const DesktopRegion& region) {
PrepareCaptureResources(); PrepareCaptureResources();
if (!CaptureImage()) { if (!CaptureImage()) {
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
@ -130,7 +124,7 @@ void ScreenCapturerWinGdi::Capture(const DesktopRegion& region) {
helper_.set_size_most_recent(current_frame->size()); helper_.set_size_most_recent(current_frame->size());
// Emit the current frame. // Emit the current frame.
DesktopFrame* frame = queue_.current_frame()->Share(); std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share();
frame->set_dpi(DesktopVector( frame->set_dpi(DesktopVector(
GetDeviceCaps(desktop_dc_, LOGPIXELSX), GetDeviceCaps(desktop_dc_, LOGPIXELSX),
GetDeviceCaps(desktop_dc_, LOGPIXELSY))); GetDeviceCaps(desktop_dc_, LOGPIXELSY)));
@ -139,7 +133,7 @@ void ScreenCapturerWinGdi::Capture(const DesktopRegion& region) {
frame->set_capture_time_ms( frame->set_capture_time_ms(
(rtc::TimeNanos() - capture_start_time_nanos) / (rtc::TimeNanos() - capture_start_time_nanos) /
rtc::kNumNanosecsPerMillisec); rtc::kNumNanosecsPerMillisec);
callback_->OnCaptureCompleted(frame); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} }
bool ScreenCapturerWinGdi::GetScreenList(ScreenList* screens) { bool ScreenCapturerWinGdi::GetScreenList(ScreenList* screens) {
@ -170,16 +164,16 @@ void ScreenCapturerWinGdi::PrepareCaptureResources() {
// Switch to the desktop receiving user input if different from the current // Switch to the desktop receiving user input if different from the current
// one. // one.
std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop());
if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { if (input_desktop && !desktop_.IsSame(*input_desktop)) {
// Release GDI resources otherwise SetThreadDesktop will fail. // Release GDI resources otherwise SetThreadDesktop will fail.
if (desktop_dc_) { if (desktop_dc_) {
ReleaseDC(NULL, desktop_dc_); ReleaseDC(NULL, desktop_dc_);
desktop_dc_ = NULL; desktop_dc_ = nullptr;
} }
if (memory_dc_) { if (memory_dc_) {
DeleteDC(memory_dc_); DeleteDC(memory_dc_);
memory_dc_ = NULL; memory_dc_ = nullptr;
} }
// If SetThreadDesktop() fails, the thread is still assigned a desktop. // If SetThreadDesktop() fails, the thread is still assigned a desktop.
@ -188,7 +182,7 @@ void ScreenCapturerWinGdi::PrepareCaptureResources() {
// Re-assert our vote to disable Aero. // Re-assert our vote to disable Aero.
// See crbug.com/124018 and crbug.com/129906. // See crbug.com/124018 and crbug.com/129906.
if (composition_func_ != NULL) { if (composition_func_) {
(*composition_func_)(DWM_EC_DISABLECOMPOSITION); (*composition_func_)(DWM_EC_DISABLECOMPOSITION);
} }
} }
@ -203,20 +197,20 @@ void ScreenCapturerWinGdi::PrepareCaptureResources() {
if (!screen_rect.equals(desktop_dc_rect_)) { if (!screen_rect.equals(desktop_dc_rect_)) {
if (desktop_dc_) { if (desktop_dc_) {
ReleaseDC(NULL, desktop_dc_); ReleaseDC(NULL, desktop_dc_);
desktop_dc_ = NULL; desktop_dc_ = nullptr;
} }
if (memory_dc_) { if (memory_dc_) {
DeleteDC(memory_dc_); DeleteDC(memory_dc_);
memory_dc_ = NULL; memory_dc_ = nullptr;
} }
desktop_dc_rect_ = DesktopRect(); desktop_dc_rect_ = DesktopRect();
} }
if (desktop_dc_ == NULL) { if (!desktop_dc_) {
assert(memory_dc_ == NULL); assert(!memory_dc_);
// Create GDI device contexts to capture from the desktop into memory. // Create GDI device contexts to capture from the desktop into memory.
desktop_dc_ = GetDC(NULL); desktop_dc_ = GetDC(nullptr);
if (!desktop_dc_) if (!desktop_dc_)
abort(); abort();
memory_dc_ = CreateCompatibleDC(desktop_dc_); memory_dc_ = CreateCompatibleDC(desktop_dc_);
@ -244,14 +238,14 @@ bool ScreenCapturerWinGdi::CaptureImage() {
// may still be reading from them. // may still be reading from them.
if (!queue_.current_frame() || if (!queue_.current_frame() ||
!queue_.current_frame()->size().equals(screen_rect.size())) { !queue_.current_frame()->size().equals(screen_rect.size())) {
assert(desktop_dc_ != NULL); assert(desktop_dc_);
assert(memory_dc_ != NULL); assert(memory_dc_);
std::unique_ptr<DesktopFrame> buffer(DesktopFrameWin::Create( std::unique_ptr<DesktopFrame> buffer = DesktopFrameWin::Create(
size, shared_memory_factory_.get(), desktop_dc_)); size, shared_memory_factory_.get(), desktop_dc_);
if (!buffer) if (!buffer)
return false; return false;
queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(buffer.release())); queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(buffer)));
} }
// Select the target bitmap into the memory dc and copy the rect from desktop // Select the target bitmap into the memory dc and copy the rect from desktop
@ -259,11 +253,9 @@ bool ScreenCapturerWinGdi::CaptureImage() {
DesktopFrameWin* current = static_cast<DesktopFrameWin*>( DesktopFrameWin* current = static_cast<DesktopFrameWin*>(
queue_.current_frame()->GetUnderlyingFrame()); queue_.current_frame()->GetUnderlyingFrame());
HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap()); HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap());
if (previous_object != NULL) { if (previous_object) {
BitBlt(memory_dc_, BitBlt(memory_dc_, 0, 0, screen_rect.width(), screen_rect.height(),
0, 0, screen_rect.width(), screen_rect.height(), desktop_dc_, screen_rect.left(), screen_rect.top(),
desktop_dc_,
screen_rect.left(), screen_rect.top(),
SRCCOPY | CAPTUREBLT); SRCCOPY | CAPTUREBLT);
// Select back the previously selected object to that the device contect // Select back the previously selected object to that the device contect

View File

@ -56,9 +56,9 @@ class ScreenCapturerWinGdi : public ScreenCapturer {
// Capture the current cursor shape. // Capture the current cursor shape.
void CaptureCursor(); void CaptureCursor();
Callback* callback_; Callback* callback_ = nullptr;
std::unique_ptr<SharedMemoryFactory> shared_memory_factory_; std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
ScreenId current_screen_id_; ScreenId current_screen_id_ = kFullDesktopScreenId;
std::wstring current_device_key_; std::wstring current_device_key_;
// A thread-safe list of invalid rectangles, and the size of the most // A thread-safe list of invalid rectangles, and the size of the most
@ -68,8 +68,8 @@ class ScreenCapturerWinGdi : public ScreenCapturer {
ScopedThreadDesktop desktop_; ScopedThreadDesktop desktop_;
// GDI resources used for screen capture. // GDI resources used for screen capture.
HDC desktop_dc_; HDC desktop_dc_ = NULL;
HDC memory_dc_; HDC memory_dc_ = NULL;
// Queue of the frames buffers. // Queue of the frames buffers.
ScreenCaptureFrameQueue<SharedDesktopFrame> queue_; ScreenCaptureFrameQueue<SharedDesktopFrame> queue_;
@ -81,11 +81,11 @@ class ScreenCapturerWinGdi : public ScreenCapturer {
// Class to calculate the difference between two screen bitmaps. // Class to calculate the difference between two screen bitmaps.
std::unique_ptr<Differ> differ_; std::unique_ptr<Differ> differ_;
HMODULE dwmapi_library_; HMODULE dwmapi_library_ = NULL;
DwmEnableCompositionFunc composition_func_; DwmEnableCompositionFunc composition_func_ = nullptr;
// Used to suppress duplicate logging of SetThreadExecutionState errors. // Used to suppress duplicate logging of SetThreadExecutionState errors.
bool set_thread_execution_state_failed_; bool set_thread_execution_state_failed_ = false;
RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinGdi); RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinGdi);
}; };

View File

@ -39,23 +39,7 @@ Atomic32 ScreenCapturerWinMagnifier::tls_index_(TLS_OUT_OF_INDEXES);
ScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier( ScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier(
std::unique_ptr<ScreenCapturer> fallback_capturer) std::unique_ptr<ScreenCapturer> fallback_capturer)
: fallback_capturer_(std::move(fallback_capturer)), : fallback_capturer_(std::move(fallback_capturer)) {}
fallback_capturer_started_(false),
callback_(NULL),
current_screen_id_(kFullDesktopScreenId),
excluded_window_(NULL),
set_thread_execution_state_failed_(false),
desktop_dc_(NULL),
mag_lib_handle_(NULL),
mag_initialize_func_(NULL),
mag_uninitialize_func_(NULL),
set_window_source_func_(NULL),
set_window_filter_list_func_(NULL),
set_image_scaling_callback_func_(NULL),
host_window_(NULL),
magnifier_window_(NULL),
magnifier_initialized_(false),
magnifier_capture_succeeded_(true) {}
ScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() { ScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() {
// DestroyWindow must be called before MagUninitialize. magnifier_window_ is // DestroyWindow must be called before MagUninitialize. magnifier_window_ is
@ -162,15 +146,14 @@ void ScreenCapturerWinMagnifier::Capture(const DesktopRegion& region) {
helper_.set_size_most_recent(current_frame->size()); helper_.set_size_most_recent(current_frame->size());
// Emit the current frame. // Emit the current frame.
DesktopFrame* frame = queue_.current_frame()->Share(); std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share();
frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX), frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX),
GetDeviceCaps(desktop_dc_, LOGPIXELSY))); GetDeviceCaps(desktop_dc_, LOGPIXELSY)));
frame->mutable_updated_region()->Clear(); frame->mutable_updated_region()->Clear();
helper_.TakeInvalidRegion(frame->mutable_updated_region()); helper_.TakeInvalidRegion(frame->mutable_updated_region());
frame->set_capture_time_ms( frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) /
(rtc::TimeNanos() - capture_start_time_nanos) /
rtc::kNumNanosecsPerMillisec); rtc::kNumNanosecsPerMillisec);
callback_->OnCaptureCompleted(frame); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} }
bool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) { bool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) {
@ -204,11 +187,8 @@ bool ScreenCapturerWinMagnifier::CaptureImage(const DesktopRect& rect) {
// Set the magnifier control to cover the captured rect. The content of the // Set the magnifier control to cover the captured rect. The content of the
// magnifier control will be the captured image. // magnifier control will be the captured image.
BOOL result = SetWindowPos(magnifier_window_, BOOL result = SetWindowPos(magnifier_window_, NULL, rect.left(), rect.top(),
NULL, rect.width(), rect.height(), 0);
rect.left(), rect.top(),
rect.width(), rect.height(),
0);
if (!result) { if (!result) {
LOG_F(LS_WARNING) << "Failed to call SetWindowPos: " << GetLastError() LOG_F(LS_WARNING) << "Failed to call SetWindowPos: " << GetLastError()
<< ". Rect = {" << rect.left() << ", " << rect.top() << ". Rect = {" << rect.left() << ", " << rect.top()
@ -257,7 +237,7 @@ BOOL ScreenCapturerWinMagnifier::OnMagImageScalingCallback(
bool ScreenCapturerWinMagnifier::InitializeMagnifier() { bool ScreenCapturerWinMagnifier::InitializeMagnifier() {
assert(!magnifier_initialized_); assert(!magnifier_initialized_);
desktop_dc_ = GetDC(NULL); desktop_dc_ = GetDC(nullptr);
mag_lib_handle_ = LoadLibrary(L"Magnification.dll"); mag_lib_handle_ = LoadLibrary(L"Magnification.dll");
if (!mag_lib_handle_) if (!mag_lib_handle_)
@ -291,7 +271,7 @@ bool ScreenCapturerWinMagnifier::InitializeMagnifier() {
return false; return false;
} }
HMODULE hInstance = NULL; HMODULE hInstance = nullptr;
result = GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | result = GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<char*>(&DefWindowProc), reinterpret_cast<char*>(&DefWindowProc),
@ -309,22 +289,16 @@ bool ScreenCapturerWinMagnifier::InitializeMagnifier() {
wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = &DefWindowProc; wcex.lpfnWndProc = &DefWindowProc;
wcex.hInstance = hInstance; wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.lpszClassName = kMagnifierHostClass; wcex.lpszClassName = kMagnifierHostClass;
// Ignore the error which may happen when the class is already registered. // Ignore the error which may happen when the class is already registered.
RegisterClassEx(&wcex); RegisterClassEx(&wcex);
// Create the host window. // Create the host window.
host_window_ = CreateWindowEx(WS_EX_LAYERED, host_window_ =
kMagnifierHostClass, CreateWindowEx(WS_EX_LAYERED, kMagnifierHostClass, kHostWindowName, 0, 0,
kHostWindowName, 0, 0, 0, nullptr, nullptr, hInstance, nullptr);
0,
0, 0, 0, 0,
NULL,
NULL,
hInstance,
NULL);
if (!host_window_) { if (!host_window_) {
mag_uninitialize_func_(); mag_uninitialize_func_();
LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: "
@ -333,14 +307,9 @@ bool ScreenCapturerWinMagnifier::InitializeMagnifier() {
} }
// Create the magnifier control. // Create the magnifier control.
magnifier_window_ = CreateWindow(kMagnifierWindowClass, magnifier_window_ = CreateWindow(kMagnifierWindowClass, kMagnifierWindowName,
kMagnifierWindowName, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
WS_CHILD | WS_VISIBLE, host_window_, nullptr, hInstance, nullptr);
0, 0, 0, 0,
host_window_,
NULL,
hInstance,
NULL);
if (!magnifier_window_) { if (!magnifier_window_) {
mag_uninitialize_func_(); mag_uninitialize_func_();
LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: "
@ -433,7 +402,7 @@ void ScreenCapturerWinMagnifier::CreateCurrentFrameIfNecessary(
? SharedMemoryDesktopFrame::Create(size, ? SharedMemoryDesktopFrame::Create(size,
shared_memory_factory_.get()) shared_memory_factory_.get())
: std::unique_ptr<DesktopFrame>(new BasicDesktopFrame(size)); : std::unique_ptr<DesktopFrame>(new BasicDesktopFrame(size));
queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(frame.release())); queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame)));
} }
} }

View File

@ -106,12 +106,12 @@ class ScreenCapturerWinMagnifier : public ScreenCapturer {
static Atomic32 tls_index_; static Atomic32 tls_index_;
std::unique_ptr<ScreenCapturer> fallback_capturer_; std::unique_ptr<ScreenCapturer> fallback_capturer_;
bool fallback_capturer_started_; bool fallback_capturer_started_ = false;
Callback* callback_; Callback* callback_ = nullptr;
std::unique_ptr<SharedMemoryFactory> shared_memory_factory_; std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
ScreenId current_screen_id_; ScreenId current_screen_id_ = kFullDesktopScreenId;
std::wstring current_device_key_; std::wstring current_device_key_;
HWND excluded_window_; HWND excluded_window_ = NULL;
// A thread-safe list of invalid rectangles, and the size of the most // A thread-safe list of invalid rectangles, and the size of the most
// recently captured screen. // recently captured screen.
@ -124,31 +124,31 @@ class ScreenCapturerWinMagnifier : public ScreenCapturer {
std::unique_ptr<Differ> differ_; std::unique_ptr<Differ> differ_;
// Used to suppress duplicate logging of SetThreadExecutionState errors. // Used to suppress duplicate logging of SetThreadExecutionState errors.
bool set_thread_execution_state_failed_; bool set_thread_execution_state_failed_ = false;
ScopedThreadDesktop desktop_; ScopedThreadDesktop desktop_;
// Used for getting the screen dpi. // Used for getting the screen dpi.
HDC desktop_dc_; HDC desktop_dc_ = NULL;
HMODULE mag_lib_handle_; HMODULE mag_lib_handle_ = NULL;
MagInitializeFunc mag_initialize_func_; MagInitializeFunc mag_initialize_func_ = nullptr;
MagUninitializeFunc mag_uninitialize_func_; MagUninitializeFunc mag_uninitialize_func_ = nullptr;
MagSetWindowSourceFunc set_window_source_func_; MagSetWindowSourceFunc set_window_source_func_ = nullptr;
MagSetWindowFilterListFunc set_window_filter_list_func_; MagSetWindowFilterListFunc set_window_filter_list_func_ = nullptr;
MagSetImageScalingCallbackFunc set_image_scaling_callback_func_; MagSetImageScalingCallbackFunc set_image_scaling_callback_func_ = nullptr;
// The hidden window hosting the magnifier control. // The hidden window hosting the magnifier control.
HWND host_window_; HWND host_window_ = NULL;
// The magnifier control that captures the screen. // The magnifier control that captures the screen.
HWND magnifier_window_; HWND magnifier_window_ = NULL;
// True if the magnifier control has been successfully initialized. // True if the magnifier control has been successfully initialized.
bool magnifier_initialized_; bool magnifier_initialized_ = false;
// True if the last OnMagImageScalingCallback was called and handled // True if the last OnMagImageScalingCallback was called and handled
// successfully. Reset at the beginning of each CaptureImage call. // successfully. Reset at the beginning of each CaptureImage call.
bool magnifier_capture_succeeded_; bool magnifier_capture_succeeded_ = true;
RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier); RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier);
}; };

View File

@ -32,7 +32,7 @@ namespace {
// Returns true if the window exists. // Returns true if the window exists.
bool IsWindowValid(CGWindowID id) { bool IsWindowValid(CGWindowID id) {
CFArrayRef window_id_array = CFArrayRef window_id_array =
CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL); CFArrayCreate(nullptr, reinterpret_cast<const void**>(&id), 1, nullptr);
CFArrayRef window_array = CFArrayRef window_array =
CGWindowListCreateDescriptionFromArray(window_id_array); CGWindowListCreateDescriptionFromArray(window_id_array);
bool valid = window_array && CFArrayGetCount(window_array); bool valid = window_array && CFArrayGetCount(window_array);
@ -58,10 +58,10 @@ class WindowCapturerMac : public WindowCapturer {
void Capture(const DesktopRegion& region) override; void Capture(const DesktopRegion& region) override;
private: private:
Callback* callback_; Callback* callback_ = nullptr;
// The window being captured. // The window being captured.
CGWindowID window_id_; CGWindowID window_id_ = 0;
rtc::scoped_refptr<FullScreenChromeWindowDetector> rtc::scoped_refptr<FullScreenChromeWindowDetector>
full_screen_chrome_window_detector_; full_screen_chrome_window_detector_;
@ -69,15 +69,12 @@ class WindowCapturerMac : public WindowCapturer {
RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerMac); RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerMac);
}; };
WindowCapturerMac::WindowCapturerMac(rtc::scoped_refptr< WindowCapturerMac::WindowCapturerMac(
FullScreenChromeWindowDetector> full_screen_chrome_window_detector) rtc::scoped_refptr<FullScreenChromeWindowDetector>
: callback_(NULL), full_screen_chrome_window_detector)
window_id_(0), : full_screen_chrome_window_detector_(full_screen_chrome_window_detector) {}
full_screen_chrome_window_detector_(full_screen_chrome_window_detector) {
}
WindowCapturerMac::~WindowCapturerMac() { WindowCapturerMac::~WindowCapturerMac() {}
}
bool WindowCapturerMac::GetWindowList(WindowList* windows) { bool WindowCapturerMac::GetWindowList(WindowList* windows) {
// Only get on screen, non-desktop windows. // Only get on screen, non-desktop windows.
@ -142,11 +139,11 @@ bool WindowCapturerMac::BringSelectedWindowToFront() {
CGWindowID ids[1]; CGWindowID ids[1];
ids[0] = window_id_; ids[0] = window_id_;
CFArrayRef window_id_array = CFArrayRef window_id_array =
CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL); CFArrayCreate(nullptr, reinterpret_cast<const void**>(&ids), 1, nullptr);
CFArrayRef window_array = CFArrayRef window_array =
CGWindowListCreateDescriptionFromArray(window_id_array); CGWindowListCreateDescriptionFromArray(window_id_array);
if (window_array == NULL || 0 == CFArrayGetCount(window_array)) { if (!window_array || 0 == CFArrayGetCount(window_array)) {
// Could not find the window. It might have been closed. // Could not find the window. It might have been closed.
LOG(LS_INFO) << "Window not found"; LOG(LS_INFO) << "Window not found";
CFRelease(window_id_array); CFRelease(window_id_array);
@ -181,7 +178,7 @@ void WindowCapturerMac::Start(Callback* callback) {
void WindowCapturerMac::Capture(const DesktopRegion& region) { void WindowCapturerMac::Capture(const DesktopRegion& region) {
if (!IsWindowValid(window_id_)) { if (!IsWindowValid(window_id_)) {
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
@ -199,7 +196,7 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
on_screen_window, kCGWindowImageBoundsIgnoreFraming); on_screen_window, kCGWindowImageBoundsIgnoreFraming);
if (!window_image) { if (!window_image) {
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
@ -207,7 +204,7 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
if (bits_per_pixel != 32) { if (bits_per_pixel != 32) {
LOG(LS_ERROR) << "Unsupported window image depth: " << bits_per_pixel; LOG(LS_ERROR) << "Unsupported window image depth: " << bits_per_pixel;
CFRelease(window_image); CFRelease(window_image);
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
@ -215,8 +212,8 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
int height = CGImageGetHeight(window_image); int height = CGImageGetHeight(window_image);
CGDataProviderRef provider = CGImageGetDataProvider(window_image); CGDataProviderRef provider = CGImageGetDataProvider(window_image);
CFDataRef cf_data = CGDataProviderCopyData(provider); CFDataRef cf_data = CGDataProviderCopyData(provider);
DesktopFrame* frame = new BasicDesktopFrame( std::unique_ptr<DesktopFrame> frame(
DesktopSize(width, height)); new BasicDesktopFrame(DesktopSize(width, height)));
int src_stride = CGImageGetBytesPerRow(window_image); int src_stride = CGImageGetBytesPerRow(window_image);
const uint8_t* src_data = CFDataGetBytePtr(cf_data); const uint8_t* src_data = CFDataGetBytePtr(cf_data);
@ -231,7 +228,7 @@ void WindowCapturerMac::Capture(const DesktopRegion& region) {
frame->mutable_updated_region()->SetRect( frame->mutable_updated_region()->SetRect(
DesktopRect::MakeSize(frame->size())); DesktopRect::MakeSize(frame->size()));
callback_->OnCaptureCompleted(frame); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
if (full_screen_chrome_window_detector_) if (full_screen_chrome_window_detector_)
full_screen_chrome_window_detector_->UpdateWindowListIfNeeded(window_id_); full_screen_chrome_window_detector_->UpdateWindowListIfNeeded(window_id_);

View File

@ -34,17 +34,13 @@ class WindowCapturerNull : public WindowCapturer {
void Capture(const DesktopRegion& region) override; void Capture(const DesktopRegion& region) override;
private: private:
Callback* callback_; Callback* callback_ = nullptr;
RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerNull); RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerNull);
}; };
WindowCapturerNull::WindowCapturerNull() WindowCapturerNull::WindowCapturerNull() {}
: callback_(NULL) { WindowCapturerNull::~WindowCapturerNull() {}
}
WindowCapturerNull::~WindowCapturerNull() {
}
bool WindowCapturerNull::GetWindowList(WindowList* windows) { bool WindowCapturerNull::GetWindowList(WindowList* windows) {
// Not implemented yet. // Not implemented yet.
@ -70,7 +66,7 @@ void WindowCapturerNull::Start(Callback* callback) {
void WindowCapturerNull::Capture(const DesktopRegion& region) { void WindowCapturerNull::Capture(const DesktopRegion& region) {
// Not implemented yet. // Not implemented yet.
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
} }
} // namespace } // namespace

View File

@ -31,7 +31,10 @@ class WindowCapturerTest : public testing::Test,
void TearDown() override {} void TearDown() override {}
// DesktopCapturer::Callback interface // DesktopCapturer::Callback interface
void OnCaptureCompleted(DesktopFrame* frame) override { frame_.reset(frame); } void OnCaptureResult(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> frame) override {
frame_ = std::move(frame);
}
protected: protected:
std::unique_ptr<WindowCapturer> capturer_; std::unique_ptr<WindowCapturer> capturer_;

View File

@ -95,11 +95,11 @@ class WindowCapturerWin : public WindowCapturer {
void Capture(const DesktopRegion& region) override; void Capture(const DesktopRegion& region) override;
private: private:
Callback* callback_; Callback* callback_ = nullptr;
// HWND and HDC for the currently selected window or NULL if window is not // HWND and HDC for the currently selected window or nullptr if window is not
// selected. // selected.
HWND window_; HWND window_ = nullptr;
DesktopSize previous_size_; DesktopSize previous_size_;
@ -112,13 +112,8 @@ class WindowCapturerWin : public WindowCapturer {
RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin); RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin);
}; };
WindowCapturerWin::WindowCapturerWin() WindowCapturerWin::WindowCapturerWin() {}
: callback_(NULL), WindowCapturerWin::~WindowCapturerWin() {}
window_(NULL) {
}
WindowCapturerWin::~WindowCapturerWin() {
}
bool WindowCapturerWin::GetWindowList(WindowList* windows) { bool WindowCapturerWin::GetWindowList(WindowList* windows) {
WindowList result; WindowList result;
@ -168,13 +163,13 @@ void WindowCapturerWin::Start(Callback* callback) {
void WindowCapturerWin::Capture(const DesktopRegion& region) { void WindowCapturerWin::Capture(const DesktopRegion& region) {
if (!window_) { if (!window_) {
LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError(); LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
// Stop capturing if the window has been closed. // Stop capturing if the window has been closed.
if (!IsWindow(window_)) { if (!IsWindow(window_)) {
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
@ -182,12 +177,13 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
// behavior on mace. Window can be temporarily invisible during the // behavior on mace. Window can be temporarily invisible during the
// transition of full screen mode on/off. // transition of full screen mode on/off.
if (IsIconic(window_) || !IsWindowVisible(window_)) { if (IsIconic(window_) || !IsWindowVisible(window_)) {
BasicDesktopFrame* frame = new BasicDesktopFrame(DesktopSize(1, 1)); std::unique_ptr<DesktopFrame> frame(
new BasicDesktopFrame(DesktopSize(1, 1)));
memset(frame->data(), 0, frame->stride() * frame->size().height()); memset(frame->data(), 0, frame->stride() * frame->size().height());
previous_size_ = frame->size(); previous_size_ = frame->size();
window_size_map_[window_] = previous_size_; window_size_map_[window_] = previous_size_;
callback_->OnCaptureCompleted(frame); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
return; return;
} }
@ -195,22 +191,22 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
DesktopRect cropped_rect; DesktopRect cropped_rect;
if (!GetCroppedWindowRect(window_, &cropped_rect, &original_rect)) { if (!GetCroppedWindowRect(window_, &cropped_rect, &original_rect)) {
LOG(LS_WARNING) << "Failed to get window info: " << GetLastError(); LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
HDC window_dc = GetWindowDC(window_); HDC window_dc = GetWindowDC(window_);
if (!window_dc) { if (!window_dc) {
LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError(); LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError();
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
std::unique_ptr<DesktopFrameWin> frame( std::unique_ptr<DesktopFrameWin> frame(
DesktopFrameWin::Create(cropped_rect.size(), NULL, window_dc)); DesktopFrameWin::Create(cropped_rect.size(), nullptr, window_dc));
if (!frame.get()) { if (!frame.get()) {
ReleaseDC(window_, window_dc); ReleaseDC(window_, window_dc);
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return; return;
} }
@ -263,7 +259,7 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
frame.reset(); frame.reset();
} }
callback_->OnCaptureCompleted(frame.release()); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} }
} // namespace } // namespace

42
webrtc/modules/desktop_capture/window_capturer_x11.cc Executable file → Normal file
View File

@ -36,10 +36,7 @@ namespace {
template <class PropertyType> template <class PropertyType>
class XWindowProperty { class XWindowProperty {
public: public:
XWindowProperty(Display* display, Window window, Atom property) XWindowProperty(Display* display, Window window, Atom property) {
: is_valid_(false),
size_(0),
data_(NULL) {
const int kBitsPerByte = 8; const int kBitsPerByte = 8;
Atom actual_type; Atom actual_type;
int actual_format; int actual_format;
@ -49,7 +46,7 @@ class XWindowProperty {
&actual_format, &size_, &actual_format, &size_,
&bytes_after, &data_); &bytes_after, &data_);
if (status != Success) { if (status != Success) {
data_ = NULL; data_ = nullptr;
return; return;
} }
if (sizeof(PropertyType) * kBitsPerByte != actual_format) { if (sizeof(PropertyType) * kBitsPerByte != actual_format) {
@ -78,9 +75,9 @@ class XWindowProperty {
} }
private: private:
bool is_valid_; bool is_valid_ = false;
unsigned long size_; // NOLINT: type required by XGetWindowProperty unsigned long size_ = 0; // NOLINT: type required by XGetWindowProperty
unsigned char* data_; unsigned char* data_ = nullptr;
RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty); RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty);
}; };
@ -117,26 +114,23 @@ class WindowCapturerLinux : public WindowCapturer,
// Returns window title for the specified X |window|. // Returns window title for the specified X |window|.
bool GetWindowTitle(::Window window, std::string* title); bool GetWindowTitle(::Window window, std::string* title);
Callback* callback_; Callback* callback_ = nullptr;
rtc::scoped_refptr<SharedXDisplay> x_display_; rtc::scoped_refptr<SharedXDisplay> x_display_;
Atom wm_state_atom_; Atom wm_state_atom_;
Atom window_type_atom_; Atom window_type_atom_;
Atom normal_window_type_atom_; Atom normal_window_type_atom_;
bool has_composite_extension_; bool has_composite_extension_ = false;
::Window selected_window_; ::Window selected_window_ = 0;
XServerPixelBuffer x_server_pixel_buffer_; XServerPixelBuffer x_server_pixel_buffer_;
RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux); RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux);
}; };
WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options) WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options)
: callback_(NULL), : x_display_(options.x_display()) {
x_display_(options.x_display()),
has_composite_extension_(false),
selected_window_(0) {
// Create Atoms so we don't need to do it every time they are used. // Create Atoms so we don't need to do it every time they are used.
wm_state_atom_ = XInternAtom(display(), "WM_STATE", True); wm_state_atom_ = XInternAtom(display(), "WM_STATE", True);
window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True); window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True);
@ -280,7 +274,7 @@ void WindowCapturerLinux::Start(Callback* callback) {
void WindowCapturerLinux::Capture(const DesktopRegion& region) { void WindowCapturerLinux::Capture(const DesktopRegion& region) {
if (!x_server_pixel_buffer_.IsWindowValid()) { if (!x_server_pixel_buffer_.IsWindowValid()) {
LOG(LS_INFO) << "The window is no longer valid."; LOG(LS_INFO) << "The window is no longer valid.";
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
@ -291,21 +285,21 @@ void WindowCapturerLinux::Capture(const DesktopRegion& region) {
// visible on screen and not covered by any other window. This is not // visible on screen and not covered by any other window. This is not
// something we want so instead, just bail out. // something we want so instead, just bail out.
LOG(LS_INFO) << "No Xcomposite extension detected."; LOG(LS_INFO) << "No Xcomposite extension detected.";
callback_->OnCaptureCompleted(NULL); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
DesktopFrame* frame = std::unique_ptr<DesktopFrame> frame(
new BasicDesktopFrame(x_server_pixel_buffer_.window_size()); new BasicDesktopFrame(x_server_pixel_buffer_.window_size()));
x_server_pixel_buffer_.Synchronize(); x_server_pixel_buffer_.Synchronize();
x_server_pixel_buffer_.CaptureRect(DesktopRect::MakeSize(frame->size()), x_server_pixel_buffer_.CaptureRect(DesktopRect::MakeSize(frame->size()),
frame); frame.get());
frame->mutable_updated_region()->SetRect( frame->mutable_updated_region()->SetRect(
DesktopRect::MakeSize(frame->size())); DesktopRect::MakeSize(frame->size()));
callback_->OnCaptureCompleted(frame); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} }
bool WindowCapturerLinux::HandleXEvent(const XEvent& event) { bool WindowCapturerLinux::HandleXEvent(const XEvent& event) {
@ -399,12 +393,12 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
int status; int status;
bool result = false; bool result = false;
XTextProperty window_name; XTextProperty window_name;
window_name.value = NULL; window_name.value = nullptr;
if (window) { if (window) {
status = XGetWMName(display(), window, &window_name); status = XGetWMName(display(), window, &window_name);
if (status && window_name.value && window_name.nitems) { if (status && window_name.value && window_name.nitems) {
int cnt; int cnt;
char **list = NULL; char** list = nullptr;
status = Xutf8TextPropertyToTextList(display(), &window_name, &list, status = Xutf8TextPropertyToTextList(display(), &window_name, &list,
&cnt); &cnt);
if (status >= Success && cnt && *list) { if (status >= Success && cnt && *list) {
@ -429,7 +423,7 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
// static // static
WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) { WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
if (!options.x_display()) if (!options.x_display())
return NULL; return nullptr;
return new WindowCapturerLinux(options); return new WindowCapturerLinux(options);
} }