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 kPMAssertionTimeoutMs = 5 * 1000; // 30 seconds | |
Wez
2012/04/14 00:08:22
This looks like five seconds, not thirty?
Wez
2012/04/14 00:08:22
See note below re naming.
dcaiafa
2012/04/14 00:21:41
Done.
dcaiafa
2012/04/14 00:21:41
Done.
| |
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 RefreshPowerManagementAssertion(); | |
201 void ReleasePowerManagementAssertion(); | |
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 pm_assertion_id_; | |
Wez
2012/04/14 00:08:22
Style guide requires that names not be abbreviated
dcaiafa
2012/04/14 00:21:41
Done.
| |
234 | |
235 // Indicates that a power management assertion was created and that | |
236 // pm_assertion_id_ is valid. | |
237 bool pm_assertion_created_; | |
Wez
2012/04/14 00:08:22
Why not just check whether the timer is started, r
dcaiafa
2012/04/14 00:21:41
Because when ReleasePowerAssertion is called by th
Wez
2012/04/14 00:24:39
OK. Is zero a valid power management assertion Id
dcaiafa
2012/04/14 00:37:43
Turns out that there is a constant called kIOPMNul
| |
238 | |
239 // Timer to remove the power management assertion on inactivity | |
240 base::OneShotTimer<CapturerMac> pm_assertion_timer_; | |
241 | |
224 DISALLOW_COPY_AND_ASSIGN(CapturerMac); | 242 DISALLOW_COPY_AND_ASSIGN(CapturerMac); |
225 }; | 243 }; |
226 | 244 |
227 CapturerMac::CapturerMac() | 245 CapturerMac::CapturerMac() |
228 : cgl_context_(NULL), | 246 : cgl_context_(NULL), |
229 current_buffer_(0), | 247 current_buffer_(0), |
230 last_buffer_(NULL), | 248 last_buffer_(NULL), |
231 pixel_format_(media::VideoFrame::RGB32), | 249 pixel_format_(media::VideoFrame::RGB32), |
232 display_configuration_capture_event_(false, true), | 250 display_configuration_capture_event_(false, true), |
233 display_create_image_func_(NULL) { | 251 display_create_image_func_(NULL), |
252 pm_assertion_id_(0), | |
253 pm_assertion_created_(false) { | |
234 } | 254 } |
235 | 255 |
236 CapturerMac::~CapturerMac() { | 256 CapturerMac::~CapturerMac() { |
237 ReleaseBuffers(); | 257 ReleaseBuffers(); |
238 CGUnregisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, this); | 258 CGUnregisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, this); |
239 CGScreenUnregisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback, this); | 259 CGScreenUnregisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback, this); |
240 CGError err = CGDisplayRemoveReconfigurationCallback( | 260 CGError err = CGDisplayRemoveReconfigurationCallback( |
241 CapturerMac::DisplaysReconfiguredCallback, this); | 261 CapturerMac::DisplaysReconfiguredCallback, this); |
242 if (err != kCGErrorSuccess) { | 262 if (err != kCGErrorSuccess) { |
243 LOG(ERROR) << "CGDisplayRemoveReconfigurationCallback " << err; | 263 LOG(ERROR) << "CGDisplayRemoveReconfigurationCallback " << err; |
244 } | 264 } |
265 ReleasePowerManagementAssertion(); | |
245 } | 266 } |
246 | 267 |
247 bool CapturerMac::Init() { | 268 bool CapturerMac::Init() { |
248 CGError err = | 269 CGError err = |
249 CGRegisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, | 270 CGRegisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, |
250 this); | 271 this); |
251 if (err != kCGErrorSuccess) { | 272 if (err != kCGErrorSuccess) { |
252 LOG(ERROR) << "CGRegisterScreenRefreshCallback " << err; | 273 LOG(ERROR) << "CGRegisterScreenRefreshCallback " << err; |
253 return false; | 274 return false; |
254 } | 275 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
353 | 374 |
354 void CapturerMac::InvalidateFullScreen() { | 375 void CapturerMac::InvalidateFullScreen() { |
355 helper_.InvalidateFullScreen(); | 376 helper_.InvalidateFullScreen(); |
356 } | 377 } |
357 | 378 |
358 void CapturerMac::CaptureInvalidRegion( | 379 void CapturerMac::CaptureInvalidRegion( |
359 const CaptureCompletedCallback& callback) { | 380 const CaptureCompletedCallback& callback) { |
360 // Only allow captures when the display configuration is not occurring. | 381 // Only allow captures when the display configuration is not occurring. |
361 scoped_refptr<CaptureData> data; | 382 scoped_refptr<CaptureData> data; |
362 | 383 |
384 RefreshPowerManagementAssertion(); | |
385 | |
363 // Critical section shared with DisplaysReconfigured(...). | 386 // Critical section shared with DisplaysReconfigured(...). |
364 CHECK(display_configuration_capture_event_.TimedWait( | 387 CHECK(display_configuration_capture_event_.TimedWait( |
365 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); | 388 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); |
366 SkRegion region; | 389 SkRegion region; |
367 helper_.SwapInvalidRegion(®ion); | 390 helper_.SwapInvalidRegion(®ion); |
368 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; | 391 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; |
369 current_buffer.Update(); | 392 current_buffer.Update(); |
370 | 393 |
371 bool flip = false; // GL capturers need flipping. | 394 bool flip = false; // GL capturers need flipping. |
372 if (display_create_image_func_ != NULL) { | 395 if (display_create_image_func_ != NULL) { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
619 } | 642 } |
620 | 643 |
621 void CapturerMac::DisplaysReconfiguredCallback( | 644 void CapturerMac::DisplaysReconfiguredCallback( |
622 CGDirectDisplayID display, | 645 CGDirectDisplayID display, |
623 CGDisplayChangeSummaryFlags flags, | 646 CGDisplayChangeSummaryFlags flags, |
624 void *user_parameter) { | 647 void *user_parameter) { |
625 CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter); | 648 CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter); |
626 capturer->DisplaysReconfigured(display, flags); | 649 capturer->DisplaysReconfigured(display, flags); |
627 } | 650 } |
628 | 651 |
652 // Creates or refreshes a power management assertion to prevent the display from | |
653 // going to sleep. | |
654 void CapturerMac::RefreshPowerManagementAssertion() { | |
655 if (pm_assertion_timer_.IsRunning()) { | |
656 DCHECK(pm_assertion_created_); | |
657 pm_assertion_timer_.Reset(); | |
658 return; | |
659 } | |
660 | |
661 IOReturn result = IOPMAssertionCreateWithName( | |
662 kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, | |
663 CFSTR("Chromoting"), &pm_assertion_id_); | |
664 | |
665 if (result == kIOReturnSuccess) { | |
666 pm_assertion_created_ = true; | |
667 pm_assertion_timer_.Start(FROM_HERE, | |
668 base::TimeDelta::FromMilliseconds( | |
669 kPMAssertionTimeoutMs), | |
670 this, | |
671 &CapturerMac::ReleasePowerManagementAssertion); | |
672 } | |
673 } | |
674 | |
675 void CapturerMac::ReleasePowerManagementAssertion() { | |
676 if (pm_assertion_created_) { | |
677 IOPMAssertionRelease(pm_assertion_id_); | |
678 pm_assertion_id_ = 0; | |
Wez
2012/04/14 00:08:22
nit: Zeroing this when it's not started effectivel
dcaiafa
2012/04/14 00:21:41
Done.
| |
679 pm_assertion_created_ = false; | |
680 pm_assertion_timer_.Stop(); | |
681 } | |
682 } | |
683 | |
629 } // namespace | 684 } // namespace |
630 | 685 |
631 // static | 686 // static |
632 Capturer* Capturer::Create() { | 687 Capturer* Capturer::Create() { |
633 CapturerMac* capturer = new CapturerMac(); | 688 CapturerMac* capturer = new CapturerMac(); |
634 if (!capturer->Init()) { | 689 if (!capturer->Init()) { |
635 delete capturer; | 690 delete capturer; |
636 capturer = NULL; | 691 capturer = NULL; |
637 } | 692 } |
638 return capturer; | 693 return capturer; |
639 } | 694 } |
640 | 695 |
641 } // namespace remoting | 696 } // namespace remoting |
OLD | NEW |