Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: webrtc/modules/desktop_capture/screen_capturer_mac.mm

Issue 2417603002: Several fixes to screen capturer mac. (Closed)
Patch Set: nits Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698