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

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) *
354 current_buffer->bytes_per_row(); 328 current_frame->stride();
355 } 329 }
356 330
357 data = new ScreenCaptureData(buffer, stride, current_buffer->dimensions()); 331 webrtc::DesktopFrame* new_frame = queue_.EmitCurrentFrame();
358 data->set_dpi(static_cast<ScreenCaptureFrameMac*>(current_buffer)->dpi()); 332 *new_frame->mutable_updated_region() = region;
359 data->mutable_dirty_region() = region;
360 333
361 helper_.set_size_most_recent(data->size()); 334 helper_.set_size_most_recent(new_frame->size());
362 335
363 // Signal that we are done capturing data from the display framebuffer, 336 // Signal that we are done capturing data from the display framebuffer,
364 // and accessing display structures. 337 // and accessing display structures.
365 display_configuration_capture_event_.Signal(); 338 display_configuration_capture_event_.Signal();
366 339
367 // Capture the current cursor shape and notify |delegate_| if it has changed. 340 // Capture the current cursor shape and notify |callback_| if it has changed.
368 CaptureCursor(); 341 CaptureCursor();
369 342
370 // Move the capture frame buffer queue on to the next buffer. 343 new_frame->set_capture_time_ms(
371 queue_.DoneWithCurrentFrame(); 344 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp());
345 callback_->OnCaptureCompleted(new_frame);
346 }
372 347
373 data->set_capture_time_ms( 348 void ScreenCapturerMac::SetMouseShapeObserver(
374 (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); 349 MouseShapeObserver* mouse_shape_observer) {
375 delegate_->OnCaptureCompleted(data); 350 DCHECK(!mouse_shape_observer_);
351 DCHECK(mouse_shape_observer);
352 mouse_shape_observer_ = mouse_shape_observer;
376 } 353 }
377 354
378 void ScreenCapturerMac::CaptureCursor() { 355 void ScreenCapturerMac::CaptureCursor() {
379 NSCursor* cursor = [NSCursor currentSystemCursor]; 356 NSCursor* cursor = [NSCursor currentSystemCursor];
380 if (cursor == nil) { 357 if (cursor == nil) {
381 return; 358 return;
382 } 359 }
383 360
384 NSImage* nsimage = [cursor image]; 361 NSImage* nsimage = [cursor image];
385 NSPoint hotspot = [cursor hotSpot]; 362 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)); 418 reinterpret_cast<const char*>(CFDataGetBytePtr(image_data_ref));
442 int data_size = CFDataGetLength(image_data_ref); 419 int data_size = CFDataGetLength(image_data_ref);
443 420
444 // Create a MouseCursorShape that describes the cursor and pass it to 421 // Create a MouseCursorShape that describes the cursor and pass it to
445 // the client. 422 // the client.
446 scoped_ptr<MouseCursorShape> cursor_shape(new MouseCursorShape()); 423 scoped_ptr<MouseCursorShape> cursor_shape(new MouseCursorShape());
447 cursor_shape->size.set(size.width, size.height); 424 cursor_shape->size.set(size.width, size.height);
448 cursor_shape->hotspot.set(hotspot.x, hotspot.y); 425 cursor_shape->hotspot.set(hotspot.x, hotspot.y);
449 cursor_shape->data.assign(cursor_src_data, cursor_src_data + data_size); 426 cursor_shape->data.assign(cursor_src_data, cursor_src_data + data_size);
450 427
451 delegate_->OnCursorShapeChanged(cursor_shape.Pass()); 428 if (mouse_shape_observer_)
429 mouse_shape_observer_->OnCursorShapeChanged(cursor_shape.Pass());
452 } 430 }
453 431
454 void ScreenCapturerMac::GlBlitFast(const ScreenCaptureFrame& buffer, 432 void ScreenCapturerMac::GlBlitFast(const webrtc::DesktopFrame& frame,
455 const SkRegion& region) { 433 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. 434 // Clip to the size of our current screen.
460 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); 435 webrtc::DesktopRect clip_rect = webrtc::DesktopRect::MakeSize(frame.size());
461 if (queue_.previous_frame()) { 436 if (queue_.previous_frame()) {
462 // We are doing double buffer for the capture data so we just need to copy 437 // 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. 438 // the invalid region from the previous capture in the current buffer.
464 // TODO(hclam): We can reduce the amount of copying here by subtracting 439 // TODO(hclam): We can reduce the amount of copying here by subtracting
465 // |capturer_helper_|s region from |last_invalid_region_|. 440 // |capturer_helper_|s region from |last_invalid_region_|.
466 // http://crbug.com/92354 441 // http://crbug.com/92354
467 442
468 // Since the image obtained from OpenGL is upside-down, need to do some 443 // Since the image obtained from OpenGL is upside-down, need to do some
469 // magic here to copy the correct rectangle. 444 // magic here to copy the correct rectangle.
470 const int y_offset = (buffer_height - 1) * buffer.bytes_per_row(); 445 const int y_offset = (frame.size().width() - 1) * frame.stride();
471 for(SkRegion::Iterator i(last_invalid_region_); !i.done(); i.next()) { 446 for (webrtc::DesktopRegion::Iterator i(last_invalid_region_);
472 SkIRect copy_rect = i.rect(); 447 !i.IsAtEnd(); i.Advance()) {
473 if (copy_rect.intersect(clip_rect)) { 448 webrtc::DesktopRect copy_rect = i.rect();
474 CopyRect(queue_.previous_frame()->pixels() + y_offset, 449 copy_rect.IntersectWith(clip_rect);
475 -buffer.bytes_per_row(), 450 if (!copy_rect.is_empty()) {
476 buffer.pixels() + y_offset, 451 CopyRect(queue_.previous_frame()->data() + y_offset,
477 -buffer.bytes_per_row(), 452 -frame.stride(),
478 4, // Bytes for pixel for RGBA. 453 frame.data() + y_offset,
454 -frame.stride(),
455 webrtc::DesktopFrame::kBytesPerPixel,
479 copy_rect); 456 copy_rect);
480 } 457 }
481 } 458 }
482 } 459 }
483 last_invalid_region_ = region; 460 last_invalid_region_ = region;
484 461
485 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; 462 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
486 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get()); 463 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pixel_buffer_object_.get());
487 glReadPixels(0, 0, buffer_width, buffer_height, GL_BGRA, GL_UNSIGNED_BYTE, 0); 464 glReadPixels(0, 0, frame.size().height(), frame.size().width(), GL_BGRA,
465 GL_UNSIGNED_BYTE, 0);
488 GLubyte* ptr = static_cast<GLubyte*>( 466 GLubyte* ptr = static_cast<GLubyte*>(
489 glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB)); 467 glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB));
490 if (ptr == NULL) { 468 if (ptr == NULL) {
491 // If the buffer can't be mapped, assume that it's no longer valid and 469 // If the buffer can't be mapped, assume that it's no longer valid and
492 // release it. 470 // release it.
493 pixel_buffer_object_.Release(); 471 pixel_buffer_object_.Release();
494 } else { 472 } else {
495 // Copy only from the dirty rects. Since the image obtained from OpenGL is 473 // 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. 474 // 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(); 475 const int y_offset = (frame.size().width() - 1) * frame.stride();
498 for(SkRegion::Iterator i(region); !i.done(); i.next()) { 476 for (webrtc::DesktopRegion::Iterator i(region);
499 SkIRect copy_rect = i.rect(); 477 !i.IsAtEnd(); i.Advance()) {
500 if (copy_rect.intersect(clip_rect)) { 478 webrtc::DesktopRect copy_rect = i.rect();
479 copy_rect.IntersectWith(clip_rect);
480 if (!copy_rect.is_empty()) {
501 CopyRect(ptr + y_offset, 481 CopyRect(ptr + y_offset,
502 -buffer.bytes_per_row(), 482 -frame.stride(),
503 buffer.pixels() + y_offset, 483 frame.data() + y_offset,
504 -buffer.bytes_per_row(), 484 -frame.stride(),
505 4, // Bytes for pixel for RGBA. 485 webrtc::DesktopFrame::kBytesPerPixel,
506 copy_rect); 486 copy_rect);
507 } 487 }
508 } 488 }
509 } 489 }
510 if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) { 490 if (!glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB)) {
511 // If glUnmapBuffer returns false, then the contents of the data store are 491 // 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 492 // undefined. This might be because the screen mode has changed, in which
513 // case it will be recreated in ScreenConfigurationChanged, but releasing 493 // case it will be recreated in ScreenConfigurationChanged, but releasing
514 // the object here is the best option. Capturing will fall back on 494 // the object here is the best option. Capturing will fall back on
515 // GlBlitSlow until such time as the pixel buffer object is recreated. 495 // GlBlitSlow until such time as the pixel buffer object is recreated.
516 pixel_buffer_object_.Release(); 496 pixel_buffer_object_.Release();
517 } 497 }
518 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); 498 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
519 } 499 }
520 500
521 void ScreenCapturerMac::GlBlitSlow(const ScreenCaptureFrame& buffer) { 501 void ScreenCapturerMac::GlBlitSlow(const webrtc::DesktopFrame& frame) {
522 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_; 502 CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
523 glReadBuffer(GL_FRONT); 503 glReadBuffer(GL_FRONT);
524 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); 504 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
525 glPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment. 505 glPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment.
526 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 506 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
527 glPixelStorei(GL_PACK_SKIP_ROWS, 0); 507 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
528 glPixelStorei(GL_PACK_SKIP_PIXELS, 0); 508 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
529 // Read a block of pixels from the frame buffer. 509 // Read a block of pixels from the frame buffer.
530 glReadPixels(0, 0, buffer.dimensions().width(), buffer.dimensions().height(), 510 glReadPixels(0, 0, frame.size().width(), frame.size().height(),
531 GL_BGRA, GL_UNSIGNED_BYTE, buffer.pixels()); 511 GL_BGRA, GL_UNSIGNED_BYTE, frame.data());
532 glPopClientAttrib(); 512 glPopClientAttrib();
533 } 513 }
534 514
535 void ScreenCapturerMac::CgBlitPreLion(const ScreenCaptureFrame& buffer, 515 void ScreenCapturerMac::CgBlitPreLion(const webrtc::DesktopFrame& frame,
536 const SkRegion& region) { 516 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. 517 // 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 518 // TODO(wez): Get rid of this as per crbug.com/145064, or implement
541 // crbug.com/92354. 519 // crbug.com/92354.
542 if (queue_.previous_frame()) { 520 if (queue_.previous_frame()) {
543 memcpy(buffer.pixels(), 521 memcpy(frame.data(),
544 queue_.previous_frame()->pixels(), 522 queue_.previous_frame()->data(),
545 buffer.bytes_per_row() * buffer_height); 523 frame.stride() * frame.size().height());
546 } 524 }
547 525
548 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { 526 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) {
549 const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; 527 const MacDisplayConfiguration& display_config = desktop_config_.displays[i];
550 528
551 // Use deprecated APIs to determine the display buffer layout. 529 // Use deprecated APIs to determine the display buffer layout.
552 DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && 530 DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ &&
553 cg_display_bits_per_pixel_); 531 cg_display_bits_per_pixel_);
554 uint8* display_base_address = 532 uint8* display_base_address =
555 reinterpret_cast<uint8*>((*cg_display_base_address_)(display_config.id)); 533 reinterpret_cast<uint8*>((*cg_display_base_address_)(display_config.id));
556 CHECK(display_base_address); 534 CHECK(display_base_address);
557 int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_config.id); 535 int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_config.id);
558 int src_bytes_per_pixel = 536 int src_bytes_per_pixel =
559 (*cg_display_bits_per_pixel_)(display_config.id) / 8; 537 (*cg_display_bits_per_pixel_)(display_config.id) / 8;
560 538
561 // Determine the display's position relative to the desktop, in pixels. 539 // Determine the display's position relative to the desktop, in pixels.
562 SkIRect display_bounds = display_config.pixel_bounds; 540 webrtc::DesktopRect display_bounds = display_config.pixel_bounds;
563 display_bounds.offset(-desktop_config_.pixel_bounds.left(), 541 display_bounds.Translate(-desktop_config_.pixel_bounds.left(),
564 -desktop_config_.pixel_bounds.top()); 542 -desktop_config_.pixel_bounds.top());
565 543
566 // Determine which parts of the blit region, if any, lay within the monitor. 544 // Determine which parts of the blit region, if any, lay within the monitor.
567 SkRegion copy_region; 545 webrtc::DesktopRegion copy_region = region;
568 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) 546 copy_region.IntersectWith(display_bounds);
547 if (copy_region.is_empty())
569 continue; 548 continue;
570 549
571 // Translate the region to be copied into display-relative coordinates. 550 // Translate the region to be copied into display-relative coordinates.
572 copy_region.translate(-display_bounds.left(), -display_bounds.top()); 551 copy_region.Translate(-display_bounds.left(), -display_bounds.top());
573 552
574 // Calculate where in the output buffer the display's origin is. 553 // Calculate where in the output buffer the display's origin is.
575 uint8* out_ptr = buffer.pixels() + 554 uint8* out_ptr = frame.data() +
576 (display_bounds.left() * src_bytes_per_pixel) + 555 (display_bounds.left() * src_bytes_per_pixel) +
577 (display_bounds.top() * buffer.bytes_per_row()); 556 (display_bounds.top() * frame.stride());
578 557
579 // Copy the dirty region from the display buffer into our desktop buffer. 558 // Copy the dirty region from the display buffer into our desktop buffer.
580 for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { 559 for (webrtc::DesktopRegion::Iterator i(copy_region);
560 !i.IsAtEnd(); i.Advance()) {
581 CopyRect(display_base_address, 561 CopyRect(display_base_address,
582 src_bytes_per_row, 562 src_bytes_per_row,
583 out_ptr, 563 out_ptr,
584 buffer.bytes_per_row(), 564 frame.stride(),
585 src_bytes_per_pixel, 565 src_bytes_per_pixel,
586 i.rect()); 566 i.rect());
587 } 567 }
588 } 568 }
589 } 569 }
590 570
591 void ScreenCapturerMac::CgBlitPostLion(const ScreenCaptureFrame& buffer, 571 void ScreenCapturerMac::CgBlitPostLion(const webrtc::DesktopFrame& frame,
592 const SkRegion& region) { 572 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. 573 // 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 574 // TODO(wez): Get rid of this as per crbug.com/145064, or implement
597 // crbug.com/92354. 575 // crbug.com/92354.
598 if (queue_.previous_frame()) { 576 if (queue_.previous_frame()) {
599 memcpy(buffer.pixels(), 577 memcpy(frame.data(),
600 queue_.previous_frame()->pixels(), 578 queue_.previous_frame()->data(),
601 buffer.bytes_per_row() * buffer_height); 579 frame.stride() * frame.size().height());
602 } 580 }
603 581
604 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { 582 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) {
605 const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; 583 const MacDisplayConfiguration& display_config = desktop_config_.displays[i];
606 584
607 // Determine the display's position relative to the desktop, in pixels. 585 // Determine the display's position relative to the desktop, in pixels.
608 SkIRect display_bounds = display_config.pixel_bounds; 586 webrtc::DesktopRect display_bounds = display_config.pixel_bounds;
609 display_bounds.offset(-desktop_config_.pixel_bounds.left(), 587 display_bounds.Translate(-desktop_config_.pixel_bounds.left(),
610 -desktop_config_.pixel_bounds.top()); 588 -desktop_config_.pixel_bounds.top());
611 589
612 // Determine which parts of the blit region, if any, lay within the monitor. 590 // Determine which parts of the blit region, if any, lay within the monitor.
613 SkRegion copy_region; 591 webrtc::DesktopRegion copy_region = region;
614 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) 592 copy_region.IntersectWith(display_bounds);
593 if (copy_region.is_empty())
615 continue; 594 continue;
616 595
617 // Translate the region to be copied into display-relative coordinates. 596 // Translate the region to be copied into display-relative coordinates.
618 copy_region.translate(-display_bounds.left(), -display_bounds.top()); 597 copy_region.Translate(-display_bounds.left(), -display_bounds.top());
619 598
620 // Create an image containing a snapshot of the display. 599 // Create an image containing a snapshot of the display.
621 base::mac::ScopedCFTypeRef<CGImageRef> image( 600 base::mac::ScopedCFTypeRef<CGImageRef> image(
622 CGDisplayCreateImage(display_config.id)); 601 CGDisplayCreateImage(display_config.id));
623 if (image.get() == NULL) 602 if (image.get() == NULL)
624 continue; 603 continue;
625 604
626 // Request access to the raw pixel data via the image's DataProvider. 605 // Request access to the raw pixel data via the image's DataProvider.
627 CGDataProviderRef provider = CGImageGetDataProvider(image); 606 CGDataProviderRef provider = CGImageGetDataProvider(image);
628 base::mac::ScopedCFTypeRef<CFDataRef> data( 607 base::mac::ScopedCFTypeRef<CFDataRef> data(
629 CGDataProviderCopyData(provider)); 608 CGDataProviderCopyData(provider));
630 if (data.get() == NULL) 609 if (data.get() == NULL)
631 continue; 610 continue;
632 611
633 const uint8* display_base_address = CFDataGetBytePtr(data); 612 const uint8* display_base_address = CFDataGetBytePtr(data);
634 int src_bytes_per_row = CGImageGetBytesPerRow(image); 613 int src_bytes_per_row = CGImageGetBytesPerRow(image);
635 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; 614 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8;
636 615
637 // Calculate where in the output buffer the display's origin is. 616 // Calculate where in the output buffer the display's origin is.
638 uint8* out_ptr = buffer.pixels() + 617 uint8* out_ptr = frame.data() +
639 (display_bounds.left() * src_bytes_per_pixel) + 618 (display_bounds.left() * src_bytes_per_pixel) +
640 (display_bounds.top() * buffer.bytes_per_row()); 619 (display_bounds.top() * frame.stride());
641 620
642 // Copy the dirty region from the display buffer into our desktop buffer. 621 // Copy the dirty region from the display buffer into our desktop buffer.
643 for (SkRegion::Iterator i(copy_region); !i.done(); i.next()) { 622 for (webrtc::DesktopRegion::Iterator i(copy_region);
623 !i.IsAtEnd(); i.Advance()) {
644 CopyRect(display_base_address, 624 CopyRect(display_base_address,
645 src_bytes_per_row, 625 src_bytes_per_row,
646 out_ptr, 626 out_ptr,
647 buffer.bytes_per_row(), 627 frame.stride(),
648 src_bytes_per_pixel, 628 src_bytes_per_pixel,
649 i.rect()); 629 i.rect());
650 } 630 }
651 } 631 }
652 } 632 }
653 633
654 void ScreenCapturerMac::ScreenConfigurationChanged() { 634 void ScreenCapturerMac::ScreenConfigurationChanged() {
655 // Release existing buffers, which will be of the wrong size. 635 // Release existing buffers, which will be of the wrong size.
656 ReleaseBuffers(); 636 ReleaseBuffers();
657 637
658 // Clear the dirty region, in case the display is down-sizing. 638 // Clear the dirty region, in case the display is down-sizing.
659 helper_.ClearInvalidRegion(); 639 helper_.ClearInvalidRegion();
660 640
661 // Refresh the cached desktop configuration. 641 // Refresh the cached desktop configuration.
662 desktop_config_ = MacDesktopConfiguration::GetCurrent( 642 desktop_config_ = MacDesktopConfiguration::GetCurrent(
663 MacDesktopConfiguration::TopLeftOrigin); 643 MacDesktopConfiguration::TopLeftOrigin);
664 644
665 // Re-mark the entire desktop as dirty. 645 // Re-mark the entire desktop as dirty.
666 helper_.InvalidateScreen( 646 helper_.InvalidateScreen(
667 SkISize::Make(desktop_config_.pixel_bounds.width(), 647 webrtc::DesktopSize(desktop_config_.pixel_bounds.width(),
668 desktop_config_.pixel_bounds.height())); 648 desktop_config_.pixel_bounds.height()));
669 649
670 // Make sure the frame buffers will be reallocated. 650 // Make sure the frame buffers will be reallocated.
671 queue_.SetAllFramesNeedUpdate(); 651 queue_.Reset();
672 652
673 // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's 653 // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's
674 // contents. Although the API exists in OS 10.6, it crashes the caller if 654 // 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 655 // the machine has no monitor connected, so we fall back to depcreated APIs
676 // when running on 10.6. 656 // when running on 10.6.
677 if (base::mac::IsOSLionOrLater()) { 657 if (base::mac::IsOSLionOrLater()) {
678 LOG(INFO) << "Using CgBlitPostLion."; 658 LOG(INFO) << "Using CgBlitPostLion.";
679 // No need for any OpenGL support on Lion 659 // No need for any OpenGL support on Lion
680 return; 660 return;
681 } 661 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 741
762 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() { 742 void ScreenCapturerMac::UnregisterRefreshAndMoveHandlers() {
763 CGUnregisterScreenRefreshCallback( 743 CGUnregisterScreenRefreshCallback(
764 ScreenCapturerMac::ScreenRefreshCallback, this); 744 ScreenCapturerMac::ScreenRefreshCallback, this);
765 CGScreenUnregisterMoveCallback( 745 CGScreenUnregisterMoveCallback(
766 ScreenCapturerMac::ScreenUpdateMoveCallback, this); 746 ScreenCapturerMac::ScreenUpdateMoveCallback, this);
767 } 747 }
768 748
769 void ScreenCapturerMac::ScreenRefresh(CGRectCount count, 749 void ScreenCapturerMac::ScreenRefresh(CGRectCount count,
770 const CGRect* rect_array) { 750 const CGRect* rect_array) {
771 if (desktop_config_.pixel_bounds.isEmpty()) { 751 if (desktop_config_.pixel_bounds.is_empty())
772 return; 752 return;
773 } 753
774 SkIRect skirect_array[count]; 754 webrtc::DesktopRegion region;
775 755
776 for (CGRectCount i = 0; i < count; ++i) { 756 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. 757 // Convert from Density-Independent Pixel to physical pixel coordinates.
780 sk_rect = ScaleSkRect(sk_rect, desktop_config_.dip_to_pixel_scale); 758 webrtc::DesktopRect rect =
781 sk_rect.round(&skirect_array[i]); 759 ScaleAndRoundCGRect(rect_array[i], desktop_config_.dip_to_pixel_scale);
782 760
783 // Translate from local desktop to capturer framebuffer coordinates. 761 // Translate from local desktop to capturer framebuffer coordinates.
784 skirect_array[i].offset(-desktop_config_.pixel_bounds.left(), 762 rect.Translate(-desktop_config_.pixel_bounds.left(),
785 -desktop_config_.pixel_bounds.top()); 763 -desktop_config_.pixel_bounds.top());
764
765 region.AddRect(rect);
786 } 766 }
787 767
788 SkRegion region;
789 region.setRects(skirect_array, count);
790 helper_.InvalidateRegion(region); 768 helper_.InvalidateRegion(region);
791 } 769 }
792 770
793 void ScreenCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, 771 void ScreenCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
794 size_t count, 772 size_t count,
795 const CGRect* rect_array) { 773 const CGRect* rect_array) {
796 // Translate |rect_array| to identify the move's destination. 774 // Translate |rect_array| to identify the move's destination.
797 CGRect refresh_rects[count]; 775 CGRect refresh_rects[count];
798 for (CGRectCount i = 0; i < count; ++i) { 776 for (CGRectCount i = 0; i < count; ++i) {
799 refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY); 777 refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY);
(...skipping 28 matching lines...) Expand all
828 // the reconfiguration handler itself). 806 // the reconfiguration handler itself).
829 UnregisterRefreshAndMoveHandlers(); 807 UnregisterRefreshAndMoveHandlers();
830 RegisterRefreshAndMoveHandlers(); 808 RegisterRefreshAndMoveHandlers();
831 ScreenConfigurationChanged(); 809 ScreenConfigurationChanged();
832 display_configuration_capture_event_.Signal(); 810 display_configuration_capture_event_.Signal();
833 } 811 }
834 } 812 }
835 } 813 }
836 814
837 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count, 815 void ScreenCapturerMac::ScreenRefreshCallback(CGRectCount count,
838 const CGRect* rect_array, 816 const CGRect* rect_array,
839 void* user_parameter) { 817 void* user_parameter) {
840 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>( 818 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>(
841 user_parameter); 819 user_parameter);
842 if (capturer->desktop_config_.pixel_bounds.isEmpty()) { 820 if (capturer->desktop_config_.pixel_bounds.is_empty()) {
843 capturer->ScreenConfigurationChanged(); 821 capturer->ScreenConfigurationChanged();
844 } 822 }
845 capturer->ScreenRefresh(count, rect_array); 823 capturer->ScreenRefresh(count, rect_array);
846 } 824 }
847 825
848 void ScreenCapturerMac::ScreenUpdateMoveCallback( 826 void ScreenCapturerMac::ScreenUpdateMoveCallback(
849 CGScreenUpdateMoveDelta delta, 827 CGScreenUpdateMoveDelta delta,
850 size_t count, 828 size_t count,
851 const CGRect* rect_array, 829 const CGRect* rect_array,
852 void* user_parameter) { 830 void* user_parameter) {
853 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>( 831 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>(
854 user_parameter); 832 user_parameter);
855 capturer->ScreenUpdateMove(delta, count, rect_array); 833 capturer->ScreenUpdateMove(delta, count, rect_array);
856 } 834 }
857 835
858 void ScreenCapturerMac::DisplaysReconfiguredCallback( 836 void ScreenCapturerMac::DisplaysReconfiguredCallback(
859 CGDirectDisplayID display, 837 CGDirectDisplayID display,
860 CGDisplayChangeSummaryFlags flags, 838 CGDisplayChangeSummaryFlags flags,
861 void* user_parameter) { 839 void* user_parameter) {
862 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>( 840 ScreenCapturerMac* capturer = reinterpret_cast<ScreenCapturerMac*>(
863 user_parameter); 841 user_parameter);
864 capturer->DisplaysReconfigured(display, flags); 842 capturer->DisplaysReconfigured(display, flags);
865 } 843 }
866 844
867 } // namespace 845 } // namespace
868 846
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 847 // static
879 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() { 848 scoped_ptr<ScreenCapturer> ScreenCapturer::Create() {
880 scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac()); 849 scoped_ptr<ScreenCapturerMac> capturer(new ScreenCapturerMac());
881 if (!capturer->Init()) 850 if (!capturer->Init())
882 capturer.reset(); 851 capturer.reset();
883 return capturer.PassAs<ScreenCapturer>(); 852 return capturer.PassAs<ScreenCapturer>();
884 } 853 }
885 854
886 } // namespace media 855 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698