| Index: webrtc/modules/desktop_capture/screen_capturer_mac.mm
|
| diff --git a/webrtc/modules/desktop_capture/screen_capturer_mac.mm b/webrtc/modules/desktop_capture/screen_capturer_mac.mm
|
| index 316aa3dbe6a04da78bad6a39ea21f7baa22638d8..451cd9ed9d8168463d6370ef52b0a012ebfaefaa 100644
|
| --- a/webrtc/modules/desktop_capture/screen_capturer_mac.mm
|
| +++ b/webrtc/modules/desktop_capture/screen_capturer_mac.mm
|
| @@ -18,7 +18,6 @@
|
|
|
| #include <ApplicationServices/ApplicationServices.h>
|
| #include <Cocoa/Cocoa.h>
|
| -#include <CoreGraphics/CoreGraphics.h>
|
| #include <dlfcn.h>
|
| #include <OpenGL/CGLMacro.h>
|
| #include <OpenGL/OpenGL.h>
|
| @@ -44,74 +43,6 @@
|
|
|
| namespace {
|
|
|
| -// CGDisplayStreamRefs need to be destroyed asynchronously after receiving a
|
| -// kCGDisplayStreamFrameStatusStopped callback from CoreGraphics. This may
|
| -// happen after the ScreenCapturerMac has been destroyed. DisplayStreamManager
|
| -// is responsible for destroying all extant CGDisplayStreamRefs, and will
|
| -// destroy itself once it's done.
|
| -class DisplayStreamManager {
|
| - public:
|
| - int GetUniqueId() { return ++unique_id_generator_; }
|
| - void DestroyStream(int unique_id) {
|
| - auto it = display_stream_wrappers_.find(unique_id);
|
| - RTC_CHECK(it != display_stream_wrappers_.end());
|
| - RTC_CHECK(!it->second.active);
|
| - CFRelease(it->second.stream);
|
| - display_stream_wrappers_.erase(it);
|
| -
|
| - if (ready_for_self_destruction_ && display_stream_wrappers_.empty())
|
| - delete this;
|
| - }
|
| -
|
| - void SaveStream(int unique_id, CGDisplayStreamRef stream) {
|
| - RTC_CHECK(unique_id <= unique_id_generator_);
|
| - DisplayStreamWrapper wrapper;
|
| - wrapper.stream = stream;
|
| - display_stream_wrappers_[unique_id] = wrapper;
|
| - }
|
| -
|
| - void UnregisterActiveStreams() {
|
| - for (auto& pair : display_stream_wrappers_) {
|
| - DisplayStreamWrapper& wrapper = pair.second;
|
| - if (wrapper.active) {
|
| - wrapper.active = false;
|
| -// CGDisplayStream* functions are only available in 10.8+. Chrome only supports
|
| -// 10.9+, but we can't remove these warning suppressions until the deployment
|
| -// target is updated. https://crbug.com/579255
|
| -#pragma clang diagnostic push
|
| -#pragma clang diagnostic ignored "-Wunguarded-availability"
|
| - CGDisplayStreamStop(wrapper.stream);
|
| -#pragma clang diagnostic pop
|
| - }
|
| - }
|
| - }
|
| -
|
| - void PrepareForSelfDestruction() {
|
| - ready_for_self_destruction_ = true;
|
| -
|
| - if (display_stream_wrappers_.empty())
|
| - delete this;
|
| - }
|
| -
|
| - // Once the DisplayStreamManager is ready for destruction, the
|
| - // ScreenCapturerMac is no longer present. Any updates should be ignored.
|
| - bool ShouldIgnoreUpdates() { return ready_for_self_destruction_; }
|
| -
|
| - private:
|
| - struct DisplayStreamWrapper {
|
| - // The registered CGDisplayStreamRef.
|
| - CGDisplayStreamRef stream = nullptr;
|
| -
|
| - // Set to false when the stream has been stopped. An asynchronous callback
|
| - // from CoreGraphics will let us destroy the CGDisplayStreamRef.
|
| - bool active = true;
|
| - };
|
| -
|
| - std::map<int, DisplayStreamWrapper> display_stream_wrappers_;
|
| - int unique_id_generator_ = 0;
|
| - bool ready_for_self_destruction_ = false;
|
| -};
|
| -
|
| // Definitions used to dynamic-link to deprecated OS 10.6 functions.
|
| const char* kApplicationServicesLibraryName =
|
| "/System/Library/Frameworks/ApplicationServices.framework/"
|
| @@ -287,11 +218,16 @@
|
| void UnregisterRefreshAndMoveHandlers();
|
|
|
| void ScreenRefresh(CGRectCount count, const CGRect *rect_array);
|
| - void ScreenUpdateMove(CGFloat delta_x,
|
| - CGFloat delta_y,
|
| + void ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
|
| size_t count,
|
| - const CGRect* rect_array);
|
| - void ScreenRefreshCallback(CGRectCount count, const CGRect* rect_array);
|
| + const CGRect *rect_array);
|
| + static void ScreenRefreshCallback(CGRectCount count,
|
| + const CGRect *rect_array,
|
| + void *user_parameter);
|
| + static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta,
|
| + size_t count,
|
| + const CGRect *rect_array,
|
| + void *user_parameter);
|
| void ReleaseBuffers();
|
|
|
| std::unique_ptr<DesktopFrame> CreateFrame();
|
| @@ -336,10 +272,6 @@
|
| CGLSetFullScreenFunc cgl_set_full_screen_ = nullptr;
|
|
|
| CGWindowID excluded_window_ = 0;
|
| -
|
| - // A self-owned object that will destroy itself after ScreenCapturerMac and
|
| - // all display streams have been destroyed..
|
| - DisplayStreamManager* display_stream_manager_;
|
|
|
| RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac);
|
| };
|
| @@ -369,25 +301,22 @@
|
|
|
| ScreenCapturerMac::ScreenCapturerMac(
|
| rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor)
|
| - : desktop_config_monitor_(desktop_config_monitor) {
|
| - display_stream_manager_ = new DisplayStreamManager;
|
| -}
|
| + : desktop_config_monitor_(desktop_config_monitor) {}
|
|
|
| ScreenCapturerMac::~ScreenCapturerMac() {
|
| ReleaseBuffers();
|
| - display_stream_manager_->PrepareForSelfDestruction();
|
| UnregisterRefreshAndMoveHandlers();
|
| dlclose(app_services_library_);
|
| dlclose(opengl_library_);
|
| }
|
|
|
| bool ScreenCapturerMac::Init() {
|
| + if (!RegisterRefreshAndMoveHandlers()) {
|
| + return false;
|
| + }
|
| desktop_config_monitor_->Lock();
|
| desktop_config_ = desktop_config_monitor_->desktop_configuration();
|
| desktop_config_monitor_->Unlock();
|
| - if (!RegisterRefreshAndMoveHandlers()) {
|
| - return false;
|
| - }
|
| ScreenConfigurationChanged();
|
| return true;
|
| }
|
| @@ -919,77 +848,28 @@
|
| }
|
|
|
| bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
|
| - desktop_config_ = desktop_config_monitor_->desktop_configuration();
|
| - for (const auto& config : desktop_config_.displays) {
|
| - size_t pixel_width = config.pixel_bounds.width();
|
| - size_t pixel_height = config.pixel_bounds.height();
|
| - if (pixel_width == 0 || pixel_height == 0)
|
| - continue;
|
| - int unique_id = display_stream_manager_->GetUniqueId();
|
| - CGDirectDisplayID display_id = config.id;
|
| - CGDisplayStreamFrameAvailableHandler handler =
|
| - ^(CGDisplayStreamFrameStatus status, uint64_t display_time,
|
| - IOSurfaceRef frame_surface, CGDisplayStreamUpdateRef updateRef) {
|
| - if (status == kCGDisplayStreamFrameStatusStopped) {
|
| - display_stream_manager_->DestroyStream(unique_id);
|
| - return;
|
| - }
|
| -
|
| - if (display_stream_manager_->ShouldIgnoreUpdates())
|
| - return;
|
| -
|
| - // Only pay attention to frame updates.
|
| - if (status != kCGDisplayStreamFrameStatusFrameComplete)
|
| - return;
|
| -
|
| - size_t count = 0;
|
| -#pragma clang diagnostic push
|
| -#pragma clang diagnostic ignored "-Wunguarded-availability"
|
| -// TODO(erikchen): Use kCGDisplayStreamUpdateDirtyRects.
|
| - const CGRect* rects = CGDisplayStreamUpdateGetRects(
|
| - updateRef, kCGDisplayStreamUpdateMovedRects, &count);
|
| -#pragma clang diagnostic pop
|
| - if (count != 0) {
|
| - CGFloat dx = 0;
|
| - CGFloat dy = 0;
|
| -#pragma clang diagnostic push
|
| -#pragma clang diagnostic ignored "-Wunguarded-availability"
|
| - CGDisplayStreamUpdateGetMovedRectsDelta(updateRef, &dx, &dy);
|
| -#pragma clang diagnostic pop
|
| - ScreenUpdateMove(dx, dy, count, rects);
|
| - }
|
| -
|
| - count = 0;
|
| -#pragma clang diagnostic push
|
| -#pragma clang diagnostic ignored "-Wunguarded-availability"
|
| - rects = CGDisplayStreamUpdateGetRects(
|
| - updateRef, kCGDisplayStreamUpdateRefreshedRects, &count);
|
| -#pragma clang diagnostic pop
|
| - if (count != 0) {
|
| - // According to CGDisplayStream.h, it's safe to call
|
| - // CGDisplayStreamStop() from within the callback.
|
| - ScreenRefreshCallback(count, rects);
|
| - }
|
| - };
|
| -#pragma clang diagnostic push
|
| -#pragma clang diagnostic ignored "-Wunguarded-availability"
|
| - CGDisplayStreamRef display_stream = CGDisplayStreamCreate(
|
| - display_id, pixel_width, pixel_height, 'BGRA', nullptr, handler);
|
| -#pragma clang diagnostic pop
|
| - if (display_stream) {
|
| - display_stream_manager_->SaveStream(unique_id, display_stream);
|
| -#pragma clang diagnostic push
|
| -#pragma clang diagnostic ignored "-Wunguarded-availability"
|
| - CGDisplayStreamStart(display_stream);
|
| -#pragma clang diagnostic pop
|
| - }
|
| + CGError err = CGRegisterScreenRefreshCallback(
|
| + ScreenCapturerMac::ScreenRefreshCallback, this);
|
| + if (err != kCGErrorSuccess) {
|
| + LOG(LS_ERROR) << "CGRegisterScreenRefreshCallback " << err;
|
| + return false;
|
| + }
|
| +
|
| + err = CGScreenRegisterMoveCallback(
|
| + ScreenCapturerMac::ScreenUpdateMoveCallback, this);
|
| + if (err != kCGErrorSuccess) {
|
| + LOG(LS_ERROR) << "CGScreenRegisterMoveCallback " << err;
|
| + return false;
|
| }
|
|
|
| return true;
|
| }
|
|
|
| void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() {
|
| - display_stream_manager_->UnregisterActiveStreams();
|
| + CGUnregisterScreenRefreshCallback(
|
| + ScreenCapturerMac::ScreenRefreshCallback, this);
|
| + CGScreenUnregisterMoveCallback(
|
| + ScreenCapturerMac::ScreenUpdateMoveCallback, this);
|
| }
|
|
|
| void ScreenCapturerMac::ScreenRefresh(CGRectCount count,
|
| @@ -1011,14 +891,13 @@
|
| helper_.InvalidateRegion(region);
|
| }
|
|
|
| -void ScreenCapturerMac::ScreenUpdateMove(CGFloat delta_x,
|
| - CGFloat delta_y,
|
| +void ScreenCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
|
| size_t count,
|
| const CGRect* rect_array) {
|
| // Translate |rect_array| to identify the move's destination.
|
| CGRect refresh_rects[count];
|
| for (CGRectCount i = 0; i < count; ++i) {
|
| - refresh_rects[i] = CGRectOffset(rect_array[i], delta_x, delta_y);
|
| + refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY);
|
| }
|
|
|
| // Currently we just treat move events the same as refreshes.
|
| @@ -1026,10 +905,23 @@
|
| }
|
|
|
| void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count,
|
| - const CGRect* rect_array) {
|
| - if (screen_pixel_bounds_.is_empty())
|
| - ScreenConfigurationChanged();
|
| - ScreenRefresh(count, rect_array);
|
| + const CGRect* rect_array,
|
| + void* user_parameter) {
|
| + ScreenCapturerMac* capturer =
|
| + reinterpret_cast<ScreenCapturerMac*>(user_parameter);
|
| + if (capturer->screen_pixel_bounds_.is_empty())
|
| + capturer->ScreenConfigurationChanged();
|
| + capturer->ScreenRefresh(count, rect_array);
|
| +}
|
| +
|
| +void ScreenCapturerMac::ScreenUpdateMoveCallback(
|
| + CGScreenUpdateMoveDelta delta,
|
| + size_t count,
|
| + const CGRect* rect_array,
|
| + void* user_parameter) {
|
| + ScreenCapturerMac* capturer =
|
| + reinterpret_cast<ScreenCapturerMac*>(user_parameter);
|
| + capturer->ScreenUpdateMove(delta, count, rect_array);
|
| }
|
|
|
| std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() {
|
|
|