| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "webrtc/modules/desktop_capture/desktop_region.h" | 33 #include "webrtc/modules/desktop_capture/desktop_region.h" |
| 34 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" | 34 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" |
| 35 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h" | 35 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h" |
| 36 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h" | 36 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h" |
| 37 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" | 37 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" |
| 38 #include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h" | 38 #include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h" |
| 39 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" | 39 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" |
| 40 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" | 40 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" |
| 41 #include "webrtc/system_wrappers/include/logging.h" | 41 #include "webrtc/system_wrappers/include/logging.h" |
| 42 | 42 |
| 43 // Once Chrome no longer supports OSX 10.8, everything within this |
| 44 // preprocessor block can be removed. https://crbug.com/579255 |
| 45 #if !defined(MAC_OS_X_VERSION_10_9) || \ |
| 46 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 |
| 47 CG_EXTERN const CGRect* CGDisplayStreamUpdateGetRects( |
| 48 CGDisplayStreamUpdateRef updateRef, |
| 49 CGDisplayStreamUpdateRectType rectType, |
| 50 size_t* rectCount); |
| 51 CG_EXTERN CFRunLoopSourceRef |
| 52 CGDisplayStreamGetRunLoopSource(CGDisplayStreamRef displayStream); |
| 53 CG_EXTERN CGError CGDisplayStreamStop(CGDisplayStreamRef displayStream); |
| 54 CG_EXTERN CGError CGDisplayStreamStart(CGDisplayStreamRef displayStream); |
| 55 CG_EXTERN CGDisplayStreamRef |
| 56 CGDisplayStreamCreate(CGDirectDisplayID display, |
| 57 size_t outputWidth, |
| 58 size_t outputHeight, |
| 59 int32_t pixelFormat, |
| 60 CFDictionaryRef properties, |
| 61 CGDisplayStreamFrameAvailableHandler handler); |
| 62 #endif |
| 63 |
| 43 namespace webrtc { | 64 namespace webrtc { |
| 44 | 65 |
| 45 namespace { | 66 namespace { |
| 46 | 67 |
| 47 // CGDisplayStreamRefs need to be destroyed asynchronously after receiving a | 68 // CGDisplayStreamRefs need to be destroyed asynchronously after receiving a |
| 48 // kCGDisplayStreamFrameStatusStopped callback from CoreGraphics. This may | 69 // kCGDisplayStreamFrameStatusStopped callback from CoreGraphics. This may |
| 49 // happen after the ScreenCapturerMac has been destroyed. DisplayStreamManager | 70 // happen after the ScreenCapturerMac has been destroyed. DisplayStreamManager |
| 50 // is responsible for destroying all extant CGDisplayStreamRefs, and will | 71 // is responsible for destroying all extant CGDisplayStreamRefs, and will |
| 51 // destroy itself once it's done. | 72 // destroy itself once it's done. |
| 52 class DisplayStreamManager { | 73 class DisplayStreamManager { |
| 53 public: | 74 public: |
| 54 int GetUniqueId() { return ++unique_id_generator_; } | 75 int GetUniqueId() { return ++unique_id_generator_; } |
| 55 void DestroyStream(int unique_id) { | 76 void DestroyStream(int unique_id) { |
| 56 auto it = display_stream_wrappers_.find(unique_id); | 77 auto it = display_stream_wrappers_.find(unique_id); |
| 57 RTC_CHECK(it != display_stream_wrappers_.end()); | 78 RTC_CHECK(it != display_stream_wrappers_.end()); |
| 58 RTC_CHECK(!it->second.active); | 79 RTC_CHECK(!it->second.active); |
| 59 CFRelease(it->second.stream); | 80 CFRelease(it->second.stream); |
| 60 display_stream_wrappers_.erase(it); | 81 display_stream_wrappers_.erase(it); |
| 61 | 82 |
| 62 if (ready_for_self_destruction_ && display_stream_wrappers_.empty()) | 83 if (ready_for_self_destruction_ && display_stream_wrappers_.empty()) |
| 63 delete this; | 84 delete this; |
| 64 } | 85 } |
| 65 | 86 |
| 66 void SaveStream(int unique_id, CGDisplayStreamRef stream) { | 87 void SaveStream(int unique_id, |
| 88 CGDisplayStreamRef stream) { |
| 67 RTC_CHECK(unique_id <= unique_id_generator_); | 89 RTC_CHECK(unique_id <= unique_id_generator_); |
| 68 DisplayStreamWrapper wrapper; | 90 DisplayStreamWrapper wrapper; |
| 69 wrapper.stream = stream; | 91 wrapper.stream = stream; |
| 70 display_stream_wrappers_[unique_id] = wrapper; | 92 display_stream_wrappers_[unique_id] = wrapper; |
| 71 } | 93 } |
| 72 | 94 |
| 73 void UnregisterActiveStreams() { | 95 void UnregisterActiveStreams() { |
| 74 for (auto& pair : display_stream_wrappers_) { | 96 for (auto& pair : display_stream_wrappers_) { |
| 75 DisplayStreamWrapper& wrapper = pair.second; | 97 DisplayStreamWrapper& wrapper = pair.second; |
| 76 if (wrapper.active) { | 98 if (wrapper.active) { |
| 77 wrapper.active = false; | 99 wrapper.active = false; |
| 78 // CGDisplayStream* functions are only available in 10.8+. Chrome only supports | 100 CFRunLoopSourceRef source = |
| 79 // 10.9+, but we can't remove these warning suppressions until the deployment | 101 CGDisplayStreamGetRunLoopSource(wrapper.stream); |
| 80 // target is updated. https://crbug.com/579255 | 102 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, |
| 81 #pragma clang diagnostic push | 103 kCFRunLoopDefaultMode); |
| 82 #pragma clang diagnostic ignored "-Wunguarded-availability" | |
| 83 CGDisplayStreamStop(wrapper.stream); | 104 CGDisplayStreamStop(wrapper.stream); |
| 84 #pragma clang diagnostic pop | |
| 85 } | 105 } |
| 86 } | 106 } |
| 87 } | 107 } |
| 88 | 108 |
| 89 void PrepareForSelfDestruction() { | 109 void PrepareForSelfDestruction() { |
| 90 ready_for_self_destruction_ = true; | 110 ready_for_self_destruction_ = true; |
| 91 | 111 |
| 92 if (display_stream_wrappers_.empty()) | 112 if (display_stream_wrappers_.empty()) |
| 93 delete this; | 113 delete this; |
| 94 } | 114 } |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 bool CgBlitPostLion(const DesktopFrame& frame, | 300 bool CgBlitPostLion(const DesktopFrame& frame, |
| 281 const DesktopRegion& region); | 301 const DesktopRegion& region); |
| 282 | 302 |
| 283 // Called when the screen configuration is changed. | 303 // Called when the screen configuration is changed. |
| 284 void ScreenConfigurationChanged(); | 304 void ScreenConfigurationChanged(); |
| 285 | 305 |
| 286 bool RegisterRefreshAndMoveHandlers(); | 306 bool RegisterRefreshAndMoveHandlers(); |
| 287 void UnregisterRefreshAndMoveHandlers(); | 307 void UnregisterRefreshAndMoveHandlers(); |
| 288 | 308 |
| 289 void ScreenRefresh(CGRectCount count, const CGRect *rect_array); | 309 void ScreenRefresh(CGRectCount count, const CGRect *rect_array); |
| 290 void ScreenUpdateMove(CGFloat delta_x, | |
| 291 CGFloat delta_y, | |
| 292 size_t count, | |
| 293 const CGRect* rect_array); | |
| 294 void ScreenRefreshCallback(CGRectCount count, const CGRect* rect_array); | |
| 295 void ReleaseBuffers(); | 310 void ReleaseBuffers(); |
| 296 | 311 |
| 297 std::unique_ptr<DesktopFrame> CreateFrame(); | 312 std::unique_ptr<DesktopFrame> CreateFrame(); |
| 298 | 313 |
| 299 Callback* callback_ = nullptr; | 314 Callback* callback_ = nullptr; |
| 300 | 315 |
| 301 CGLContextObj cgl_context_ = nullptr; | 316 CGLContextObj cgl_context_ = nullptr; |
| 302 ScopedPixelBufferObject pixel_buffer_object_; | 317 ScopedPixelBufferObject pixel_buffer_object_; |
| 303 | 318 |
| 304 // Queue of the frames buffers. | 319 // Queue of the frames buffers. |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 pixel_buffer_object_.Init(cgl_context_, buffer_size); | 933 pixel_buffer_object_.Init(cgl_context_, buffer_size); |
| 919 } | 934 } |
| 920 | 935 |
| 921 bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() { | 936 bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() { |
| 922 desktop_config_ = desktop_config_monitor_->desktop_configuration(); | 937 desktop_config_ = desktop_config_monitor_->desktop_configuration(); |
| 923 for (const auto& config : desktop_config_.displays) { | 938 for (const auto& config : desktop_config_.displays) { |
| 924 size_t pixel_width = config.pixel_bounds.width(); | 939 size_t pixel_width = config.pixel_bounds.width(); |
| 925 size_t pixel_height = config.pixel_bounds.height(); | 940 size_t pixel_height = config.pixel_bounds.height(); |
| 926 if (pixel_width == 0 || pixel_height == 0) | 941 if (pixel_width == 0 || pixel_height == 0) |
| 927 continue; | 942 continue; |
| 928 int unique_id = display_stream_manager_->GetUniqueId(); | 943 // Using a local variable forces the block to capture the raw pointer. |
| 944 DisplayStreamManager* manager = display_stream_manager_; |
| 945 int unique_id = manager->GetUniqueId(); |
| 929 CGDirectDisplayID display_id = config.id; | 946 CGDirectDisplayID display_id = config.id; |
| 930 CGDisplayStreamFrameAvailableHandler handler = | 947 CGDisplayStreamFrameAvailableHandler handler = |
| 931 ^(CGDisplayStreamFrameStatus status, uint64_t display_time, | 948 ^(CGDisplayStreamFrameStatus status, uint64_t display_time, |
| 932 IOSurfaceRef frame_surface, CGDisplayStreamUpdateRef updateRef) { | 949 IOSurfaceRef frame_surface, CGDisplayStreamUpdateRef updateRef) { |
| 933 if (status == kCGDisplayStreamFrameStatusStopped) { | 950 if (status == kCGDisplayStreamFrameStatusStopped) { |
| 934 display_stream_manager_->DestroyStream(unique_id); | 951 manager->DestroyStream(unique_id); |
| 935 return; | 952 return; |
| 936 } | 953 } |
| 937 | 954 |
| 938 if (display_stream_manager_->ShouldIgnoreUpdates()) | 955 if (manager->ShouldIgnoreUpdates()) |
| 939 return; | 956 return; |
| 940 | 957 |
| 941 // Only pay attention to frame updates. | 958 // Only pay attention to frame updates. |
| 942 if (status != kCGDisplayStreamFrameStatusFrameComplete) | 959 if (status != kCGDisplayStreamFrameStatusFrameComplete) |
| 943 return; | 960 return; |
| 944 | 961 |
| 945 size_t count = 0; | 962 size_t count = 0; |
| 946 #pragma clang diagnostic push | |
| 947 #pragma clang diagnostic ignored "-Wunguarded-availability" | |
| 948 // TODO(erikchen): Use kCGDisplayStreamUpdateDirtyRects. | |
| 949 const CGRect* rects = CGDisplayStreamUpdateGetRects( | 963 const CGRect* rects = CGDisplayStreamUpdateGetRects( |
| 950 updateRef, kCGDisplayStreamUpdateMovedRects, &count); | 964 updateRef, kCGDisplayStreamUpdateDirtyRects, &count); |
| 951 #pragma clang diagnostic pop | |
| 952 if (count != 0) { | |
| 953 CGFloat dx = 0; | |
| 954 CGFloat dy = 0; | |
| 955 #pragma clang diagnostic push | |
| 956 #pragma clang diagnostic ignored "-Wunguarded-availability" | |
| 957 CGDisplayStreamUpdateGetMovedRectsDelta(updateRef, &dx, &dy); | |
| 958 #pragma clang diagnostic pop | |
| 959 ScreenUpdateMove(dx, dy, count, rects); | |
| 960 } | |
| 961 | |
| 962 count = 0; | |
| 963 #pragma clang diagnostic push | |
| 964 #pragma clang diagnostic ignored "-Wunguarded-availability" | |
| 965 rects = CGDisplayStreamUpdateGetRects( | |
| 966 updateRef, kCGDisplayStreamUpdateRefreshedRects, &count); | |
| 967 #pragma clang diagnostic pop | |
| 968 if (count != 0) { | 965 if (count != 0) { |
| 969 // According to CGDisplayStream.h, it's safe to call | 966 // According to CGDisplayStream.h, it's safe to call |
| 970 // CGDisplayStreamStop() from within the callback. | 967 // CGDisplayStreamStop() from within the callback. |
| 971 ScreenRefreshCallback(count, rects); | 968 ScreenRefresh(count, rects); |
| 972 } | 969 } |
| 973 }; | 970 }; |
| 974 #pragma clang diagnostic push | |
| 975 #pragma clang diagnostic ignored "-Wunguarded-availability" | |
| 976 CGDisplayStreamRef display_stream = CGDisplayStreamCreate( | 971 CGDisplayStreamRef display_stream = CGDisplayStreamCreate( |
| 977 display_id, pixel_width, pixel_height, 'BGRA', nullptr, handler); | 972 display_id, pixel_width, pixel_height, 'BGRA', nullptr, handler); |
| 978 #pragma clang diagnostic pop | 973 |
| 979 if (display_stream) { | 974 if (display_stream) { |
| 975 CGError error = CGDisplayStreamStart(display_stream); |
| 976 if (error != kCGErrorSuccess) |
| 977 return false; |
| 978 |
| 979 CFRunLoopSourceRef source = |
| 980 CGDisplayStreamGetRunLoopSource(display_stream); |
| 981 CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); |
| 980 display_stream_manager_->SaveStream(unique_id, display_stream); | 982 display_stream_manager_->SaveStream(unique_id, display_stream); |
| 981 #pragma clang diagnostic push | |
| 982 #pragma clang diagnostic ignored "-Wunguarded-availability" | |
| 983 CGDisplayStreamStart(display_stream); | |
| 984 #pragma clang diagnostic pop | |
| 985 } | 983 } |
| 986 } | 984 } |
| 987 | 985 |
| 988 return true; | 986 return true; |
| 989 } | 987 } |
| 990 | 988 |
| 991 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { | 989 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { |
| 992 display_stream_manager_->UnregisterActiveStreams(); | 990 display_stream_manager_->UnregisterActiveStreams(); |
| 993 } | 991 } |
| 994 | 992 |
| 995 void ScreenCapturerMac::ScreenRefresh(CGRectCount count, | 993 void ScreenCapturerMac::ScreenRefresh(CGRectCount count, |
| 996 const CGRect* rect_array) { | 994 const CGRect* rect_array) { |
| 997 if (screen_pixel_bounds_.is_empty()) | 995 if (screen_pixel_bounds_.is_empty()) |
| 998 return; | 996 ScreenConfigurationChanged(); |
| 999 | 997 |
| 1000 DesktopRegion region; | 998 DesktopRegion region; |
| 1001 DesktopVector translate_vector = | 999 DesktopVector translate_vector = |
| 1002 DesktopVector().subtract(screen_pixel_bounds_.top_left()); | 1000 DesktopVector().subtract(screen_pixel_bounds_.top_left()); |
| 1003 for (CGRectCount i = 0; i < count; ++i) { | 1001 for (CGRectCount i = 0; i < count; ++i) { |
| 1004 // Convert from Density-Independent Pixel to physical pixel coordinates. | 1002 // Convert from Density-Independent Pixel to physical pixel coordinates. |
| 1005 DesktopRect rect = ScaleAndRoundCGRect(rect_array[i], dip_to_pixel_scale_); | 1003 DesktopRect rect = ScaleAndRoundCGRect(rect_array[i], dip_to_pixel_scale_); |
| 1006 // Translate from local desktop to capturer framebuffer coordinates. | 1004 // Translate from local desktop to capturer framebuffer coordinates. |
| 1007 rect.Translate(translate_vector); | 1005 rect.Translate(translate_vector); |
| 1008 region.AddRect(rect); | 1006 region.AddRect(rect); |
| 1009 } | 1007 } |
| 1010 | 1008 |
| 1011 helper_.InvalidateRegion(region); | 1009 helper_.InvalidateRegion(region); |
| 1012 } | 1010 } |
| 1013 | 1011 |
| 1014 void ScreenCapturerMac::ScreenUpdateMove(CGFloat delta_x, | |
| 1015 CGFloat delta_y, | |
| 1016 size_t count, | |
| 1017 const CGRect* rect_array) { | |
| 1018 // Translate |rect_array| to identify the move's destination. | |
| 1019 CGRect refresh_rects[count]; | |
| 1020 for (CGRectCount i = 0; i < count; ++i) { | |
| 1021 refresh_rects[i] = CGRectOffset(rect_array[i], delta_x, delta_y); | |
| 1022 } | |
| 1023 | |
| 1024 // Currently we just treat move events the same as refreshes. | |
| 1025 ScreenRefresh(count, refresh_rects); | |
| 1026 } | |
| 1027 | |
| 1028 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count, | |
| 1029 const CGRect* rect_array) { | |
| 1030 if (screen_pixel_bounds_.is_empty()) | |
| 1031 ScreenConfigurationChanged(); | |
| 1032 ScreenRefresh(count, rect_array); | |
| 1033 } | |
| 1034 | |
| 1035 std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() { | 1012 std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() { |
| 1036 std::unique_ptr<DesktopFrame> frame( | 1013 std::unique_ptr<DesktopFrame> frame( |
| 1037 new BasicDesktopFrame(screen_pixel_bounds_.size())); | 1014 new BasicDesktopFrame(screen_pixel_bounds_.size())); |
| 1038 frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_, | 1015 frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_, |
| 1039 kStandardDPI * dip_to_pixel_scale_)); | 1016 kStandardDPI * dip_to_pixel_scale_)); |
| 1040 return frame; | 1017 return frame; |
| 1041 } | 1018 } |
| 1042 | 1019 |
| 1043 } // namespace | 1020 } // namespace |
| 1044 | 1021 |
| 1045 // static | 1022 // static |
| 1046 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { | 1023 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { |
| 1047 if (!options.configuration_monitor()) | 1024 if (!options.configuration_monitor()) |
| 1048 return nullptr; | 1025 return nullptr; |
| 1049 | 1026 |
| 1050 std::unique_ptr<ScreenCapturer> capturer( | 1027 std::unique_ptr<ScreenCapturer> capturer( |
| 1051 new ScreenCapturerMac(options.configuration_monitor())); | 1028 new ScreenCapturerMac(options.configuration_monitor())); |
| 1052 if (!static_cast<ScreenCapturerMac*>(capturer.get())->Init()) { | 1029 if (!static_cast<ScreenCapturerMac*>(capturer.get())->Init()) { |
| 1053 return nullptr; | 1030 return nullptr; |
| 1054 } | 1031 } |
| 1055 | 1032 |
| 1056 if (options.detect_updated_region()) { | 1033 if (options.detect_updated_region()) { |
| 1057 capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer))); | 1034 capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer))); |
| 1058 } | 1035 } |
| 1059 | 1036 |
| 1060 return capturer.release(); | 1037 return capturer.release(); |
| 1061 } | 1038 } |
| 1062 | 1039 |
| 1063 } // namespace webrtc | 1040 } // namespace webrtc |
| OLD | NEW |