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

Side by Side Diff: media/video/capture/screen/screen_capturer_mac.mm

Issue 13983010: Use webrtc::DesktopCapturer for screen capturer implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/video/capture/screen/screen_capturer.h" 5 #include "media/video/capture/screen/screen_capturer.h"
6 6
7 #include <ApplicationServices/ApplicationServices.h> 7 #include <ApplicationServices/ApplicationServices.h>
8 #include <Cocoa/Cocoa.h> 8 #include <Cocoa/Cocoa.h>
9 #include <dlfcn.h> 9 #include <dlfcn.h>
10 #include <IOKit/pwr_mgt/IOPMLib.h> 10 #include <IOKit/pwr_mgt/IOPMLib.h>
11 #include <OpenGL/CGLMacro.h> 11 #include <OpenGL/CGLMacro.h>
12 #include <OpenGL/OpenGL.h> 12 #include <OpenGL/OpenGL.h>
13 #include <stddef.h> 13 #include <stddef.h>
14 #include <set> 14 #include <set>
15 15
16 #include "base/files/file_path.h" 16 #include "base/files/file_path.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/mac/mac_util.h" 18 #include "base/mac/mac_util.h"
19 #include "base/mac/scoped_cftyperef.h" 19 #include "base/mac/scoped_cftyperef.h"
20 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
21 #include "base/scoped_native_library.h" 21 #include "base/scoped_native_library.h"
22 #include "base/synchronization/waitable_event.h" 22 #include "base/synchronization/waitable_event.h"
23 #include "base/time.h" 23 #include "base/time.h"
24 #include "media/video/capture/screen/mac/desktop_configuration.h" 24 #include "media/video/capture/screen/mac/desktop_configuration.h"
25 #include "media/video/capture/screen/mac/scoped_pixel_buffer_object.h" 25 #include "media/video/capture/screen/mac/scoped_pixel_buffer_object.h"
26 #include "media/video/capture/screen/mouse_cursor_shape.h" 26 #include "media/video/capture/screen/mouse_cursor_shape.h"
27 #include "media/video/capture/screen/screen_capture_data.h"
28 #include "media/video/capture/screen/screen_capture_frame.h"
29 #include "media/video/capture/screen/screen_capture_frame_queue.h" 27 #include "media/video/capture/screen/screen_capture_frame_queue.h"
30 #include "media/video/capture/screen/screen_capturer_helper.h" 28 #include "media/video/capture/screen/screen_capturer_helper.h"
31 #include "skia/ext/skia_utils_mac.h" 29 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
30 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
31 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
32 32
33 namespace media { 33 namespace media {
34 34
35 namespace { 35 namespace {
36 36
37 // Definitions used to dynamic-link to deprecated OS 10.6 functions. 37 // Definitions used to dynamic-link to deprecated OS 10.6 functions.
38 const char* kApplicationServicesLibraryName = 38 const char* kApplicationServicesLibraryName =
39 "/System/Library/Frameworks/ApplicationServices.framework/" 39 "/System/Library/Frameworks/ApplicationServices.framework/"
40 "ApplicationServices"; 40 "ApplicationServices";
41 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID); 41 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID);
42 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID); 42 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID);
43 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID); 43 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID);
44 const char* kOpenGlLibraryName = 44 const char* kOpenGlLibraryName =
45 "/System/Library/Frameworks/OpenGL.framework/OpenGL"; 45 "/System/Library/Frameworks/OpenGL.framework/OpenGL";
46 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj); 46 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj);
47 47
48 // Standard Mac displays have 72dpi, but we report 96dpi for 48 // Standard Mac displays have 72dpi, but we report 96dpi for
49 // consistency with Windows and Linux. 49 // consistency with Windows and Linux.
50 const int kStandardDPI = 96; 50 const int kStandardDPI = 96;
51 51
52 // skia/ext/skia_utils_mac.h only defines CGRectToSkRect(). 52 // Scales all coordinates of a rect by a specified factor.
53 SkIRect CGRectToSkIRect(const CGRect& rect) { 53 webrtc::DesktopRect ScaleAndRoundCGRect(const CGRect& rect, float scale) {
54 SkIRect result; 54 return webrtc::DesktopRect::MakeLTRB(
55 gfx::CGRectToSkRect(rect).round(&result); 55 static_cast<int>(floor(rect.origin.x * scale)),
56 return result; 56 static_cast<int>(floor(rect.origin.y * scale)),
57 } 57 static_cast<int>(ceil((rect.origin.x + rect.size.width) * scale)),
58 58 static_cast<int>(ceil((rect.origin.y + rect.size.height) * scale)));
59 // Scales all coordinates of an SkRect by a specified factor.
60 SkRect ScaleSkRect(const SkRect& rect, float scale) {
61 SkRect result = {
62 rect.left() * scale, rect.top() * scale,
63 rect.right() * scale, rect.bottom() * scale
64 };
65 return result;
66 } 59 }
67 60
68 // Copy pixels in the |rect| from |src_place| to |dest_plane|. 61 // Copy pixels in the |rect| from |src_place| to |dest_plane|.
69 void CopyRect(const uint8* src_plane, 62 void CopyRect(const uint8* src_plane,
70 int src_plane_stride, 63 int src_plane_stride,
71 uint8* dest_plane, 64 uint8* dest_plane,
72 int dest_plane_stride, 65 int dest_plane_stride,
73 int bytes_per_pixel, 66 int bytes_per_pixel,
74 const SkIRect& rect) { 67 const webrtc::DesktopRect& rect) {
75 // Get the address of the starting point. 68 // Get the address of the starting point.
76 const int src_y_offset = src_plane_stride * rect.top(); 69 const int src_y_offset = src_plane_stride * rect.top();
77 const int dest_y_offset = dest_plane_stride * rect.top(); 70 const int dest_y_offset = dest_plane_stride * rect.top();
78 const int x_offset = bytes_per_pixel * rect.left(); 71 const int x_offset = bytes_per_pixel * rect.left();
79 src_plane += src_y_offset + x_offset; 72 src_plane += src_y_offset + x_offset;
80 dest_plane += dest_y_offset + x_offset; 73 dest_plane += dest_y_offset + x_offset;
81 74
82 // Copy pixels in the rectangle line by line. 75 // Copy pixels in the rectangle line by line.
83 const int bytes_per_line = bytes_per_pixel * rect.width(); 76 const int bytes_per_line = bytes_per_pixel * rect.width();
84 const int height = rect.height(); 77 const int height = rect.height();
85 for (int i = 0 ; i < height; ++i) { 78 for (int i = 0 ; i < height; ++i) {
86 memcpy(dest_plane, src_plane, bytes_per_line); 79 memcpy(dest_plane, src_plane, bytes_per_line);
87 src_plane += src_plane_stride; 80 src_plane += src_plane_stride;
88 dest_plane += dest_plane_stride; 81 dest_plane += dest_plane_stride;
89 } 82 }
90 } 83 }
91 84
92 // The amount of time allowed for displays to reconfigure. 85 // The amount of time allowed for displays to reconfigure.
93 const int64 kDisplayConfigurationEventTimeoutInSeconds = 10; 86 const int64 kDisplayConfigurationEventTimeoutInSeconds = 10;
94 87
95 // A class representing a full-frame pixel buffer.
96 class ScreenCaptureFrameMac : public ScreenCaptureFrame {
97 public:
98 explicit ScreenCaptureFrameMac(const MacDesktopConfiguration& desktop_config);
99 virtual ~ScreenCaptureFrameMac();
100
101 const SkIPoint& dpi() const { return dpi_; }
102
103 private:
104 // Allocated pixel buffer.
105 scoped_ptr<uint8[]> data_;
106
107 // DPI settings for this buffer.
108 SkIPoint dpi_;
109
110 DISALLOW_COPY_AND_ASSIGN(ScreenCaptureFrameMac);
111 };
112
113 // A class to perform video frame capturing for mac. 88 // A class to perform video frame capturing for mac.
114 class ScreenCapturerMac : public ScreenCapturer { 89 class ScreenCapturerMac : public ScreenCapturer {
115 public: 90 public:
116 ScreenCapturerMac(); 91 ScreenCapturerMac();
117 virtual ~ScreenCapturerMac(); 92 virtual ~ScreenCapturerMac();
118 93
119 bool Init(); 94 bool Init();
120 95
121 // Overridden from ScreenCapturer: 96 // Overridden from ScreenCapturer:
122 virtual void Start(Delegate* delegate) OVERRIDE; 97 virtual void Start(Callback* callback) OVERRIDE;
123 virtual void CaptureFrame() OVERRIDE; 98 virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE;
99 virtual void SetMouseShapeObserver(
100 MouseShapeObserver* mouse_shape_observer) OVERRIDE;
124 101
125 private: 102 private:
126 void CaptureCursor(); 103 void CaptureCursor();
127 104
128 void GlBlitFast(const ScreenCaptureFrame& buffer, const SkRegion& region); 105 void GlBlitFast(const webrtc::DesktopFrame& frame,
129 void GlBlitSlow(const ScreenCaptureFrame& buffer); 106 const webrtc::DesktopRegion& region);
130 void CgBlitPreLion(const ScreenCaptureFrame& buffer, const SkRegion& region); 107 void GlBlitSlow(const webrtc::DesktopFrame& frame);
131 void CgBlitPostLion(const ScreenCaptureFrame& buffer, const SkRegion& region); 108 void CgBlitPreLion(const webrtc::DesktopFrame& frame,
109 const webrtc::DesktopRegion& region);
110 void CgBlitPostLion(const webrtc::DesktopFrame& frame,
111 const webrtc::DesktopRegion& region);
132 112
133 // Called when the screen configuration is changed. 113 // Called when the screen configuration is changed.
134 void ScreenConfigurationChanged(); 114 void ScreenConfigurationChanged();
135 115
136 bool RegisterRefreshAndMoveHandlers(); 116 bool RegisterRefreshAndMoveHandlers();
137 void UnregisterRefreshAndMoveHandlers(); 117 void UnregisterRefreshAndMoveHandlers();
138 118
139 void ScreenRefresh(CGRectCount count, const CGRect *rect_array); 119 void ScreenRefresh(CGRectCount count, const CGRect *rect_array);
140 void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, 120 void ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
141 size_t count, 121 size_t count,
142 const CGRect *rect_array); 122 const CGRect *rect_array);
143 void DisplaysReconfigured(CGDirectDisplayID display, 123 void DisplaysReconfigured(CGDirectDisplayID display,
144 CGDisplayChangeSummaryFlags flags); 124 CGDisplayChangeSummaryFlags flags);
145 static void ScreenRefreshCallback(CGRectCount count, 125 static void ScreenRefreshCallback(CGRectCount count,
146 const CGRect *rect_array, 126 const CGRect *rect_array,
147 void *user_parameter); 127 void *user_parameter);
148 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, 128 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta,
149 size_t count, 129 size_t count,
150 const CGRect *rect_array, 130 const CGRect *rect_array,
151 void *user_parameter); 131 void *user_parameter);
152 static void DisplaysReconfiguredCallback(CGDirectDisplayID display, 132 static void DisplaysReconfiguredCallback(CGDirectDisplayID display,
153 CGDisplayChangeSummaryFlags flags, 133 CGDisplayChangeSummaryFlags flags,
154 void *user_parameter); 134 void *user_parameter);
155 135
156 void ReleaseBuffers(); 136 void ReleaseBuffers();
157 137
158 Delegate* delegate_; 138 Callback* callback_;
139 MouseShapeObserver* mouse_shape_observer_;
159 140
160 CGLContextObj cgl_context_; 141 CGLContextObj cgl_context_;
161 ScopedPixelBufferObject pixel_buffer_object_; 142 ScopedPixelBufferObject pixel_buffer_object_;
162 143
163 // Queue of the frames buffers. 144 // Queue of the frames buffers.
164 ScreenCaptureFrameQueue queue_; 145 ScreenCaptureFrameQueue queue_;
165 146
166 // Current display configuration. 147 // Current display configuration.
167 MacDesktopConfiguration desktop_config_; 148 MacDesktopConfiguration desktop_config_;
168 149
169 // A thread-safe list of invalid rectangles, and the size of the most 150 // A thread-safe list of invalid rectangles, and the size of the most
170 // recently captured screen. 151 // recently captured screen.
171 ScreenCapturerHelper helper_; 152 ScreenCapturerHelper helper_;
172 153
173 // Image of the last cursor that we sent to the client. 154 // Image of the last cursor that we sent to the client.
174 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; 155 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_;
175 156
176 // Contains an invalid region from the previous capture. 157 // Contains an invalid region from the previous capture.
177 SkRegion last_invalid_region_; 158 webrtc::DesktopRegion last_invalid_region_;
178 159
179 // Used to ensure that frame captures do not take place while displays 160 // Used to ensure that frame captures do not take place while displays
180 // are being reconfigured. 161 // are being reconfigured.
181 base::WaitableEvent display_configuration_capture_event_; 162 base::WaitableEvent display_configuration_capture_event_;
182 163
183 // Records the Ids of attached displays which are being reconfigured. 164 // Records the Ids of attached displays which are being reconfigured.
184 // Accessed on the thread on which we are notified of display events. 165 // Accessed on the thread on which we are notified of display events.
185 std::set<CGDirectDisplayID> reconfiguring_displays_; 166 std::set<CGDirectDisplayID> reconfiguring_displays_;
186 167
187 // Power management assertion to prevent the screen from sleeping. 168 // Power management assertion to prevent the screen from sleeping.
188 IOPMAssertionID power_assertion_id_display_; 169 IOPMAssertionID power_assertion_id_display_;
189 170
190 // Power management assertion to indicate that the user is active. 171 // Power management assertion to indicate that the user is active.
191 IOPMAssertionID power_assertion_id_user_; 172 IOPMAssertionID power_assertion_id_user_;
192 173
193 // Dynamically link to deprecated APIs for Mac OS X 10.6 support. 174 // Dynamically link to deprecated APIs for Mac OS X 10.6 support.
194 base::ScopedNativeLibrary app_services_library_; 175 base::ScopedNativeLibrary app_services_library_;
195 CGDisplayBaseAddressFunc cg_display_base_address_; 176 CGDisplayBaseAddressFunc cg_display_base_address_;
196 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; 177 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_;
197 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; 178 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_;
198 base::ScopedNativeLibrary opengl_library_; 179 base::ScopedNativeLibrary opengl_library_;
199 CGLSetFullScreenFunc cgl_set_full_screen_; 180 CGLSetFullScreenFunc cgl_set_full_screen_;
200 181
201 DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac); 182 DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac);
202 }; 183 };
203 184
204 ScreenCaptureFrameMac::ScreenCaptureFrameMac( 185 scoped_ptr<webrtc::DesktopFrame> CreateFrame(
205 const MacDesktopConfiguration& desktop_config) { 186 const MacDesktopConfiguration& desktop_config) {
206 SkISize size = SkISize::Make(desktop_config.pixel_bounds.width(),
207 desktop_config.pixel_bounds.height());
208 set_bytes_per_row(size.width() * sizeof(uint32_t));
209 set_dimensions(size);
210 187
211 size_t buffer_size = size.width() * size.height() * sizeof(uint32_t); 188 webrtc::DesktopSize size(desktop_config.pixel_bounds.width(),
212 data_.reset(new uint8[buffer_size]); 189 desktop_config.pixel_bounds.height());
213 set_pixels(data_.get()); 190 scoped_ptr<webrtc::DesktopFrame> frame(new webrtc::BasicDesktopFrame(size));
214 191
215 dpi_ = SkIPoint::Make(kStandardDPI * desktop_config.dip_to_pixel_scale, 192 frame->set_dpi(webrtc::DesktopVector(
216 kStandardDPI * desktop_config.dip_to_pixel_scale); 193 kStandardDPI * desktop_config.dip_to_pixel_scale,
217 } 194 kStandardDPI * desktop_config.dip_to_pixel_scale));
218 195 return frame.Pass();
219 ScreenCaptureFrameMac::~ScreenCaptureFrameMac() {
220 } 196 }
221 197
222 ScreenCapturerMac::ScreenCapturerMac() 198 ScreenCapturerMac::ScreenCapturerMac()
223 : delegate_(NULL), 199 : callback_(NULL),
200 mouse_shape_observer_(NULL),
224 cgl_context_(NULL), 201 cgl_context_(NULL),
225 display_configuration_capture_event_(false, true), 202 display_configuration_capture_event_(false, true),
226 power_assertion_id_display_(kIOPMNullAssertionID), 203 power_assertion_id_display_(kIOPMNullAssertionID),
227 power_assertion_id_user_(kIOPMNullAssertionID), 204 power_assertion_id_user_(kIOPMNullAssertionID),
228 cg_display_base_address_(NULL), 205 cg_display_base_address_(NULL),
229 cg_display_bytes_per_row_(NULL), 206 cg_display_bytes_per_row_(NULL),
230 cg_display_bits_per_pixel_(NULL), 207 cg_display_bits_per_pixel_(NULL),
231 cgl_set_full_screen_(NULL) 208 cgl_set_full_screen_(NULL) {
232 {
233 } 209 }
234 210
235 ScreenCapturerMac::~ScreenCapturerMac() { 211 ScreenCapturerMac::~ScreenCapturerMac() {
236 if (power_assertion_id_display_ != kIOPMNullAssertionID) { 212 if (power_assertion_id_display_ != kIOPMNullAssertionID) {
237 IOPMAssertionRelease(power_assertion_id_display_); 213 IOPMAssertionRelease(power_assertion_id_display_);
238 power_assertion_id_display_ = kIOPMNullAssertionID; 214 power_assertion_id_display_ = kIOPMNullAssertionID;
239 } 215 }
240 if (power_assertion_id_user_ != kIOPMNullAssertionID) { 216 if (power_assertion_id_user_ != kIOPMNullAssertionID) {
241 IOPMAssertionRelease(power_assertion_id_user_); 217 IOPMAssertionRelease(power_assertion_id_user_);
242 power_assertion_id_user_ = kIOPMNullAssertionID; 218 power_assertion_id_user_ = kIOPMNullAssertionID;
(...skipping 26 matching lines...) Expand all
269 245
270 void ScreenCapturerMac::ReleaseBuffers() { 246 void ScreenCapturerMac::ReleaseBuffers() {
271 if (cgl_context_) { 247 if (cgl_context_) {
272 pixel_buffer_object_.Release(); 248 pixel_buffer_object_.Release();
273 CGLDestroyContext(cgl_context_); 249 CGLDestroyContext(cgl_context_);
274 cgl_context_ = NULL; 250 cgl_context_ = NULL;
275 } 251 }
276 // The buffers might be in use by the encoder, so don't delete them here. 252 // The buffers might be in use by the encoder, so don't delete them here.
277 // Instead, mark them as "needs update"; next time the buffers are used by 253 // Instead, mark them as "needs update"; next time the buffers are used by
278 // the capturer, they will be recreated if necessary. 254 // the capturer, they will be recreated if necessary.
279 queue_.SetAllFramesNeedUpdate(); 255 queue_.Reset();
280 } 256 }
281 257
282 void ScreenCapturerMac::Start(Delegate* delegate) { 258 void ScreenCapturerMac::Start(Callback* callback) {
283 DCHECK(delegate_ == NULL); 259 DCHECK(!callback_);
260 DCHECK(callback);
284 261
285 delegate_ = delegate; 262 callback_ = callback;
286 263
287 // Create power management assertions to wake the display and prevent it from 264 // Create power management assertions to wake the display and prevent it from
288 // going to sleep on user idle. 265 // going to sleep on user idle.
289 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above 266 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above
290 // instead of the following two assertions. 267 // instead of the following two assertions.
291 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, 268 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
292 kIOPMAssertionLevelOn, 269 kIOPMAssertionLevelOn,
293 CFSTR("Chrome Remote Desktop connection active"), 270 CFSTR("Chrome Remote Desktop connection active"),
294 &power_assertion_id_display_); 271 &power_assertion_id_display_);
295 // This assertion ensures that the display is woken up if it already asleep 272 // This assertion ensures that the display is woken up if it already asleep
296 // (as used by Apple Remote Desktop). 273 // (as used by Apple Remote Desktop).
297 IOPMAssertionCreateWithName(CFSTR("UserIsActive"), 274 IOPMAssertionCreateWithName(CFSTR("UserIsActive"),
298 kIOPMAssertionLevelOn, 275 kIOPMAssertionLevelOn,
299 CFSTR("Chrome Remote Desktop connection active"), 276 CFSTR("Chrome Remote Desktop connection active"),
300 &power_assertion_id_user_); 277 &power_assertion_id_user_);
301 } 278 }
302 279
303 void ScreenCapturerMac::CaptureFrame() { 280 void ScreenCapturerMac::Capture(
304 // Only allow captures when the display configuration is not occurring. 281 const webrtc::DesktopRegion& region_to_capture) {
305 scoped_refptr<ScreenCaptureData> data; 282 base::Time capture_start_time = base::Time::Now();
306 283
307 base::Time capture_start_time = base::Time::Now(); 284 queue_.MoveToNextFrame();
308 285
309 // Wait until the display configuration is stable. If one or more displays 286 // Wait until the display configuration is stable. If one or more displays
310 // are reconfiguring then |display_configuration_capture_event_| will not be 287 // are reconfiguring then |display_configuration_capture_event_| will not be
311 // set until the reconfiguration completes. 288 // set until the reconfiguration completes.
312 // TODO(wez): Replace this with an early-exit (See crbug.com/104542). 289 // TODO(wez): Replace this with an early-exit (See crbug.com/104542).
313 CHECK(display_configuration_capture_event_.TimedWait( 290 CHECK(display_configuration_capture_event_.TimedWait(
314 base::TimeDelta::FromSeconds( 291 base::TimeDelta::FromSeconds(
315 kDisplayConfigurationEventTimeoutInSeconds))); 292 kDisplayConfigurationEventTimeoutInSeconds)));
316 293
317 SkRegion region; 294 webrtc::DesktopRegion region;
318 helper_.SwapInvalidRegion(&region); 295 helper_.TakeInvalidRegion(&region);
319 296
320 // If the current buffer is from an older generation then allocate a new one. 297 // If the current buffer is from an older generation then allocate a new one.
321 // Note that we can't reallocate other buffers at this point, since the caller 298 // Note that we can't reallocate other buffers at this point, since the caller
322 // may still be reading from them. 299 // may still be reading from them.
323 if (queue_.current_frame_needs_update()) { 300 if (!queue_.current_frame())
324 scoped_ptr<ScreenCaptureFrameMac> buffer( 301 queue_.ReplaceCurrentFrame(CreateFrame(desktop_config_));
325 new ScreenCaptureFrameMac(desktop_config_));
326 queue_.ReplaceCurrentFrame(buffer.PassAs<ScreenCaptureFrame>());
327 }
328 302
329 ScreenCaptureFrame* current_buffer = queue_.current_frame(); 303 webrtc::DesktopFrame* current_frame = queue_.current_frame();
330 304
331 bool flip = false; // GL capturers need flipping. 305 bool flip = false; // GL capturers need flipping.
332 if (base::mac::IsOSLionOrLater()) { 306 if (base::mac::IsOSLionOrLater()) {
333 // Lion requires us to use their new APIs for doing screen capture. These 307 // Lion requires us to use their new APIs for doing screen capture. These
334 // APIS currently crash on 10.6.8 if there is no monitor attached. 308 // APIS currently crash on 10.6.8 if there is no monitor attached.
335 CgBlitPostLion(*current_buffer, region); 309 CgBlitPostLion(*current_frame, region);
336 } else if (cgl_context_) { 310 } else if (cgl_context_) {
337 flip = true; 311 flip = true;
338 if (pixel_buffer_object_.get() != 0) { 312 if (pixel_buffer_object_.get() != 0) {
339 GlBlitFast(*current_buffer, region); 313 GlBlitFast(*current_frame, region);
340 } else { 314 } else {
341 // See comment in ScopedPixelBufferObject::Init about why the slow 315 // See comment in ScopedPixelBufferObject::Init about why the slow
342 // path is always used on 10.5. 316 // path is always used on 10.5.
343 GlBlitSlow(*current_buffer); 317 GlBlitSlow(*current_frame);
344 } 318 }
345 } else { 319 } else {
346 CgBlitPreLion(*current_buffer, region); 320 CgBlitPreLion(*current_frame, region);
347 } 321 }
348 322
349 uint8* buffer = current_buffer->pixels(); 323 uint8* buffer = current_frame->data();
350 int stride = current_buffer->bytes_per_row(); 324 int stride = current_frame->stride();
351 if (flip) { 325 if (flip) {
352 stride = -stride; 326 stride = -stride;
353 buffer += (current_buffer->dimensions().height() - 1) * 327 buffer += (current_frame->size().height() - 1) * current_frame->stride();
354 current_buffer->bytes_per_row();
355 } 328 }
356 329
357 data = new ScreenCaptureData(buffer, stride, current_buffer->dimensions()); 330 webrtc::DesktopFrame* new_frame = queue_.current_frame()->Share();
358 data->set_dpi(static_cast<ScreenCaptureFrameMac*>(current_buffer)->dpi()); 331 *new_frame->mutable_updated_region() = region;
359 data->mutable_dirty_region() = region;
360 332
361 helper_.set_size_most_recent(data->size()); 333 helper_.set_size_most_recent(new_frame->size());
362 334
363 // Signal that we are done capturing data from the display framebuffer, 335 // Signal that we are done capturing data from the display framebuffer,
364 // and accessing display structures. 336 // and accessing display structures.
365 display_configuration_capture_event_.Signal(); 337 display_configuration_capture_event_.Signal();
366 338
367 // Capture the current cursor shape and notify |delegate_| if it has changed. 339 // Capture the current cursor shape and notify |callback_| if it has changed.
368 CaptureCursor(); 340 CaptureCursor();
369 341
370 // Move the capture frame buffer queue on to the next buffer. 342 new_frame->set_capture_time_ms(
371 queue_.DoneWithCurrentFrame(); 343 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp());
344 callback_->OnCaptureCompleted(new_frame);
345 }
372 346
373 data->set_capture_time_ms( 347 void ScreenCapturerMac::SetMouseShapeObserver(
374 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); 348 MouseShapeObserver* mouse_shape_observer) {
375 delegate_->OnCaptureCompleted(data); 349 DCHECK(!mouse_shape_observer_);
350 DCHECK(mouse_shape_observer);
351 mouse_shape_observer_ = mouse_shape_observer;
376 } 352 }
377 353
378 void ScreenCapturerMac::CaptureCursor() { 354 void ScreenCapturerMac::CaptureCursor() {
379 NSCursor* cursor = [NSCursor currentSystemCursor]; 355 NSCursor* cursor = [NSCursor currentSystemCursor];
380 if (cursor == nil) { 356 if (cursor == nil) {
381 return; 357 return;
382 } 358 }
383 359
384 NSImage* nsimage = [cursor image]; 360 NSImage* nsimage = [cursor image];
385 NSPoint hotspot = [cursor hotSpot]; 361 NSPoint hotspot = [cursor hotSpot];
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 reinterpret_cast<const char*>(CFDataGetBytePtr(image_data_ref)); 417 reinterpret_cast<const char*>(CFDataGetBytePtr(image_data_ref));
442 int data_size = CFDataGetLength(image_data_ref); 418 int data_size = CFDataGetLength(image_data_ref);
443 419
444 // Create a MouseCursorShape that describes the cursor and pass it to 420 // Create a MouseCursorShape that describes the cursor and pass it to
445 // the client. 421 // the client.
446 scoped_ptr<MouseCursorShape> cursor_shape(new MouseCursorShape()); 422 scoped_ptr<MouseCursorShape> cursor_shape(new MouseCursorShape());
447 cursor_shape->size.set(size.width, size.height); 423 cursor_shape->size.set(size.width, size.height);
448 cursor_shape->hotspot.set(hotspot.x, hotspot.y); 424 cursor_shape->hotspot.set(hotspot.x, hotspot.y);
449 cursor_shape->data.assign(cursor_src_data, cursor_src_data + data_size); 425 cursor_shape->data.assign(cursor_src_data, cursor_src_data + data_size);
450 426
451 delegate_->OnCursorShapeChanged(cursor_shape.Pass()); 427 if (mouse_shape_observer_)
428 mouse_shape_observer_->OnCursorShapeChanged(cursor_shape.Pass());
452 } 429 }
453 430
454 void ScreenCapturerMac::GlBlitFast(const ScreenCaptureFrame& buffer, 431 void ScreenCapturerMac::GlBlitFast(const webrtc::DesktopFrame& frame,
455 const SkRegion& region) { 432 const webrtc::DesktopRegion& region) {
456 const int buffer_height = buffer.dimensions().height();
457 const int buffer_width = buffer.dimensions().width();
458
459 // Clip to the size of our current screen. 433 // Clip to the size of our current screen.
460 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); 434 webrtc::DesktopRect clip_rect = webrtc::DesktopRect::MakeSize(frame.size());
461 if (queue_.previous_frame()) { 435 if (queue_.previous_frame()) {
462 // We are doing double buffer for the capture data so we just need to copy 436 // We are doing double buffer for the capture data so we just need to copy
463 // the invalid region from the previous capture in the current buffer. 437 // the invalid region from the previous capture in the current buffer.
464 // TODO(hclam): We can reduce the amount of copying here by subtracting 438 // TODO(hclam): We can reduce the amount of copying here by subtracting
465 // |capturer_helper_|s region from |last_invalid_region_|. 439 // |capturer_helper_|s region from |last_invalid_region_|.
466 // http://crbug.com/92354 440 // http://crbug.com/92354
467 441
468 // Since the image obtained from OpenGL is upside-down, need to do some 442 // Since the image obtained from OpenGL is upside-down, need to do some
469 // magic here to copy the correct rectangle. 443 // magic here to copy the correct rectangle.
470 const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); 444 const int y_offset = (frame.size().width() - 1) * frame.stride();
471 for(SkRegion::Iterator i(last_invalid_region_); !i.done(); i.next()) { 445 for (webrtc::DesktopRegion::Iterator i(last_invalid_region_);
472 SkIRect copy_rect = i.rect(); 446 !i.IsAtEnd(); i.Advance()) {
473 if (copy_rect.intersect(clip_rect)) { 447 webrtc::DesktopRect copy_rect = i.rect();
474 CopyRect(queue_.previous_frame()->pixels() + y_offset, 448 copy_rect.IntersectWith(clip_rect);
475 -buffer.bytes_per_row(), 449 if (!copy_rect.is_empty()) {
476 buffer.pixels() + y_offset, 450 CopyRect(queue_.previous_frame()->data() + y_offset,
477 -buffer.bytes_per_row(), 451 -frame.stride(),
478 4, // Bytes for pixel for RGBA. 452 frame.data() + y_offset,
453 -frame.stride(),
454 webrtc::DesktopFrame::kBytesPerPixel,
479 copy_rect); 455 copy_rect);
480 } 456 }
481 } 457 }
482 } 458 }
483 last_invalid_region_ = region; 459 last_invalid_region_ = region;
484 460
485 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; 461 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
486 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get()); 462 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get());
487 glReadPixels(0, 0, buffer_width, buffer_height, GL_BGRA, GL_UNSIGNED_BYTE, 0); 463 glReadPixels(0, 0, frame.size().height(), frame.size().width(), GL_BGRA,
464 GL_UNSIGNED_BYTE, 0);
488 GLubyte* ptr = static_cast<GLubyte*>( 465 GLubyte* ptr = static_cast<GLubyte*>(
489 glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB)); 466 glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB));
490 if (ptr == NULL) { 467 if (ptr == NULL) {
491 // If the buffer can't be mapped, assume that it's no longer valid and 468 // If the buffer can't be mapped, assume that it's no longer valid and
492 // release it. 469 // release it.
493 pixel_buffer_object_.Release(); 470 pixel_buffer_object_.Release();
494 } else { 471 } else {
495 // Copy only from the dirty rects. Since the image obtained from OpenGL is 472 // Copy only from the dirty rects. Since the image obtained from OpenGL is
496 // upside-down we need to do some magic here to copy the correct rectangle. 473 // upside-down we need to do some magic here to copy the correct rectangle.
497 const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); 474 const int y_offset = (frame.size().height() - 1) * frame.stride();
498 for(SkRegion::Iterator i(region); !i.done(); i.next()) { 475 for (webrtc::DesktopRegion::Iterator i(region);
499 SkIRect copy_rect = i.rect(); 476 !i.IsAtEnd(); i.Advance()) {
500 if (copy_rect.intersect(clip_rect)) { 477 webrtc::DesktopRect copy_rect = i.rect();
478 copy_rect.IntersectWith(clip_rect);
479 if (!copy_rect.is_empty()) {
501 CopyRect(ptr + y_offset, 480 CopyRect(ptr + y_offset,
502 -buffer.bytes_per_row(), 481 -frame.stride(),
503 buffer.pixels() + y_offset, 482 frame.data() + y_offset,
504 -buffer.bytes_per_row(), 483 -frame.stride(),
505 4, // Bytes for pixel for RGBA. 484 webrtc::DesktopFrame::kBytesPerPixel,
506 copy_rect); 485 copy_rect);
507 } 486 }
508 } 487 }
509 } 488 }
510 if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) { 489 if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) {
511 // If glUnmapBuffer returns false, then the contents of the data store are 490 // If glUnmapBuffer returns false, then the contents of the data store are
512 // undefined. This might be because the screen mode has changed, in which 491 // undefined. This might be because the screen mode has changed, in which
513 // case it will be recreated in ScreenConfigurationChanged, but releasing 492 // case it will be recreated in ScreenConfigurationChanged, but releasing
514 // the object here is the best option. Capturing will fall back on 493 // the object here is the best option. Capturing will fall back on
515 // GlBlitSlow until such time as the pixel buffer object is recreated. 494 // GlBlitSlow until such time as the pixel buffer object is recreated.
516 pixel_buffer_object_.Release(); 495 pixel_buffer_object_.Release();
517 } 496 }
518 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); 497 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
519 } 498 }
520 499
521 void ScreenCapturerMac::GlBlitSlow(const ScreenCaptureFrame& buffer) { 500 void ScreenCapturerMac::GlBlitSlow(const webrtc::DesktopFrame& frame) {
522 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; 501 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
523 glReadBuffer(GL_FRONT); 502 glReadBuffer(GL_FRONT);
524 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 503 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
525 glPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment. 504 glPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment.
526 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 505 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
527 glPixelStorei(GL_PACK_SKIP_ROWS, 0); 506 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
528 glPixelStorei(GL_PACK_SKIP_PIXELS, 0); 507 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
529 // Read a block of pixels from the frame buffer. 508 // Read a block of pixels from the frame buffer.
530 glReadPixels(0, 0, buffer.dimensions().width(), buffer.dimensions().height(), 509 glReadPixels(0, 0, frame.size().width(), frame.size().height(),
531 GL_BGRA, GL_UNSIGNED_BYTE, buffer.pixels()); 510 GL_BGRA, GL_UNSIGNED_BYTE, frame.data());
532 glPopClientAttrib(); 511 glPopClientAttrib();
533 } 512 }
534 513
535 void ScreenCapturerMac::CgBlitPreLion(const ScreenCaptureFrame& buffer, 514 void ScreenCapturerMac::CgBlitPreLion(const webrtc::DesktopFrame& frame,
536 const SkRegion& region) { 515 const webrtc::DesktopRegion& region) {
537 const int buffer_height = buffer.dimensions().height();
538
539 // Copy the entire contents of the previous capture buffer, to capture over. 516 // Copy the entire contents of the previous capture buffer, to capture over.
540 // TODO(wez): Get rid of this as per crbug.com/145064, or implement 517 // TODO(wez): Get rid of this as per crbug.com/145064, or implement
541 // crbug.com/92354. 518 // crbug.com/92354.
542 if (queue_.previous_frame()) { 519 if (queue_.previous_frame()) {
543 memcpy(buffer.pixels(), 520 memcpy(frame.data(),
544 queue_.previous_frame()->pixels(), 521 queue_.previous_frame()->data(),
545 buffer.bytes_per_row() * buffer_height); 522 frame.stride() * frame.size().height());
546 } 523 }
547 524
548 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { 525 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) {
549 const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; 526 const MacDisplayConfiguration& display_config = desktop_config_.displays[i];
550 527
551 // Use deprecated APIs to determine the display buffer layout. 528 // Use deprecated APIs to determine the display buffer layout.
552 DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && 529 DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ &&
553 cg_display_bits_per_pixel_); 530 cg_display_bits_per_pixel_);
554 uint8* display_base_address = 531 uint8* display_base_address =
555 reinterpret_cast<uint8*>((*cg_display_base_address_)(display_config.id)); 532 reinterpret_cast<uint8*>((*cg_display_base_address_)(display_config.id));
556 CHECK(display_base_address); 533 CHECK(display_base_address);
557 int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_config.id); 534 int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_config.id);
558 int src_bytes_per_pixel = 535 int src_bytes_per_pixel =
559 (*cg_display_bits_per_pixel_)(display_config.id) / 8; 536 (*cg_display_bits_per_pixel_)(display_config.id) / 8;
560 537
561 // Determine the display's position relative to the desktop, in pixels. 538 // Determine the display's position relative to the desktop, in pixels.
562 SkIRect display_bounds = display_config.pixel_bounds; 539 webrtc::DesktopRect display_bounds = display_config.pixel_bounds;
563 display_bounds.offset(-desktop_config_.pixel_bounds.left(), 540 display_bounds.Translate(-desktop_config_.pixel_bounds.left(),
564 -desktop_config_.pixel_bounds.top()); 541 -desktop_config_.pixel_bounds.top());
565 542
566 // Determine which parts of the blit region, if any, lay within the monitor. 543 // Determine which parts of the blit region, if any, lay within the monitor.
567 SkRegion copy_region; 544 webrtc::DesktopRegion copy_region = region;
568 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) 545 copy_region.IntersectWith(display_bounds);
546 if (copy_region.is_empty())
569 continue; 547 continue;
570 548
571 // Translate the region to be copied into display-relative coordinates. 549 // Translate the region to be copied into display-relative coordinates.
572 copy_region.translate(-display_bounds.left(), -display_bounds.top()); 550 copy_region.Translate(-display_bounds.left(), -display_bounds.top());
573 551
574 // Calculate where in the output buffer the display's origin is. 552 // Calculate where in the output buffer the display's origin is.
575 uint8* out_ptr = buffer.pixels() + 553 uint8* out_ptr = frame.data() +
576 (display_bounds.left() * src_bytes_per_pixel) + 554 (display_bounds.left() * src_bytes_per_pixel) +
577 (display_bounds.top() * buffer.bytes_per_row()); 555 (display_bounds.top() * frame.stride());
578 556
579 // Copy the dirty region from the display buffer into our desktop buffer. 557 // Copy the dirty region from the display buffer into our desktop buffer.
580 for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { 558 for (webrtc::DesktopRegion::Iterator i(copy_region);
559 !i.IsAtEnd(); i.Advance()) {
581 CopyRect(display_base_address, 560 CopyRect(display_base_address,
582 src_bytes_per_row, 561 src_bytes_per_row,
583 out_ptr, 562 out_ptr,
584 buffer.bytes_per_row(), 563 frame.stride(),
585 src_bytes_per_pixel, 564 src_bytes_per_pixel,
586 i.rect()); 565 i.rect());
587 } 566 }
588 } 567 }
589 } 568 }
590 569
591 void ScreenCapturerMac::CgBlitPostLion(const ScreenCaptureFrame& buffer, 570 void ScreenCapturerMac::CgBlitPostLion(const webrtc::DesktopFrame& frame,
592 const SkRegion& region) { 571 const webrtc::DesktopRegion& region) {
593 const int buffer_height = buffer.dimensions().height();
594
595 // Copy the entire contents of the previous capture buffer, to capture over. 572 // Copy the entire contents of the previous capture buffer, to capture over.
596 // TODO(wez): Get rid of this as per crbug.com/145064, or implement 573 // TODO(wez): Get rid of this as per crbug.com/145064, or implement
597 // crbug.com/92354. 574 // crbug.com/92354.
598 if (queue_.previous_frame()) { 575 if (queue_.previous_frame()) {
599 memcpy(buffer.pixels(), 576 memcpy(frame.data(),
600 queue_.previous_frame()->pixels(), 577 queue_.previous_frame()->data(),
601 buffer.bytes_per_row() * buffer_height); 578 frame.stride() * frame.size().height());
602 } 579 }
603 580
604 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { 581 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) {
605 const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; 582 const MacDisplayConfiguration& display_config = desktop_config_.displays[i];
606 583
607 // Determine the display's position relative to the desktop, in pixels. 584 // Determine the display's position relative to the desktop, in pixels.
608 SkIRect display_bounds = display_config.pixel_bounds; 585 webrtc::DesktopRect display_bounds = display_config.pixel_bounds;
609 display_bounds.offset(-desktop_config_.pixel_bounds.left(), 586 display_bounds.Translate(-desktop_config_.pixel_bounds.left(),
610 -desktop_config_.pixel_bounds.top()); 587 -desktop_config_.pixel_bounds.top());
611 588
612 // Determine which parts of the blit region, if any, lay within the monitor. 589 // Determine which parts of the blit region, if any, lay within the monitor.
613 SkRegion copy_region; 590 webrtc::DesktopRegion copy_region = region;
614 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) 591 copy_region.IntersectWith(display_bounds);
592 if (copy_region.is_empty())
615 continue; 593 continue;
616 594
617 // Translate the region to be copied into display-relative coordinates. 595 // Translate the region to be copied into display-relative coordinates.
618 copy_region.translate(-display_bounds.left(), -display_bounds.top()); 596 copy_region.Translate(-display_bounds.left(), -display_bounds.top());
619 597
620 // Create an image containing a snapshot of the display. 598 // Create an image containing a snapshot of the display.
621 base::mac::ScopedCFTypeRef<CGImageRef> image( 599 base::mac::ScopedCFTypeRef<CGImageRef> image(
622 CGDisplayCreateImage(display_config.id)); 600 CGDisplayCreateImage(display_config.id));
623 if (image.get() == NULL) 601 if (image.get() == NULL)
624 continue; 602 continue;
625 603
626 // Request access to the raw pixel data via the image's DataProvider. 604 // Request access to the raw pixel data via the image's DataProvider.
627 CGDataProviderRef provider = CGImageGetDataProvider(image); 605 CGDataProviderRef provider = CGImageGetDataProvider(image);
628 base::mac::ScopedCFTypeRef<CFDataRef> data( 606 base::mac::ScopedCFTypeRef<CFDataRef> data(
629 CGDataProviderCopyData(provider)); 607 CGDataProviderCopyData(provider));
630 if (data.get() == NULL) 608 if (data.get() == NULL)
631 continue; 609 continue;
632 610
633 const uint8* display_base_address = CFDataGetBytePtr(data); 611 const uint8* display_base_address = CFDataGetBytePtr(data);
634 int src_bytes_per_row = CGImageGetBytesPerRow(image); 612 int src_bytes_per_row = CGImageGetBytesPerRow(image);
635 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; 613 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8;
636 614
637 // Calculate where in the output buffer the display's origin is. 615 // Calculate where in the output buffer the display's origin is.
638 uint8* out_ptr = buffer.pixels() + 616 uint8* out_ptr = frame.data() +
639 (display_bounds.left() * src_bytes_per_pixel) + 617 (display_bounds.left() * src_bytes_per_pixel) +
640 (display_bounds.top() * buffer.bytes_per_row()); 618 (display_bounds.top() * frame.stride());
641 619
642 // Copy the dirty region from the display buffer into our desktop buffer. 620 // Copy the dirty region from the display buffer into our desktop buffer.
643 for (SkRegion::Iterator i(copy_region); !i.done(); i.next()) { 621 for (webrtc::DesktopRegion::Iterator i(copy_region);
622 !i.IsAtEnd(); i.Advance()) {
644 CopyRect(display_base_address, 623 CopyRect(display_base_address,
645 src_bytes_per_row, 624 src_bytes_per_row,
646 out_ptr, 625 out_ptr,
647 buffer.bytes_per_row(), 626 frame.stride(),
648 src_bytes_per_pixel, 627 src_bytes_per_pixel,
649 i.rect()); 628 i.rect());
650 } 629 }
651 } 630 }
652 } 631 }
653 632
654 void ScreenCapturerMac::ScreenConfigurationChanged() { 633 void ScreenCapturerMac::ScreenConfigurationChanged() {
655 // Release existing buffers, which will be of the wrong size. 634 // Release existing buffers, which will be of the wrong size.
656 ReleaseBuffers(); 635 ReleaseBuffers();
657 636
658 // Clear the dirty region, in case the display is down-sizing. 637 // Clear the dirty region, in case the display is down-sizing.
659 helper_.ClearInvalidRegion(); 638 helper_.ClearInvalidRegion();
660 639
661 // Refresh the cached desktop configuration. 640 // Refresh the cached desktop configuration.
662 desktop_config_ = MacDesktopConfiguration::GetCurrent( 641 desktop_config_ = MacDesktopConfiguration::GetCurrent(
663 MacDesktopConfiguration::TopLeftOrigin); 642 MacDesktopConfiguration::TopLeftOrigin);
664 643
665 // Re-mark the entire desktop as dirty. 644 // Re-mark the entire desktop as dirty.
666 helper_.InvalidateScreen( 645 helper_.InvalidateScreen(
667 SkISize::Make(desktop_config_.pixel_bounds.width(), 646 webrtc::DesktopSize(desktop_config_.pixel_bounds.width(),
668 desktop_config_.pixel_bounds.height())); 647 desktop_config_.pixel_bounds.height()));
669 648
670 // Make sure the frame buffers will be reallocated. 649 // Make sure the frame buffers will be reallocated.
671 queue_.SetAllFramesNeedUpdate(); 650 queue_.Reset();
672 651
673 // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's 652 // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's
674 // contents. Although the API exists in OS 10.6, it crashes the caller if 653 // contents. Although the API exists in OS 10.6, it crashes the caller if
675 // the machine has no monitor connected, so we fall back to depcreated APIs 654 // the machine has no monitor connected, so we fall back to depcreated APIs
676 // when running on 10.6. 655 // when running on 10.6.
677 if (base::mac::IsOSLionOrLater()) { 656 if (base::mac::IsOSLionOrLater()) {
678 LOG(INFO) << "Using CgBlitPostLion."; 657 LOG(INFO) << "Using CgBlitPostLion.";
679 // No need for any OpenGL support on Lion 658 // No need for any OpenGL support on Lion
680 return; 659 return;
681 } 660 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 740
762 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { 741 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() {
763 CGUnregisterScreenRefreshCallback( 742 CGUnregisterScreenRefreshCallback(
764 ScreenCapturerMac::ScreenRefreshCallback, this); 743 ScreenCapturerMac::ScreenRefreshCallback, this);
765 CGScreenUnregisterMoveCallback( 744 CGScreenUnregisterMoveCallback(
766 ScreenCapturerMac::ScreenUpdateMoveCallback, this); 745 ScreenCapturerMac::ScreenUpdateMoveCallback, this);
767 } 746 }
768 747
769 void ScreenCapturerMac::ScreenRefresh(CGRectCount count, 748 void ScreenCapturerMac::ScreenRefresh(CGRectCount count,
770 const CGRect* rect_array) { 749 const CGRect* rect_array) {
771 if (desktop_config_.pixel_bounds.isEmpty()) { 750 if (desktop_config_.pixel_bounds.is_empty())
772 return; 751 return;
773 } 752
774 SkIRect skirect_array[count]; 753 webrtc::DesktopRegion region;
775 754
776 for (CGRectCount i = 0; i < count; ++i) { 755 for (CGRectCount i = 0; i < count; ++i) {
777 SkRect sk_rect = gfx::CGRectToSkRect(rect_array[i]);
778
779 // Convert from Density-Independent Pixel to physical pixel coordinates. 756 // Convert from Density-Independent Pixel to physical pixel coordinates.
780 sk_rect = ScaleSkRect(sk_rect, desktop_config_.dip_to_pixel_scale); 757 webrtc::DesktopRect rect =
781 sk_rect.round(&skirect_array[i]); 758 ScaleAndRoundCGRect(rect_array[i], desktop_config_.dip_to_pixel_scale);
782 759
783 // Translate from local desktop to capturer framebuffer coordinates. 760 // Translate from local desktop to capturer framebuffer coordinates.
784 skirect_array[i].offset(-desktop_config_.pixel_bounds.left(), 761 rect.Translate(-desktop_config_.pixel_bounds.left(),
785 -desktop_config_.pixel_bounds.top()); 762 -desktop_config_.pixel_bounds.top());
763
764 region.AddRect(rect);
786 } 765 }
787 766
788 SkRegion region;
789 region.setRects(skirect_array, count);
790 helper_.InvalidateRegion(region); 767 helper_.InvalidateRegion(region);
791 } 768 }
792 769
793 void ScreenCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, 770 void ScreenCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
794 size_t count, 771 size_t count,
795 const CGRect* rect_array) { 772 const CGRect* rect_array) {
796 // Translate |rect_array| to identify the move's destination. 773 // Translate |rect_array| to identify the move's destination.
797 CGRect refresh_rects[count]; 774 CGRect refresh_rects[count];
798 for (CGRectCount i = 0; i < count; ++i) { 775 for (CGRectCount i = 0; i < count; ++i) {
799 refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY); 776 refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY);
(...skipping 28 matching lines...) Expand all
828 // the reconfiguration handler itself). 805 // the reconfiguration handler itself).
829 UnregisterRefreshAndMoveHandlers(); 806 UnregisterRefreshAndMoveHandlers();
830 RegisterRefreshAndMoveHandlers(); 807 RegisterRefreshAndMoveHandlers();
831 ScreenConfigurationChanged(); 808 ScreenConfigurationChanged();
832 display_configuration_capture_event_.Signal(); 809 display_configuration_capture_event_.Signal();
833 } 810 }
834 } 811 }
835 } 812 }
836 813
837 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count, 814 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count,
838 const CGRect* rect_array, 815 const CGRect* rect_array,
839 void* user_parameter) { 816 void* user_parameter) {
840 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>( 817 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>(
841 user_parameter); 818 user_parameter);
842 if (capturer->desktop_config_.pixel_bounds.isEmpty()) { 819 if (capturer->desktop_config_.pixel_bounds.is_empty()) {
843 capturer->ScreenConfigurationChanged(); 820 capturer->ScreenConfigurationChanged();
844 } 821 }
845 capturer->ScreenRefresh(count, rect_array); 822 capturer->ScreenRefresh(count, rect_array);
846 } 823 }
847 824
848 void ScreenCapturerMac::ScreenUpdateMoveCallback( 825 void ScreenCapturerMac::ScreenUpdateMoveCallback(
849 CGScreenUpdateMoveDelta delta, 826 CGScreenUpdateMoveDelta delta,
850 size_t count, 827 size_t count,
851 const CGRect* rect_array, 828 const CGRect* rect_array,
852 void* user_parameter) { 829 void* user_parameter) {
853 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>( 830 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>(
854 user_parameter); 831 user_parameter);
855 capturer->ScreenUpdateMove(delta, count, rect_array); 832 capturer->ScreenUpdateMove(delta, count, rect_array);
856 } 833 }
857 834
858 void ScreenCapturerMac::DisplaysReconfiguredCallback( 835 void ScreenCapturerMac::DisplaysReconfiguredCallback(
859 CGDirectDisplayID display, 836 CGDirectDisplayID display,
860 CGDisplayChangeSummaryFlags flags, 837 CGDisplayChangeSummaryFlags flags,
861 void* user_parameter) { 838 void* user_parameter) {
862 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>( 839 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>(
863 user_parameter); 840 user_parameter);
864 capturer->DisplaysReconfigured(display, flags); 841 capturer->DisplaysReconfigured(display, flags);
865 } 842 }
866 843
867 } // namespace 844 } // namespace
868 845
869 scoped_refptr<SharedBuffer> ScreenCapturer::Delegate::CreateSharedBuffer(
870 uint32 size) {
871 return scoped_refptr<SharedBuffer>();
872 }
873
874 void ScreenCapturer::Delegate::ReleaseSharedBuffer(
875 scoped_refptr<SharedBuffer> buffer) {
876 }
877
878 // static 846 // static
879 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() { 847 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() {
880 scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac()); 848 scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac());
881 if (!capturer->Init()) 849 if (!capturer->Init())
882 capturer.reset(); 850 capturer.reset();
883 return capturer.PassAs<ScreenCapturer>(); 851 return capturer.PassAs<ScreenCapturer>();
884 } 852 }
885 853
886 } // namespace media 854 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698