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

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

Issue 2391743004: Use non-deprecated screen update callbacks. (Closed)
Patch Set: Clang format. 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
11 #include "webrtc/modules/desktop_capture/screen_capturer.h" 11 #include "webrtc/modules/desktop_capture/screen_capturer.h"
12 12
13 #include <stddef.h> 13 #include <stddef.h>
14 14
15 #include <memory> 15 #include <memory>
16 #include <set> 16 #include <set>
17 #include <utility> 17 #include <utility>
18 18
19 #include <ApplicationServices/ApplicationServices.h> 19 #include <ApplicationServices/ApplicationServices.h>
20 #include <Cocoa/Cocoa.h> 20 #include <Cocoa/Cocoa.h>
21 #include <CoreGraphics/CoreGraphics.h>
21 #include <dlfcn.h> 22 #include <dlfcn.h>
22 #include <OpenGL/CGLMacro.h> 23 #include <OpenGL/CGLMacro.h>
23 #include <OpenGL/OpenGL.h> 24 #include <OpenGL/OpenGL.h>
24 25
25 #include "webrtc/base/checks.h" 26 #include "webrtc/base/checks.h"
26 #include "webrtc/base/constructormagic.h" 27 #include "webrtc/base/constructormagic.h"
27 #include "webrtc/base/macutils.h" 28 #include "webrtc/base/macutils.h"
29 #include "webrtc/base/criticalsection.h"
28 #include "webrtc/base/timeutils.h" 30 #include "webrtc/base/timeutils.h"
29 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" 31 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
30 #include "webrtc/modules/desktop_capture/desktop_frame.h" 32 #include "webrtc/modules/desktop_capture/desktop_frame.h"
31 #include "webrtc/modules/desktop_capture/desktop_geometry.h" 33 #include "webrtc/modules/desktop_capture/desktop_geometry.h"
32 #include "webrtc/modules/desktop_capture/desktop_region.h" 34 #include "webrtc/modules/desktop_capture/desktop_region.h"
33 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" 35 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
34 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h" 36 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
35 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h" 37 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h"
36 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" 38 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
37 #include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h" 39 #include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h"
38 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" 40 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h"
39 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" 41 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
40 #include "webrtc/system_wrappers/include/logging.h" 42 #include "webrtc/system_wrappers/include/logging.h"
41 43
42 namespace webrtc { 44 namespace webrtc {
43 45
44 namespace { 46 namespace {
45 47
48 // This container (in conjunction with g_display_stream_wrappers) has two
49 // purposes:
50 // 1) Maps from unique id to CGDisplayStreamRef, to allow destruction of the
51 // appropriate CGDisplayStreamRef from the callback.
52 // 2) Adds sufficient metadata to map ownership of active CGDisplayStreamRefs
53 // to ScreenCapturerMac. This could theoretically be done with another
54 // instance-scoped container in ScreenCapturerMac, but having a single, global
55 // container seems cleaner.
56 struct DisplayStreamWrapper {
57 // The registered CGDisplayStreamRef.
58 CGDisplayStreamRef stream = nullptr;
59
60 // Once |stream| has been stopped, this parameter is set to false. Only after
61 // an asynchronous callback from CoreGraphics can CGDisplayStreamRef be
62 // destroyed.
63 bool active = true;
64
65 // Metadata that allow instances of ScreenCapturerMac to determine whether
66 // they own |stream|.
67 void* owner = nullptr;
Sergey Ulanov 2016/10/06 23:51:33 Maybe make this ScreenCapturerMac*?
erikchen 2016/10/07 17:56:19 Rewrote to use a self-owned manager rather than a
68 };
69
70 // CGDisplayStreamRef needs to be destroyed asynchronously, after a callback
71 // with status kCGDisplayStreamFrameStatusStopped. There's no guarantee that
72 // ScreenCapturerMac will still be around, so we need a global to maintain the
73 // mapping from callback to CGDisplayStreamRef.
74 static std::map<int, DisplayStreamWrapper> g_display_stream_wrappers;
75 static int g_unique_id_generator = 0;
76 static rtc::CriticalSection g_display_stream_critical_section;
Sergey Ulanov 2016/10/06 23:51:33 This and g_display_stream_wrappers will require st
erikchen 2016/10/07 17:56:19 no more statics and globals. :)
77
46 // Definitions used to dynamic-link to deprecated OS 10.6 functions. 78 // Definitions used to dynamic-link to deprecated OS 10.6 functions.
47 const char* kApplicationServicesLibraryName = 79 const char* kApplicationServicesLibraryName =
48 "/System/Library/Frameworks/ApplicationServices.framework/" 80 "/System/Library/Frameworks/ApplicationServices.framework/"
49 "ApplicationServices"; 81 "ApplicationServices";
50 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID); 82 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID);
51 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID); 83 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID);
52 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID); 84 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID);
53 const char* kOpenGlLibraryName = 85 const char* kOpenGlLibraryName =
54 "/System/Library/Frameworks/OpenGL.framework/OpenGL"; 86 "/System/Library/Frameworks/OpenGL.framework/OpenGL";
55 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj); 87 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 bool CgBlitPostLion(const DesktopFrame& frame, 243 bool CgBlitPostLion(const DesktopFrame& frame,
212 const DesktopRegion& region); 244 const DesktopRegion& region);
213 245
214 // Called when the screen configuration is changed. 246 // Called when the screen configuration is changed.
215 void ScreenConfigurationChanged(); 247 void ScreenConfigurationChanged();
216 248
217 bool RegisterRefreshAndMoveHandlers(); 249 bool RegisterRefreshAndMoveHandlers();
218 void UnregisterRefreshAndMoveHandlers(); 250 void UnregisterRefreshAndMoveHandlers();
219 251
220 void ScreenRefresh(CGRectCount count, const CGRect *rect_array); 252 void ScreenRefresh(CGRectCount count, const CGRect *rect_array);
221 void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, 253 void ScreenUpdateMove(CGFloat delta_x,
254 CGFloat delta_y,
222 size_t count, 255 size_t count,
223 const CGRect *rect_array); 256 const CGRect* rect_array);
224 static void ScreenRefreshCallback(CGRectCount count, 257 void ScreenRefreshCallback(CGRectCount count, const CGRect* rect_array);
225 const CGRect *rect_array,
226 void *user_parameter);
227 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta,
228 size_t count,
229 const CGRect *rect_array,
230 void *user_parameter);
231 void ReleaseBuffers(); 258 void ReleaseBuffers();
232 259
233 std::unique_ptr<DesktopFrame> CreateFrame(); 260 std::unique_ptr<DesktopFrame> CreateFrame();
234 261
235 Callback* callback_ = nullptr; 262 Callback* callback_ = nullptr;
236 263
237 CGLContextObj cgl_context_ = nullptr; 264 CGLContextObj cgl_context_ = nullptr;
238 ScopedPixelBufferObject pixel_buffer_object_; 265 ScopedPixelBufferObject pixel_buffer_object_;
239 266
240 // Queue of the frames buffers. 267 // Queue of the frames buffers.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 : desktop_config_monitor_(desktop_config_monitor) {} 331 : desktop_config_monitor_(desktop_config_monitor) {}
305 332
306 ScreenCapturerMac::~ScreenCapturerMac() { 333 ScreenCapturerMac::~ScreenCapturerMac() {
307 ReleaseBuffers(); 334 ReleaseBuffers();
308 UnregisterRefreshAndMoveHandlers(); 335 UnregisterRefreshAndMoveHandlers();
309 dlclose(app_services_library_); 336 dlclose(app_services_library_);
310 dlclose(opengl_library_); 337 dlclose(opengl_library_);
311 } 338 }
312 339
313 bool ScreenCapturerMac::Init() { 340 bool ScreenCapturerMac::Init() {
341 desktop_config_monitor_->Lock();
342 desktop_config_ = desktop_config_monitor_->desktop_configuration();
343 desktop_config_monitor_->Unlock();
314 if (!RegisterRefreshAndMoveHandlers()) { 344 if (!RegisterRefreshAndMoveHandlers()) {
315 return false; 345 return false;
316 } 346 }
317 desktop_config_monitor_->Lock();
318 desktop_config_ = desktop_config_monitor_->desktop_configuration();
319 desktop_config_monitor_->Unlock();
320 ScreenConfigurationChanged(); 347 ScreenConfigurationChanged();
321 return true; 348 return true;
322 } 349 }
323 350
324 void ScreenCapturerMac::ReleaseBuffers() { 351 void ScreenCapturerMac::ReleaseBuffers() {
325 if (cgl_context_) { 352 if (cgl_context_) {
326 pixel_buffer_object_.Release(); 353 pixel_buffer_object_.Release();
327 CGLDestroyContext(cgl_context_); 354 CGLDestroyContext(cgl_context_);
328 cgl_context_ = nullptr; 355 cgl_context_ = nullptr;
329 } 356 }
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 (*cgl_set_full_screen_)(cgl_context_); 868 (*cgl_set_full_screen_)(cgl_context_);
842 CGLSetCurrentContext(cgl_context_); 869 CGLSetCurrentContext(cgl_context_);
843 870
844 size_t buffer_size = screen_pixel_bounds_.width() * 871 size_t buffer_size = screen_pixel_bounds_.width() *
845 screen_pixel_bounds_.height() * 872 screen_pixel_bounds_.height() *
846 sizeof(uint32_t); 873 sizeof(uint32_t);
847 pixel_buffer_object_.Init(cgl_context_, buffer_size); 874 pixel_buffer_object_.Init(cgl_context_, buffer_size);
848 } 875 }
849 876
850 bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() { 877 bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
851 CGError err = CGRegisterScreenRefreshCallback( 878 desktop_config_ = desktop_config_monitor_->desktop_configuration();
852 ScreenCapturerMac::ScreenRefreshCallback, this); 879 for (const auto& config : desktop_config_.displays) {
853 if (err != kCGErrorSuccess) { 880 size_t pixel_width = config.pixel_bounds.width();
854 LOG(LS_ERROR) << "CGRegisterScreenRefreshCallback " << err; 881 size_t pixel_height = config.pixel_bounds.height();
855 return false; 882 if (pixel_width == 0 || pixel_height == 0)
856 } 883 continue;
884 int unique_id = 0;
885 {
886 rtc::CritScope scoper(&g_display_stream_critical_section);
887 unique_id = ++g_unique_id_generator;
888 }
889 CGDirectDisplayID display_id = config.id;
890 CGDisplayStreamFrameAvailableHandler handler =
891 ^(CGDisplayStreamFrameStatus status, uint64_t display_time,
892 IOSurfaceRef frame_surface, CGDisplayStreamUpdateRef updateRef) {
Sergey Ulanov 2016/10/06 23:51:33 nit: one argument per line in function definition
erikchen 2016/10/07 17:56:20 this is from clang-format.
893 if (status == kCGDisplayStreamFrameStatusStopped) {
894 rtc::CritScope scoper(&g_display_stream_critical_section);
895 auto it = g_display_stream_wrappers.find(unique_id);
896 assert(it != g_display_stream_wrappers.end());
Sergey Ulanov 2016/10/06 23:51:33 Please use RTC_DCHECK() instead of assert()
erikchen 2016/10/07 17:56:19 I switched to RTC_CHECK. I think these should not
897 assert(!it->second.active);
898 CFRelease(it->second.stream);
899 g_display_stream_wrappers.erase(it);
900 return;
901 }
857 902
858 err = CGScreenRegisterMoveCallback( 903 // Only pay attention to frame updates.
859 ScreenCapturerMac::ScreenUpdateMoveCallback, this); 904 if (status != kCGDisplayStreamFrameStatusFrameComplete)
860 if (err != kCGErrorSuccess) { 905 return;
861 LOG(LS_ERROR) << "CGScreenRegisterMoveCallback " << err; 906
862 return false; 907 size_t count = 0;
908 const CGRect* rects = CGDisplayStreamUpdateGetRects(
909 updateRef, kCGDisplayStreamUpdateMovedRects, &count);
Sergey Ulanov 2016/10/06 23:51:33 I think you can use kCGDisplayStreamUpdateDirtyRec
erikchen 2016/10/07 17:56:19 Yes, but then we can't distinguish between the two
Sergey Ulanov 2016/10/10 21:03:51 We don't need to distinguish between them. In both
910 if (count != 0) {
911 CGFloat dx = 0;
912 CGFloat dy = 0;
913 CGDisplayStreamUpdateGetMovedRectsDelta(updateRef, &dx, &dy);
914 ScreenUpdateMove(dx, dy, count, rects);
915 }
916
917 count = 0;
918 rects = CGDisplayStreamUpdateGetRects(
919 updateRef, kCGDisplayStreamUpdateRefreshedRects, &count);
920 if (count != 0) {
921 // According to CGDisplayStream.h, it's safe to call
922 // CGDisplayStreamStop() from within the callback.
923 ScreenRefreshCallback(count, rects);
924 }
925 };
926 CGDisplayStreamRef display_stream = CGDisplayStreamCreate(
927 display_id, pixel_width, pixel_height, 'BGRA', nullptr, handler);
928 if (display_stream) {
929 DisplayStreamWrapper wrapper;
930 wrapper.stream = display_stream;
931 wrapper.owner = this;
932 {
933 rtc::CritScope scoper(&g_display_stream_critical_section);
934 assert(g_display_stream_wrappers.find(unique_id) ==
935 g_display_stream_wrappers.end());
936 g_display_stream_wrappers[unique_id] = wrapper;
937 }
938 CGDisplayStreamStart(display_stream);
939 }
863 } 940 }
864 941
865 return true; 942 return true;
866 } 943 }
867 944
868 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { 945 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() {
869 CGUnregisterScreenRefreshCallback( 946 rtc::CritScope scoper(&g_display_stream_critical_section);
870 ScreenCapturerMac::ScreenRefreshCallback, this); 947 for (auto& pair : g_display_stream_wrappers) {
871 CGScreenUnregisterMoveCallback( 948 DisplayStreamWrapper& wrapper = pair.second;
872 ScreenCapturerMac::ScreenUpdateMoveCallback, this); 949 if (wrapper.active && wrapper.owner == this) {
950 wrapper.active = false;
951 CGDisplayStreamStop(wrapper.stream);
952 }
953 }
873 } 954 }
874 955
875 void ScreenCapturerMac::ScreenRefresh(CGRectCount count, 956 void ScreenCapturerMac::ScreenRefresh(CGRectCount count,
876 const CGRect* rect_array) { 957 const CGRect* rect_array) {
877 if (screen_pixel_bounds_.is_empty()) 958 if (screen_pixel_bounds_.is_empty())
878 return; 959 return;
879 960
880 DesktopRegion region; 961 DesktopRegion region;
881 DesktopVector translate_vector = 962 DesktopVector translate_vector =
882 DesktopVector().subtract(screen_pixel_bounds_.top_left()); 963 DesktopVector().subtract(screen_pixel_bounds_.top_left());
883 for (CGRectCount i = 0; i < count; ++i) { 964 for (CGRectCount i = 0; i < count; ++i) {
884 // Convert from Density-Independent Pixel to physical pixel coordinates. 965 // Convert from Density-Independent Pixel to physical pixel coordinates.
885 DesktopRect rect = ScaleAndRoundCGRect(rect_array[i], dip_to_pixel_scale_); 966 DesktopRect rect = ScaleAndRoundCGRect(rect_array[i], dip_to_pixel_scale_);
886 // Translate from local desktop to capturer framebuffer coordinates. 967 // Translate from local desktop to capturer framebuffer coordinates.
887 rect.Translate(translate_vector); 968 rect.Translate(translate_vector);
888 region.AddRect(rect); 969 region.AddRect(rect);
889 } 970 }
890 971
891 helper_.InvalidateRegion(region); 972 helper_.InvalidateRegion(region);
892 } 973 }
893 974
894 void ScreenCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, 975 void ScreenCapturerMac::ScreenUpdateMove(CGFloat delta_x,
976 CGFloat delta_y,
895 size_t count, 977 size_t count,
896 const CGRect* rect_array) { 978 const CGRect* rect_array) {
897 // Translate |rect_array| to identify the move's destination. 979 // Translate |rect_array| to identify the move's destination.
898 CGRect refresh_rects[count]; 980 CGRect refresh_rects[count];
899 for (CGRectCount i = 0; i < count; ++i) { 981 for (CGRectCount i = 0; i < count; ++i) {
900 refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY); 982 refresh_rects[i] = CGRectOffset(rect_array[i], delta_x, delta_y);
901 } 983 }
902 984
903 // Currently we just treat move events the same as refreshes. 985 // Currently we just treat move events the same as refreshes.
904 ScreenRefresh(count, refresh_rects); 986 ScreenRefresh(count, refresh_rects);
905 } 987 }
906 988
907 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count, 989 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count,
908 const CGRect* rect_array, 990 const CGRect* rect_array) {
909 void* user_parameter) { 991 if (screen_pixel_bounds_.is_empty())
910 ScreenCapturerMac* capturer = 992 ScreenConfigurationChanged();
911 reinterpret_cast<ScreenCapturerMac*>(user_parameter); 993 ScreenRefresh(count, rect_array);
912 if (capturer->screen_pixel_bounds_.is_empty())
913 capturer->ScreenConfigurationChanged();
914 capturer->ScreenRefresh(count, rect_array);
915 }
916
917 void ScreenCapturerMac::ScreenUpdateMoveCallback(
918 CGScreenUpdateMoveDelta delta,
919 size_t count,
920 const CGRect* rect_array,
921 void* user_parameter) {
922 ScreenCapturerMac* capturer =
923 reinterpret_cast<ScreenCapturerMac*>(user_parameter);
924 capturer->ScreenUpdateMove(delta, count, rect_array);
925 } 994 }
926 995
927 std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() { 996 std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() {
928 std::unique_ptr<DesktopFrame> frame( 997 std::unique_ptr<DesktopFrame> frame(
929 new BasicDesktopFrame(screen_pixel_bounds_.size())); 998 new BasicDesktopFrame(screen_pixel_bounds_.size()));
930 frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_, 999 frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_,
931 kStandardDPI * dip_to_pixel_scale_)); 1000 kStandardDPI * dip_to_pixel_scale_));
932 return frame; 1001 return frame;
933 } 1002 }
934 1003
(...skipping 11 matching lines...) Expand all
946 } 1015 }
947 1016
948 if (options.detect_updated_region()) { 1017 if (options.detect_updated_region()) {
949 capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer))); 1018 capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer)));
950 } 1019 }
951 1020
952 return capturer.release(); 1021 return capturer.release();
953 } 1022 }
954 1023
955 } // namespace webrtc 1024 } // 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