OLD | NEW |
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 "remoting/host/capturer.h" | 5 #include "remoting/host/capturer.h" |
6 | 6 |
7 #include <ApplicationServices/ApplicationServices.h> | 7 #include <ApplicationServices/ApplicationServices.h> |
8 #include <dlfcn.h> | 8 #include <dlfcn.h> |
| 9 #include <IOKit/pwr_mgt/IOPMLib.h> |
9 #include <OpenGL/CGLMacro.h> | 10 #include <OpenGL/CGLMacro.h> |
10 #include <OpenGL/OpenGL.h> | 11 #include <OpenGL/OpenGL.h> |
11 #include <stddef.h> | 12 #include <stddef.h> |
12 | 13 |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/mac/mac_util.h" | 15 #include "base/mac/mac_util.h" |
15 #include "base/mac/scoped_cftyperef.h" | 16 #include "base/mac/scoped_cftyperef.h" |
16 #include "base/memory/scoped_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
17 #include "base/synchronization/waitable_event.h" | 18 #include "base/synchronization/waitable_event.h" |
| 19 #include "base/time.h" |
| 20 #include "base/timer.h" |
18 #include "remoting/base/util.h" | 21 #include "remoting/base/util.h" |
19 #include "remoting/host/capturer_helper.h" | 22 #include "remoting/host/capturer_helper.h" |
20 | 23 |
21 | 24 |
22 namespace remoting { | 25 namespace remoting { |
23 | 26 |
24 namespace { | 27 namespace { |
25 | 28 |
| 29 const int64 kPowerAssertionTimeoutMs = 5 * 1000; // 5 seconds |
| 30 |
26 SkIRect CGRectToSkIRect(const CGRect& rect) { | 31 SkIRect CGRectToSkIRect(const CGRect& rect) { |
27 SkIRect sk_rect = { | 32 SkIRect sk_rect = { |
28 SkScalarRound(rect.origin.x), | 33 SkScalarRound(rect.origin.x), |
29 SkScalarRound(rect.origin.y), | 34 SkScalarRound(rect.origin.y), |
30 SkScalarRound(rect.origin.x + rect.size.width), | 35 SkScalarRound(rect.origin.x + rect.size.width), |
31 SkScalarRound(rect.origin.y + rect.size.height) | 36 SkScalarRound(rect.origin.y + rect.size.height) |
32 }; | 37 }; |
33 return sk_rect; | 38 return sk_rect; |
34 } | 39 } |
35 | 40 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 void *user_parameter); | 190 void *user_parameter); |
186 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, | 191 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, |
187 size_t count, | 192 size_t count, |
188 const CGRect *rect_array, | 193 const CGRect *rect_array, |
189 void *user_parameter); | 194 void *user_parameter); |
190 static void DisplaysReconfiguredCallback(CGDirectDisplayID display, | 195 static void DisplaysReconfiguredCallback(CGDirectDisplayID display, |
191 CGDisplayChangeSummaryFlags flags, | 196 CGDisplayChangeSummaryFlags flags, |
192 void *user_parameter); | 197 void *user_parameter); |
193 | 198 |
194 void ReleaseBuffers(); | 199 void ReleaseBuffers(); |
| 200 void RefreshPowerAssertion(); |
| 201 void ReleasePowerAssertion(); |
| 202 |
195 CGLContextObj cgl_context_; | 203 CGLContextObj cgl_context_; |
196 static const int kNumBuffers = 2; | 204 static const int kNumBuffers = 2; |
197 scoped_pixel_buffer_object pixel_buffer_object_; | 205 scoped_pixel_buffer_object pixel_buffer_object_; |
198 VideoFrameBuffer buffers_[kNumBuffers]; | 206 VideoFrameBuffer buffers_[kNumBuffers]; |
199 | 207 |
200 // A thread-safe list of invalid rectangles, and the size of the most | 208 // A thread-safe list of invalid rectangles, and the size of the most |
201 // recently captured screen. | 209 // recently captured screen. |
202 CapturerHelper helper_; | 210 CapturerHelper helper_; |
203 | 211 |
204 // The current buffer with valid data for reading. | 212 // The current buffer with valid data for reading. |
205 int current_buffer_; | 213 int current_buffer_; |
206 | 214 |
207 // The previous buffer into which we captured, or NULL for the first capture | 215 // The previous buffer into which we captured, or NULL for the first capture |
208 // for a particular screen resolution. | 216 // for a particular screen resolution. |
209 uint8* last_buffer_; | 217 uint8* last_buffer_; |
210 | 218 |
211 // Contains an invalid region from the previous capture. | 219 // Contains an invalid region from the previous capture. |
212 SkRegion last_invalid_region_; | 220 SkRegion last_invalid_region_; |
213 | 221 |
214 // Format of pixels returned in buffer. | 222 // Format of pixels returned in buffer. |
215 media::VideoFrame::Format pixel_format_; | 223 media::VideoFrame::Format pixel_format_; |
216 | 224 |
217 // Acts as a critical section around our display configuration data | 225 // Acts as a critical section around our display configuration data |
218 // structures. Specifically cgl_context_ and pixel_buffer_object_. | 226 // structures. Specifically cgl_context_ and pixel_buffer_object_. |
219 base::WaitableEvent display_configuration_capture_event_; | 227 base::WaitableEvent display_configuration_capture_event_; |
220 | 228 |
221 // Will be non-null on lion. | 229 // Will be non-null on lion. |
222 CGDisplayCreateImageFunc display_create_image_func_; | 230 CGDisplayCreateImageFunc display_create_image_func_; |
223 | 231 |
| 232 // Power management assertion to prevent the screen from sleeping. |
| 233 IOPMAssertionID power_assertion_id_; |
| 234 |
| 235 // Timer to remove the power management assertion on inactivity |
| 236 base::OneShotTimer<CapturerMac> power_assertion_timer_; |
| 237 |
224 DISALLOW_COPY_AND_ASSIGN(CapturerMac); | 238 DISALLOW_COPY_AND_ASSIGN(CapturerMac); |
225 }; | 239 }; |
226 | 240 |
227 CapturerMac::CapturerMac() | 241 CapturerMac::CapturerMac() |
228 : cgl_context_(NULL), | 242 : cgl_context_(NULL), |
229 current_buffer_(0), | 243 current_buffer_(0), |
230 last_buffer_(NULL), | 244 last_buffer_(NULL), |
231 pixel_format_(media::VideoFrame::RGB32), | 245 pixel_format_(media::VideoFrame::RGB32), |
232 display_configuration_capture_event_(false, true), | 246 display_configuration_capture_event_(false, true), |
233 display_create_image_func_(NULL) { | 247 display_create_image_func_(NULL), |
| 248 power_assertion_id_(kIOPMNullAssertionID) { |
234 } | 249 } |
235 | 250 |
236 CapturerMac::~CapturerMac() { | 251 CapturerMac::~CapturerMac() { |
237 ReleaseBuffers(); | 252 ReleaseBuffers(); |
238 CGUnregisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, this); | 253 CGUnregisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, this); |
239 CGScreenUnregisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback, this); | 254 CGScreenUnregisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback, this); |
240 CGError err = CGDisplayRemoveReconfigurationCallback( | 255 CGError err = CGDisplayRemoveReconfigurationCallback( |
241 CapturerMac::DisplaysReconfiguredCallback, this); | 256 CapturerMac::DisplaysReconfiguredCallback, this); |
242 if (err != kCGErrorSuccess) { | 257 if (err != kCGErrorSuccess) { |
243 LOG(ERROR) << "CGDisplayRemoveReconfigurationCallback " << err; | 258 LOG(ERROR) << "CGDisplayRemoveReconfigurationCallback " << err; |
244 } | 259 } |
| 260 ReleasePowerAssertion(); |
245 } | 261 } |
246 | 262 |
247 bool CapturerMac::Init() { | 263 bool CapturerMac::Init() { |
248 CGError err = | 264 CGError err = |
249 CGRegisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, | 265 CGRegisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, |
250 this); | 266 this); |
251 if (err != kCGErrorSuccess) { | 267 if (err != kCGErrorSuccess) { |
252 LOG(ERROR) << "CGRegisterScreenRefreshCallback " << err; | 268 LOG(ERROR) << "CGRegisterScreenRefreshCallback " << err; |
253 return false; | 269 return false; |
254 } | 270 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 | 369 |
354 void CapturerMac::InvalidateFullScreen() { | 370 void CapturerMac::InvalidateFullScreen() { |
355 helper_.InvalidateFullScreen(); | 371 helper_.InvalidateFullScreen(); |
356 } | 372 } |
357 | 373 |
358 void CapturerMac::CaptureInvalidRegion( | 374 void CapturerMac::CaptureInvalidRegion( |
359 const CaptureCompletedCallback& callback) { | 375 const CaptureCompletedCallback& callback) { |
360 // Only allow captures when the display configuration is not occurring. | 376 // Only allow captures when the display configuration is not occurring. |
361 scoped_refptr<CaptureData> data; | 377 scoped_refptr<CaptureData> data; |
362 | 378 |
| 379 RefreshPowerAssertion(); |
| 380 |
363 // Critical section shared with DisplaysReconfigured(...). | 381 // Critical section shared with DisplaysReconfigured(...). |
364 CHECK(display_configuration_capture_event_.TimedWait( | 382 CHECK(display_configuration_capture_event_.TimedWait( |
365 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); | 383 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); |
366 SkRegion region; | 384 SkRegion region; |
367 helper_.SwapInvalidRegion(®ion); | 385 helper_.SwapInvalidRegion(®ion); |
368 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; | 386 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; |
369 current_buffer.Update(); | 387 current_buffer.Update(); |
370 | 388 |
371 bool flip = false; // GL capturers need flipping. | 389 bool flip = false; // GL capturers need flipping. |
372 if (display_create_image_func_ != NULL) { | 390 if (display_create_image_func_ != NULL) { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 } | 637 } |
620 | 638 |
621 void CapturerMac::DisplaysReconfiguredCallback( | 639 void CapturerMac::DisplaysReconfiguredCallback( |
622 CGDirectDisplayID display, | 640 CGDirectDisplayID display, |
623 CGDisplayChangeSummaryFlags flags, | 641 CGDisplayChangeSummaryFlags flags, |
624 void *user_parameter) { | 642 void *user_parameter) { |
625 CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter); | 643 CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter); |
626 capturer->DisplaysReconfigured(display, flags); | 644 capturer->DisplaysReconfigured(display, flags); |
627 } | 645 } |
628 | 646 |
| 647 // Creates or refreshes a power management assertion to prevent the display from |
| 648 // going to sleep. |
| 649 void CapturerMac::RefreshPowerAssertion() { |
| 650 if (power_assertion_timer_.IsRunning()) { |
| 651 DCHECK(power_assertion_id_ != kIOPMNullAssertionID); |
| 652 power_assertion_timer_.Reset(); |
| 653 return; |
| 654 } |
| 655 |
| 656 IOReturn result = IOPMAssertionCreate(kIOPMAssertionTypeNoDisplaySleep, |
| 657 kIOPMAssertionLevelOn, |
| 658 &power_assertion_id_); |
| 659 |
| 660 if (result == kIOReturnSuccess) { |
| 661 power_assertion_timer_.Start(FROM_HERE, |
| 662 base::TimeDelta::FromMilliseconds( |
| 663 kPowerAssertionTimeoutMs), |
| 664 this, |
| 665 &CapturerMac::ReleasePowerAssertion); |
| 666 } |
| 667 } |
| 668 |
| 669 void CapturerMac::ReleasePowerAssertion() { |
| 670 if (power_assertion_id_ != kIOPMNullAssertionID) { |
| 671 IOPMAssertionRelease(power_assertion_id_); |
| 672 power_assertion_id_ = kIOPMNullAssertionID; |
| 673 power_assertion_timer_.Stop(); |
| 674 } |
| 675 } |
| 676 |
629 } // namespace | 677 } // namespace |
630 | 678 |
631 // static | 679 // static |
632 Capturer* Capturer::Create() { | 680 Capturer* Capturer::Create() { |
633 CapturerMac* capturer = new CapturerMac(); | 681 CapturerMac* capturer = new CapturerMac(); |
634 if (!capturer->Init()) { | 682 if (!capturer->Init()) { |
635 delete capturer; | 683 delete capturer; |
636 capturer = NULL; | 684 capturer = NULL; |
637 } | 685 } |
638 return capturer; | 686 return capturer; |
639 } | 687 } |
640 | 688 |
641 } // namespace remoting | 689 } // namespace remoting |
OLD | NEW |