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

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

Issue 2391743004: Use non-deprecated screen update callbacks. (Closed)
Patch Set: vector -> map 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 struct DisplayStreamWrapper {
Eugene But (OOO till 7-30) 2016/10/04 23:13:52 Do you want to add comments for this?
erikchen 2016/10/04 23:52:39 Done. Note that I added an |owner| field.
49 CGDisplayStreamRef stream = nullptr;
50 int unique_id = 0;
51 bool active = true;
52 };
53
54 // CGDisplayStreamRef needs to be destroyed asynchronously, after a callback
55 // with status kCGDisplayStreamFrameStatusStopped. There's no guarantee that
56 // ScreenCapturerMac will still be around, so we need a global to ensure that
57 // the map from callback to CGDisplayStreamRef is still valid.
58 static std::map<int, DisplayStreamWrapper> g_display_stream_wrappers;
Eugene But (OOO till 7-30) 2016/10/04 23:13:53 I don't think that static global objects are allow
erikchen 2016/10/04 23:52:39 We do use them: https://cs.chromium.org/search/?q=
Eugene But (OOO till 7-30) 2016/10/05 00:19:53 Maybe a function which returns a map reference?:
Sergey Ulanov 2016/10/06 23:57:24 this pattern is used in several places in WebRTC,
59 static int g_unique_id_generator = 0;
60 static rtc::CriticalSection g_display_stream_critical_section;
61
46 // Definitions used to dynamic-link to deprecated OS 10.6 functions. 62 // Definitions used to dynamic-link to deprecated OS 10.6 functions.
47 const char* kApplicationServicesLibraryName = 63 const char* kApplicationServicesLibraryName =
48 "/System/Library/Frameworks/ApplicationServices.framework/" 64 "/System/Library/Frameworks/ApplicationServices.framework/"
49 "ApplicationServices"; 65 "ApplicationServices";
50 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID); 66 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID);
51 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID); 67 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID);
52 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID); 68 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID);
53 const char* kOpenGlLibraryName = 69 const char* kOpenGlLibraryName =
54 "/System/Library/Frameworks/OpenGL.framework/OpenGL"; 70 "/System/Library/Frameworks/OpenGL.framework/OpenGL";
55 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj); 71 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 bool CgBlitPostLion(const DesktopFrame& frame, 227 bool CgBlitPostLion(const DesktopFrame& frame,
212 const DesktopRegion& region); 228 const DesktopRegion& region);
213 229
214 // Called when the screen configuration is changed. 230 // Called when the screen configuration is changed.
215 void ScreenConfigurationChanged(); 231 void ScreenConfigurationChanged();
216 232
217 bool RegisterRefreshAndMoveHandlers(); 233 bool RegisterRefreshAndMoveHandlers();
218 void UnregisterRefreshAndMoveHandlers(); 234 void UnregisterRefreshAndMoveHandlers();
219 235
220 void ScreenRefresh(CGRectCount count, const CGRect *rect_array); 236 void ScreenRefresh(CGRectCount count, const CGRect *rect_array);
221 void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, 237 void ScreenUpdateMove(CGFloat delta_x,
238 CGFloat delta_y,
222 size_t count, 239 size_t count,
223 const CGRect *rect_array); 240 const CGRect* rect_array);
224 static void ScreenRefreshCallback(CGRectCount count, 241 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(); 242 void ReleaseBuffers();
232 243
233 std::unique_ptr<DesktopFrame> CreateFrame(); 244 std::unique_ptr<DesktopFrame> CreateFrame();
234 245
235 Callback* callback_ = nullptr; 246 Callback* callback_ = nullptr;
236 247
237 CGLContextObj cgl_context_ = nullptr; 248 CGLContextObj cgl_context_ = nullptr;
238 ScopedPixelBufferObject pixel_buffer_object_; 249 ScopedPixelBufferObject pixel_buffer_object_;
239 250
240 // Queue of the frames buffers. 251 // Queue of the frames buffers.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 : desktop_config_monitor_(desktop_config_monitor) {} 315 : desktop_config_monitor_(desktop_config_monitor) {}
305 316
306 ScreenCapturerMac::~ScreenCapturerMac() { 317 ScreenCapturerMac::~ScreenCapturerMac() {
307 ReleaseBuffers(); 318 ReleaseBuffers();
308 UnregisterRefreshAndMoveHandlers(); 319 UnregisterRefreshAndMoveHandlers();
309 dlclose(app_services_library_); 320 dlclose(app_services_library_);
310 dlclose(opengl_library_); 321 dlclose(opengl_library_);
311 } 322 }
312 323
313 bool ScreenCapturerMac::Init() { 324 bool ScreenCapturerMac::Init() {
325 desktop_config_monitor_->Lock();
326 desktop_config_ = desktop_config_monitor_->desktop_configuration();
327 desktop_config_monitor_->Unlock();
314 if (!RegisterRefreshAndMoveHandlers()) { 328 if (!RegisterRefreshAndMoveHandlers()) {
315 return false; 329 return false;
316 } 330 }
317 desktop_config_monitor_->Lock();
318 desktop_config_ = desktop_config_monitor_->desktop_configuration();
319 desktop_config_monitor_->Unlock();
320 ScreenConfigurationChanged(); 331 ScreenConfigurationChanged();
321 return true; 332 return true;
322 } 333 }
323 334
324 void ScreenCapturerMac::ReleaseBuffers() { 335 void ScreenCapturerMac::ReleaseBuffers() {
325 if (cgl_context_) { 336 if (cgl_context_) {
326 pixel_buffer_object_.Release(); 337 pixel_buffer_object_.Release();
327 CGLDestroyContext(cgl_context_); 338 CGLDestroyContext(cgl_context_);
328 cgl_context_ = nullptr; 339 cgl_context_ = nullptr;
329 } 340 }
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 (*cgl_set_full_screen_)(cgl_context_); 852 (*cgl_set_full_screen_)(cgl_context_);
842 CGLSetCurrentContext(cgl_context_); 853 CGLSetCurrentContext(cgl_context_);
843 854
844 size_t buffer_size = screen_pixel_bounds_.width() * 855 size_t buffer_size = screen_pixel_bounds_.width() *
845 screen_pixel_bounds_.height() * 856 screen_pixel_bounds_.height() *
846 sizeof(uint32_t); 857 sizeof(uint32_t);
847 pixel_buffer_object_.Init(cgl_context_, buffer_size); 858 pixel_buffer_object_.Init(cgl_context_, buffer_size);
848 } 859 }
849 860
850 bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() { 861 bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
851 CGError err = CGRegisterScreenRefreshCallback( 862 desktop_config_ = desktop_config_monitor_->desktop_configuration();
Eugene But (OOO till 7-30) 2016/10/04 23:13:53 Is this thing can be called on different threads?
erikchen 2016/10/04 23:52:39 Based on the usage of desktop_config_ in the rest
Eugene But (OOO till 7-30) 2016/10/05 00:19:53 So if it is single threaded, then what is the reas
852 ScreenCapturerMac::ScreenRefreshCallback, this); 863 for (MacDisplayConfigurations::iterator it = desktop_config_.displays.begin();
Eugene But (OOO till 7-30) 2016/10/04 23:13:53 NIT: Maybe use auto and for in?
erikchen 2016/10/04 23:52:39 Done.
853 if (err != kCGErrorSuccess) { 864 it != desktop_config_.displays.end(); ++it) {
854 LOG(LS_ERROR) << "CGRegisterScreenRefreshCallback " << err; 865 size_t pixel_width = it->pixel_bounds.width();
855 return false; 866 size_t pixel_height = it->pixel_bounds.height();
856 } 867 if (pixel_width == 0 || pixel_height == 0)
868 continue;
869 int unique_id;
Eugene But (OOO till 7-30) 2016/10/04 23:13:53 Please initialize
erikchen 2016/10/04 23:52:39 Done.
870 {
871 rtc::CritScope scoper(&g_display_stream_critical_section);
872 unique_id = ++g_unique_id_generator;
873 }
874 CGDirectDisplayID display_id = it->id;
875 CGDisplayStreamFrameAvailableHandler handler =
876 ^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
Eugene But (OOO till 7-30) 2016/10/04 23:13:53 s/displayTime/display_time
erikchen 2016/10/04 23:52:39 Done.
877 IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
Eugene But (OOO till 7-30) 2016/10/04 23:13:53 s/frameSurface/frame_surface s/updateRef/update_re
Eugene But (OOO till 7-30) 2016/10/04 23:13:53 Is this hander called on different thread (other t
erikchen 2016/10/04 23:52:39 No. The reason for the lock I added was to deal wi
erikchen 2016/10/04 23:52:39 Done.
Eugene But (OOO till 7-30) 2016/10/05 00:19:53 So if |g_display_stream_wrappers| is always access
878 if (status == kCGDisplayStreamFrameStatusStopped) {
879 rtc::CritScope scoper(&g_display_stream_critical_section);
880 auto it = g_display_stream_wrappers.find(unique_id);
881 assert(it != g_display_stream_wrappers.end());
Eugene But (OOO till 7-30) 2016/10/04 23:13:52 Should this be DCHECK?
erikchen 2016/10/04 23:52:39 I think the answer is no. Assuming we don't immedi
882 assert(!it->second.active);
883 CFRelease(it->second.stream);
884 g_display_stream_wrappers.erase(it);
885 return;
886 }
857 887
858 err = CGScreenRegisterMoveCallback( 888 // Only pay attention to frame updates.
859 ScreenCapturerMac::ScreenUpdateMoveCallback, this); 889 if (status != kCGDisplayStreamFrameStatusFrameComplete)
860 if (err != kCGErrorSuccess) { 890 return;
861 LOG(LS_ERROR) << "CGScreenRegisterMoveCallback " << err; 891
862 return false; 892 size_t count = 0;
893 const CGRect* rects = CGDisplayStreamUpdateGetRects(
894 updateRef, kCGDisplayStreamUpdateMovedRects, &count);
895 if (count != 0) {
896 CGFloat dx = 0;
897 CGFloat dy = 0;
898 CGDisplayStreamUpdateGetMovedRectsDelta(updateRef, &dx, &dy);
899 ScreenUpdateMove(dx, dy, count, rects);
900 }
901
902 count = 0;
903 rects = CGDisplayStreamUpdateGetRects(
904 updateRef, kCGDisplayStreamUpdateRefreshedRects, &count);
905 if (count != 0) {
906 ScreenRefreshCallback(count, rects);
907 }
908 };
909 CGDisplayStreamRef display_stream = CGDisplayStreamCreate(
910 display_id, pixel_width, pixel_height, 'BGRA', nullptr, handler);
911 if (display_stream) {
912 DisplayStreamWrapper wrapper;
913 wrapper.stream = display_stream;
914 wrapper.unique_id = unique_id;
915 {
916 rtc::CritScope scoper(&g_display_stream_critical_section);
917 assert(g_display_stream_wrappers.find(unique_id) ==
918 g_display_stream_wrappers.end());
919 g_display_stream_wrappers[unique_id] = wrapper;
920 }
921 CGDisplayStreamStart(display_stream);
922 }
863 } 923 }
864 924
865 return true; 925 return true;
866 } 926 }
867 927
868 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { 928 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() {
869 CGUnregisterScreenRefreshCallback( 929 rtc::CritScope scoper(&g_display_stream_critical_section);
870 ScreenCapturerMac::ScreenRefreshCallback, this); 930 for (auto& pair : g_display_stream_wrappers) {
871 CGScreenUnregisterMoveCallback( 931 DisplayStreamWrapper& wrapper = pair.second;
872 ScreenCapturerMac::ScreenUpdateMoveCallback, this); 932 if (wrapper.active) {
933 wrapper.active = false;
934 CGDisplayStreamStop(wrapper.stream);
935 }
936 }
873 } 937 }
874 938
875 void ScreenCapturerMac::ScreenRefresh(CGRectCount count, 939 void ScreenCapturerMac::ScreenRefresh(CGRectCount count,
876 const CGRect* rect_array) { 940 const CGRect* rect_array) {
877 if (screen_pixel_bounds_.is_empty()) 941 if (screen_pixel_bounds_.is_empty())
878 return; 942 return;
879 943
880 DesktopRegion region; 944 DesktopRegion region;
881 DesktopVector translate_vector = 945 DesktopVector translate_vector =
882 DesktopVector().subtract(screen_pixel_bounds_.top_left()); 946 DesktopVector().subtract(screen_pixel_bounds_.top_left());
883 for (CGRectCount i = 0; i < count; ++i) { 947 for (CGRectCount i = 0; i < count; ++i) {
884 // Convert from Density-Independent Pixel to physical pixel coordinates. 948 // Convert from Density-Independent Pixel to physical pixel coordinates.
885 DesktopRect rect = ScaleAndRoundCGRect(rect_array[i], dip_to_pixel_scale_); 949 DesktopRect rect = ScaleAndRoundCGRect(rect_array[i], dip_to_pixel_scale_);
886 // Translate from local desktop to capturer framebuffer coordinates. 950 // Translate from local desktop to capturer framebuffer coordinates.
887 rect.Translate(translate_vector); 951 rect.Translate(translate_vector);
888 region.AddRect(rect); 952 region.AddRect(rect);
889 } 953 }
890 954
891 helper_.InvalidateRegion(region); 955 helper_.InvalidateRegion(region);
892 } 956 }
893 957
894 void ScreenCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, 958 void ScreenCapturerMac::ScreenUpdateMove(CGFloat delta_x,
959 CGFloat delta_y,
895 size_t count, 960 size_t count,
896 const CGRect* rect_array) { 961 const CGRect* rect_array) {
897 // Translate |rect_array| to identify the move's destination. 962 // Translate |rect_array| to identify the move's destination.
898 CGRect refresh_rects[count]; 963 CGRect refresh_rects[count];
899 for (CGRectCount i = 0; i < count; ++i) { 964 for (CGRectCount i = 0; i < count; ++i) {
900 refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY); 965 refresh_rects[i] = CGRectOffset(rect_array[i], delta_x, delta_y);
901 } 966 }
902 967
903 // Currently we just treat move events the same as refreshes. 968 // Currently we just treat move events the same as refreshes.
904 ScreenRefresh(count, refresh_rects); 969 ScreenRefresh(count, refresh_rects);
905 } 970 }
906 971
907 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count, 972 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count,
908 const CGRect* rect_array, 973 const CGRect* rect_array) {
909 void* user_parameter) { 974 if (screen_pixel_bounds_.is_empty())
910 ScreenCapturerMac* capturer = 975 ScreenConfigurationChanged();
911 reinterpret_cast<ScreenCapturerMac*>(user_parameter); 976 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 } 977 }
926 978
927 std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() { 979 std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() {
928 std::unique_ptr<DesktopFrame> frame( 980 std::unique_ptr<DesktopFrame> frame(
929 new BasicDesktopFrame(screen_pixel_bounds_.size())); 981 new BasicDesktopFrame(screen_pixel_bounds_.size()));
930 frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_, 982 frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_,
931 kStandardDPI * dip_to_pixel_scale_)); 983 kStandardDPI * dip_to_pixel_scale_));
932 return frame; 984 return frame;
933 } 985 }
934 986
(...skipping 11 matching lines...) Expand all
946 } 998 }
947 999
948 if (options.detect_updated_region()) { 1000 if (options.detect_updated_region()) {
949 capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer))); 1001 capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer)));
950 } 1002 }
951 1003
952 return capturer.release(); 1004 return capturer.release();
953 } 1005 }
954 1006
955 } // namespace webrtc 1007 } // 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