OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/desktop_capture/screen_capturer.h" | 11 #include "webrtc/modules/desktop_capture/screen_capturer.h" |
12 | 12 |
13 #include <stddef.h> | 13 #include <stddef.h> |
14 | 14 |
15 #include <memory> | 15 #include <memory> |
16 #include <set> | 16 #include <set> |
17 | 17 |
18 #include <ApplicationServices/ApplicationServices.h> | 18 #include <ApplicationServices/ApplicationServices.h> |
19 #include <Cocoa/Cocoa.h> | 19 #include <Cocoa/Cocoa.h> |
20 #include <dlfcn.h> | 20 #include <dlfcn.h> |
21 #include <IOKit/pwr_mgt/IOPMLib.h> | 21 #include <IOKit/pwr_mgt/IOPMLib.h> |
22 #include <OpenGL/CGLMacro.h> | 22 #include <OpenGL/CGLMacro.h> |
23 #include <OpenGL/OpenGL.h> | 23 #include <OpenGL/OpenGL.h> |
24 | 24 |
25 #include "webrtc/base/checks.h" | |
26 #include "webrtc/base/macutils.h" | 25 #include "webrtc/base/macutils.h" |
27 #include "webrtc/base/thread_checker.h" | |
28 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" | 26 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" |
29 #include "webrtc/modules/desktop_capture/desktop_frame.h" | 27 #include "webrtc/modules/desktop_capture/desktop_frame.h" |
30 #include "webrtc/modules/desktop_capture/desktop_geometry.h" | 28 #include "webrtc/modules/desktop_capture/desktop_geometry.h" |
31 #include "webrtc/modules/desktop_capture/desktop_region.h" | 29 #include "webrtc/modules/desktop_capture/desktop_region.h" |
32 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" | 30 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" |
33 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h" | 31 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h" |
34 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h" | 32 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h" |
35 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" | 33 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" |
36 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" | 34 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" |
37 #include "webrtc/system_wrappers/include/logging.h" | 35 #include "webrtc/system_wrappers/include/logging.h" |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 window_bounds, window_list, kCGWindowImageDefault); | 181 window_bounds, window_list, kCGWindowImageDefault); |
184 } | 182 } |
185 | 183 |
186 // A class to perform video frame capturing for mac. | 184 // A class to perform video frame capturing for mac. |
187 class ScreenCapturerMac : public ScreenCapturer { | 185 class ScreenCapturerMac : public ScreenCapturer { |
188 public: | 186 public: |
189 explicit ScreenCapturerMac( | 187 explicit ScreenCapturerMac( |
190 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor); | 188 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor); |
191 virtual ~ScreenCapturerMac(); | 189 virtual ~ScreenCapturerMac(); |
192 | 190 |
| 191 bool Init(); |
| 192 |
193 // Overridden from ScreenCapturer: | 193 // Overridden from ScreenCapturer: |
194 void Start(Callback* callback) override; | 194 void Start(Callback* callback) override; |
195 void Capture(const DesktopRegion& region) override; | 195 void Capture(const DesktopRegion& region) override; |
196 void SetExcludedWindow(WindowId window) override; | 196 void SetExcludedWindow(WindowId window) override; |
197 bool GetScreenList(ScreenList* screens) override; | 197 bool GetScreenList(ScreenList* screens) override; |
198 bool SelectScreen(ScreenId id) override; | 198 bool SelectScreen(ScreenId id) override; |
199 | 199 |
200 private: | 200 private: |
201 bool Initialize(); | |
202 | |
203 void GlBlitFast(const DesktopFrame& frame, | 201 void GlBlitFast(const DesktopFrame& frame, |
204 const DesktopRegion& region); | 202 const DesktopRegion& region); |
205 void GlBlitSlow(const DesktopFrame& frame); | 203 void GlBlitSlow(const DesktopFrame& frame); |
206 void CgBlitPreLion(const DesktopFrame& frame, | 204 void CgBlitPreLion(const DesktopFrame& frame, |
207 const DesktopRegion& region); | 205 const DesktopRegion& region); |
208 // Returns false if the selected screen is no longer valid. | 206 // Returns false if the selected screen is no longer valid. |
209 bool CgBlitPostLion(const DesktopFrame& frame, | 207 bool CgBlitPostLion(const DesktopFrame& frame, |
210 const DesktopRegion& region); | 208 const DesktopRegion& region); |
211 | 209 |
212 // Called when the screen configuration is changed. | 210 // Called when the screen configuration is changed. |
(...skipping 10 matching lines...) Expand all Loading... |
223 const CGRect *rect_array, | 221 const CGRect *rect_array, |
224 void *user_parameter); | 222 void *user_parameter); |
225 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, | 223 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, |
226 size_t count, | 224 size_t count, |
227 const CGRect *rect_array, | 225 const CGRect *rect_array, |
228 void *user_parameter); | 226 void *user_parameter); |
229 void ReleaseBuffers(); | 227 void ReleaseBuffers(); |
230 | 228 |
231 DesktopFrame* CreateFrame(); | 229 DesktopFrame* CreateFrame(); |
232 | 230 |
233 rtc::ThreadChecker thread_checker_; | 231 Callback* callback_; |
234 | 232 |
235 Callback* callback_ = nullptr; | 233 CGLContextObj cgl_context_; |
236 | |
237 CGLContextObj cgl_context_ = nullptr; | |
238 ScopedPixelBufferObject pixel_buffer_object_; | 234 ScopedPixelBufferObject pixel_buffer_object_; |
239 | 235 |
240 // Queue of the frames buffers. | 236 // Queue of the frames buffers. |
241 ScreenCaptureFrameQueue queue_; | 237 ScreenCaptureFrameQueue queue_; |
242 | 238 |
243 // Current display configuration. | 239 // Current display configuration. |
244 MacDesktopConfiguration desktop_config_; | 240 MacDesktopConfiguration desktop_config_; |
245 | 241 |
246 // Currently selected display, or 0 if the full desktop is selected. On OS X | 242 // Currently selected display, or 0 if the full desktop is selected. On OS X |
247 // 10.6 and before, this is always 0. | 243 // 10.6 and before, this is always 0. |
248 CGDirectDisplayID current_display_ = 0; | 244 CGDirectDisplayID current_display_; |
249 | 245 |
250 // The physical pixel bounds of the current screen. | 246 // The physical pixel bounds of the current screen. |
251 DesktopRect screen_pixel_bounds_; | 247 DesktopRect screen_pixel_bounds_; |
252 | 248 |
253 // The dip to physical pixel scale of the current screen. | 249 // The dip to physical pixel scale of the current screen. |
254 float dip_to_pixel_scale_ = 1.0f; | 250 float dip_to_pixel_scale_; |
255 | 251 |
256 // A thread-safe list of invalid rectangles, and the size of the most | 252 // A thread-safe list of invalid rectangles, and the size of the most |
257 // recently captured screen. | 253 // recently captured screen. |
258 ScreenCapturerHelper helper_; | 254 ScreenCapturerHelper helper_; |
259 | 255 |
260 // Contains an invalid region from the previous capture. | 256 // Contains an invalid region from the previous capture. |
261 DesktopRegion last_invalid_region_; | 257 DesktopRegion last_invalid_region_; |
262 | 258 |
263 // Monitoring display reconfiguration. | 259 // Monitoring display reconfiguration. |
264 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor_; | 260 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor_; |
265 | 261 |
266 // Power management assertion to prevent the screen from sleeping. | 262 // Power management assertion to prevent the screen from sleeping. |
267 IOPMAssertionID power_assertion_id_display_ = kIOPMNullAssertionID; | 263 IOPMAssertionID power_assertion_id_display_; |
268 | 264 |
269 // Power management assertion to indicate that the user is active. | 265 // Power management assertion to indicate that the user is active. |
270 IOPMAssertionID power_assertion_id_user_ = kIOPMNullAssertionID; | 266 IOPMAssertionID power_assertion_id_user_; |
271 | 267 |
272 // Dynamically link to deprecated APIs for Mac OS X 10.6 support. | 268 // Dynamically link to deprecated APIs for Mac OS X 10.6 support. |
273 void* app_services_library_ = nullptr; | 269 void* app_services_library_; |
274 CGDisplayBaseAddressFunc cg_display_base_address_ = nullptr; | 270 CGDisplayBaseAddressFunc cg_display_base_address_; |
275 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_ = nullptr; | 271 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; |
276 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_ = nullptr; | 272 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; |
277 void* opengl_library_ = nullptr; | 273 void* opengl_library_; |
278 CGLSetFullScreenFunc cgl_set_full_screen_ = nullptr; | 274 CGLSetFullScreenFunc cgl_set_full_screen_; |
279 | 275 |
280 CGWindowID excluded_window_ = 0; | 276 CGWindowID excluded_window_; |
281 | 277 |
282 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac); | 278 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac); |
283 }; | 279 }; |
284 | 280 |
285 // DesktopFrame wrapper that flips wrapped frame upside down by inverting | 281 // DesktopFrame wrapper that flips wrapped frame upside down by inverting |
286 // stride. | 282 // stride. |
287 class InvertedDesktopFrame : public DesktopFrame { | 283 class InvertedDesktopFrame : public DesktopFrame { |
288 public: | 284 public: |
289 // Takes ownership of |frame|. | 285 // Takes ownership of |frame|. |
290 InvertedDesktopFrame(DesktopFrame* frame) | 286 InvertedDesktopFrame(DesktopFrame* frame) |
291 : DesktopFrame( | 287 : DesktopFrame( |
292 frame->size(), -frame->stride(), | 288 frame->size(), -frame->stride(), |
293 frame->data() + (frame->size().height() - 1) * frame->stride(), | 289 frame->data() + (frame->size().height() - 1) * frame->stride(), |
294 frame->shared_memory()), | 290 frame->shared_memory()), |
295 original_frame_(frame) { | 291 original_frame_(frame) { |
296 set_dpi(frame->dpi()); | 292 set_dpi(frame->dpi()); |
297 set_capture_time_ms(frame->capture_time_ms()); | 293 set_capture_time_ms(frame->capture_time_ms()); |
298 mutable_updated_region()->Swap(frame->mutable_updated_region()); | 294 mutable_updated_region()->Swap(frame->mutable_updated_region()); |
299 } | 295 } |
300 virtual ~InvertedDesktopFrame() {} | 296 virtual ~InvertedDesktopFrame() {} |
301 | 297 |
302 private: | 298 private: |
303 std::unique_ptr<DesktopFrame> original_frame_; | 299 std::unique_ptr<DesktopFrame> original_frame_; |
304 | 300 |
305 RTC_DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame); | 301 RTC_DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame); |
306 }; | 302 }; |
307 | 303 |
308 ScreenCapturerMac::ScreenCapturerMac( | 304 ScreenCapturerMac::ScreenCapturerMac( |
309 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor) | 305 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor) |
310 : desktop_config_monitor_(desktop_config_monitor) { | 306 : callback_(NULL), |
311 // ScreenCapturer can be used on a thread different from the thread on which | 307 cgl_context_(NULL), |
312 // it's created. | 308 current_display_(0), |
313 thread_checker_.DetachFromThread(); | 309 dip_to_pixel_scale_(1.0f), |
| 310 desktop_config_monitor_(desktop_config_monitor), |
| 311 power_assertion_id_display_(kIOPMNullAssertionID), |
| 312 power_assertion_id_user_(kIOPMNullAssertionID), |
| 313 app_services_library_(NULL), |
| 314 cg_display_base_address_(NULL), |
| 315 cg_display_bytes_per_row_(NULL), |
| 316 cg_display_bits_per_pixel_(NULL), |
| 317 opengl_library_(NULL), |
| 318 cgl_set_full_screen_(NULL), |
| 319 excluded_window_(0) { |
314 } | 320 } |
315 | 321 |
316 ScreenCapturerMac::~ScreenCapturerMac() { | 322 ScreenCapturerMac::~ScreenCapturerMac() { |
317 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
318 | |
319 if (power_assertion_id_display_ != kIOPMNullAssertionID) { | 323 if (power_assertion_id_display_ != kIOPMNullAssertionID) { |
320 IOPMAssertionRelease(power_assertion_id_display_); | 324 IOPMAssertionRelease(power_assertion_id_display_); |
321 power_assertion_id_display_ = kIOPMNullAssertionID; | 325 power_assertion_id_display_ = kIOPMNullAssertionID; |
322 } | 326 } |
323 if (power_assertion_id_user_ != kIOPMNullAssertionID) { | 327 if (power_assertion_id_user_ != kIOPMNullAssertionID) { |
324 IOPMAssertionRelease(power_assertion_id_user_); | 328 IOPMAssertionRelease(power_assertion_id_user_); |
325 power_assertion_id_user_ = kIOPMNullAssertionID; | 329 power_assertion_id_user_ = kIOPMNullAssertionID; |
326 } | 330 } |
327 | 331 |
328 ReleaseBuffers(); | 332 ReleaseBuffers(); |
329 UnregisterRefreshAndMoveHandlers(); | 333 UnregisterRefreshAndMoveHandlers(); |
330 dlclose(app_services_library_); | 334 dlclose(app_services_library_); |
331 dlclose(opengl_library_); | 335 dlclose(opengl_library_); |
332 } | 336 } |
333 | 337 |
334 bool ScreenCapturerMac::Initialize() { | 338 bool ScreenCapturerMac::Init() { |
335 if (!RegisterRefreshAndMoveHandlers()) { | 339 if (!RegisterRefreshAndMoveHandlers()) { |
336 return false; | 340 return false; |
337 } | 341 } |
338 desktop_config_monitor_->Lock(); | 342 desktop_config_monitor_->Lock(); |
339 desktop_config_ = desktop_config_monitor_->desktop_configuration(); | 343 desktop_config_ = desktop_config_monitor_->desktop_configuration(); |
340 desktop_config_monitor_->Unlock(); | 344 desktop_config_monitor_->Unlock(); |
341 ScreenConfigurationChanged(); | 345 ScreenConfigurationChanged(); |
342 return true; | 346 return true; |
343 } | 347 } |
344 | 348 |
345 void ScreenCapturerMac::ReleaseBuffers() { | 349 void ScreenCapturerMac::ReleaseBuffers() { |
346 if (cgl_context_) { | 350 if (cgl_context_) { |
347 pixel_buffer_object_.Release(); | 351 pixel_buffer_object_.Release(); |
348 CGLDestroyContext(cgl_context_); | 352 CGLDestroyContext(cgl_context_); |
349 cgl_context_ = NULL; | 353 cgl_context_ = NULL; |
350 } | 354 } |
351 // The buffers might be in use by the encoder, so don't delete them here. | 355 // The buffers might be in use by the encoder, so don't delete them here. |
352 // Instead, mark them as "needs update"; next time the buffers are used by | 356 // Instead, mark them as "needs update"; next time the buffers are used by |
353 // the capturer, they will be recreated if necessary. | 357 // the capturer, they will be recreated if necessary. |
354 queue_.Reset(); | 358 queue_.Reset(); |
355 } | 359 } |
356 | 360 |
357 void ScreenCapturerMac::Start(Callback* callback) { | 361 void ScreenCapturerMac::Start(Callback* callback) { |
358 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 362 assert(!callback_); |
359 RTC_DCHECK(!callback_); | 363 assert(callback); |
360 RTC_DCHECK(callback); | |
361 | 364 |
362 callback_ = callback; | 365 callback_ = callback; |
363 | 366 |
364 if (!Initialize()) { | |
365 callback_->OnInitializationFailed(); | |
366 return; | |
367 } | |
368 | |
369 // Create power management assertions to wake the display and prevent it from | 367 // Create power management assertions to wake the display and prevent it from |
370 // going to sleep on user idle. | 368 // going to sleep on user idle. |
371 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above | 369 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above |
372 // instead of the following two assertions. | 370 // instead of the following two assertions. |
373 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, | 371 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, |
374 kIOPMAssertionLevelOn, | 372 kIOPMAssertionLevelOn, |
375 CFSTR("Chrome Remote Desktop connection active"), | 373 CFSTR("Chrome Remote Desktop connection active"), |
376 &power_assertion_id_display_); | 374 &power_assertion_id_display_); |
377 // This assertion ensures that the display is woken up if it already asleep | 375 // This assertion ensures that the display is woken up if it already asleep |
378 // (as used by Apple Remote Desktop). | 376 // (as used by Apple Remote Desktop). |
379 IOPMAssertionCreateWithName(CFSTR("UserIsActive"), | 377 IOPMAssertionCreateWithName(CFSTR("UserIsActive"), |
380 kIOPMAssertionLevelOn, | 378 kIOPMAssertionLevelOn, |
381 CFSTR("Chrome Remote Desktop connection active"), | 379 CFSTR("Chrome Remote Desktop connection active"), |
382 &power_assertion_id_user_); | 380 &power_assertion_id_user_); |
383 } | 381 } |
384 | 382 |
385 void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) { | 383 void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) { |
386 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
387 | |
388 TickTime capture_start_time = TickTime::Now(); | 384 TickTime capture_start_time = TickTime::Now(); |
389 | 385 |
390 queue_.MoveToNextFrame(); | 386 queue_.MoveToNextFrame(); |
391 | 387 |
392 desktop_config_monitor_->Lock(); | 388 desktop_config_monitor_->Lock(); |
393 MacDesktopConfiguration new_config = | 389 MacDesktopConfiguration new_config = |
394 desktop_config_monitor_->desktop_configuration(); | 390 desktop_config_monitor_->desktop_configuration(); |
395 if (!desktop_config_.Equals(new_config)) { | 391 if (!desktop_config_.Equals(new_config)) { |
396 desktop_config_ = new_config; | 392 desktop_config_ = new_config; |
397 // If the display configuraiton has changed then refresh capturer data | 393 // If the display configuraiton has changed then refresh capturer data |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 // Signal that we are done capturing data from the display framebuffer, | 442 // Signal that we are done capturing data from the display framebuffer, |
447 // and accessing display structures. | 443 // and accessing display structures. |
448 desktop_config_monitor_->Unlock(); | 444 desktop_config_monitor_->Unlock(); |
449 | 445 |
450 new_frame->set_capture_time_ms( | 446 new_frame->set_capture_time_ms( |
451 (TickTime::Now() - capture_start_time).Milliseconds()); | 447 (TickTime::Now() - capture_start_time).Milliseconds()); |
452 callback_->OnCaptureCompleted(new_frame); | 448 callback_->OnCaptureCompleted(new_frame); |
453 } | 449 } |
454 | 450 |
455 void ScreenCapturerMac::SetExcludedWindow(WindowId window) { | 451 void ScreenCapturerMac::SetExcludedWindow(WindowId window) { |
456 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
457 excluded_window_ = window; | 452 excluded_window_ = window; |
458 } | 453 } |
459 | 454 |
460 bool ScreenCapturerMac::GetScreenList(ScreenList* screens) { | 455 bool ScreenCapturerMac::GetScreenList(ScreenList* screens) { |
461 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 456 assert(screens->size() == 0); |
462 RTC_DCHECK(screens->size() == 0); | |
463 | |
464 if (rtc::GetOSVersionName() < rtc::kMacOSLion) { | 457 if (rtc::GetOSVersionName() < rtc::kMacOSLion) { |
465 // Single monitor cast is not supported on pre OS X 10.7. | 458 // Single monitor cast is not supported on pre OS X 10.7. |
466 Screen screen; | 459 Screen screen; |
467 screen.id = kFullDesktopScreenId; | 460 screen.id = kFullDesktopScreenId; |
468 screens->push_back(screen); | 461 screens->push_back(screen); |
469 return true; | 462 return true; |
470 } | 463 } |
471 | 464 |
472 for (MacDisplayConfigurations::iterator it = desktop_config_.displays.begin(); | 465 for (MacDisplayConfigurations::iterator it = desktop_config_.displays.begin(); |
473 it != desktop_config_.displays.end(); ++it) { | 466 it != desktop_config_.displays.end(); ++it) { |
474 Screen screen; | 467 Screen screen; |
475 screen.id = static_cast<ScreenId>(it->id); | 468 screen.id = static_cast<ScreenId>(it->id); |
476 screens->push_back(screen); | 469 screens->push_back(screen); |
477 } | 470 } |
478 return true; | 471 return true; |
479 } | 472 } |
480 | 473 |
481 bool ScreenCapturerMac::SelectScreen(ScreenId id) { | 474 bool ScreenCapturerMac::SelectScreen(ScreenId id) { |
482 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
483 | |
484 if (rtc::GetOSVersionName() < rtc::kMacOSLion) { | 475 if (rtc::GetOSVersionName() < rtc::kMacOSLion) { |
485 // Ignore the screen selection on unsupported OS. | 476 // Ignore the screen selection on unsupported OS. |
486 assert(!current_display_); | 477 assert(!current_display_); |
487 return id == kFullDesktopScreenId; | 478 return id == kFullDesktopScreenId; |
488 } | 479 } |
489 | 480 |
490 if (id == kFullDesktopScreenId) { | 481 if (id == kFullDesktopScreenId) { |
491 current_display_ = 0; | 482 current_display_ = 0; |
492 } else { | 483 } else { |
493 const MacDisplayConfiguration* config = | 484 const MacDisplayConfiguration* config = |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 return frame.release(); | 973 return frame.release(); |
983 } | 974 } |
984 | 975 |
985 } // namespace | 976 } // namespace |
986 | 977 |
987 // static | 978 // static |
988 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { | 979 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { |
989 if (!options.configuration_monitor()) | 980 if (!options.configuration_monitor()) |
990 return NULL; | 981 return NULL; |
991 | 982 |
992 return new ScreenCapturerMac(options.configuration_monitor()); | 983 std::unique_ptr<ScreenCapturerMac> capturer( |
| 984 new ScreenCapturerMac(options.configuration_monitor())); |
| 985 if (!capturer->Init()) |
| 986 capturer.reset(); |
| 987 return capturer.release(); |
993 } | 988 } |
994 | 989 |
995 } // namespace webrtc | 990 } // namespace webrtc |
OLD | NEW |