Chromium Code Reviews| 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/video_frame_capturer.h" | 5 #include "remoting/host/video_frame_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> |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 | 106 |
| 107 // A class to perform video frame capturing for mac. | 107 // A class to perform video frame capturing for mac. |
| 108 class VideoFrameCapturerMac : public VideoFrameCapturer { | 108 class VideoFrameCapturerMac : public VideoFrameCapturer { |
| 109 public: | 109 public: |
| 110 VideoFrameCapturerMac(); | 110 VideoFrameCapturerMac(); |
| 111 virtual ~VideoFrameCapturerMac(); | 111 virtual ~VideoFrameCapturerMac(); |
| 112 | 112 |
| 113 bool Init(); | 113 bool Init(); |
| 114 | 114 |
| 115 // Overridden from VideoFrameCapturer: | 115 // Overridden from VideoFrameCapturer: |
| 116 virtual void Start(const CursorShapeChangedCallback& callback) OVERRIDE; | 116 virtual void Start(Delegate* delegate) OVERRIDE; |
| 117 virtual void Stop() OVERRIDE; | 117 virtual void Stop() OVERRIDE; |
| 118 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; | 118 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; |
| 119 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; | 119 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; |
| 120 virtual void CaptureInvalidRegion( | 120 virtual void CaptureInvalidRegion() OVERRIDE; |
| 121 const CaptureCompletedCallback& callback) OVERRIDE; | |
| 122 virtual const SkISize& size_most_recent() const OVERRIDE; | 121 virtual const SkISize& size_most_recent() const OVERRIDE; |
| 123 | 122 |
| 124 private: | 123 private: |
| 125 void CaptureCursor(); | 124 void CaptureCursor(); |
| 126 | 125 |
| 127 void GlBlitFast(const VideoFrameBuffer& buffer, const SkRegion& region); | 126 void GlBlitFast(const VideoFrameBuffer& buffer, const SkRegion& region); |
| 128 void GlBlitSlow(const VideoFrameBuffer& buffer); | 127 void GlBlitSlow(const VideoFrameBuffer& buffer); |
| 129 void CgBlitPreLion(const VideoFrameBuffer& buffer, const SkRegion& region); | 128 void CgBlitPreLion(const VideoFrameBuffer& buffer, const SkRegion& region); |
| 130 void CgBlitPostLion(const VideoFrameBuffer& buffer, const SkRegion& region); | 129 void CgBlitPostLion(const VideoFrameBuffer& buffer, const SkRegion& region); |
| 131 void CaptureRegion(const SkRegion& region, | |
| 132 const CaptureCompletedCallback& callback); | |
| 133 | 130 |
| 134 // Called when the screen configuration is changed. | 131 // Called when the screen configuration is changed. |
| 135 void ScreenConfigurationChanged(); | 132 void ScreenConfigurationChanged(); |
| 136 | 133 |
| 137 void ScreenRefresh(CGRectCount count, const CGRect *rect_array); | 134 void ScreenRefresh(CGRectCount count, const CGRect *rect_array); |
| 138 void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, | 135 void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, |
| 139 size_t count, | 136 size_t count, |
| 140 const CGRect *rect_array); | 137 const CGRect *rect_array); |
| 141 void DisplaysReconfigured(CGDirectDisplayID display, | 138 void DisplaysReconfigured(CGDirectDisplayID display, |
| 142 CGDisplayChangeSummaryFlags flags); | 139 CGDisplayChangeSummaryFlags flags); |
| 143 static void ScreenRefreshCallback(CGRectCount count, | 140 static void ScreenRefreshCallback(CGRectCount count, |
| 144 const CGRect *rect_array, | 141 const CGRect *rect_array, |
| 145 void *user_parameter); | 142 void *user_parameter); |
| 146 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, | 143 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, |
| 147 size_t count, | 144 size_t count, |
| 148 const CGRect *rect_array, | 145 const CGRect *rect_array, |
| 149 void *user_parameter); | 146 void *user_parameter); |
| 150 static void DisplaysReconfiguredCallback(CGDirectDisplayID display, | 147 static void DisplaysReconfiguredCallback(CGDirectDisplayID display, |
| 151 CGDisplayChangeSummaryFlags flags, | 148 CGDisplayChangeSummaryFlags flags, |
| 152 void *user_parameter); | 149 void *user_parameter); |
| 153 | 150 |
| 154 void ReleaseBuffers(); | 151 void ReleaseBuffers(); |
| 155 | 152 |
| 153 Delegate* delegate_; | |
| 154 | |
| 156 CGLContextObj cgl_context_; | 155 CGLContextObj cgl_context_; |
| 157 static const int kNumBuffers = 2; | 156 static const int kNumBuffers = 2; |
| 158 ScopedPixelBufferObject pixel_buffer_object_; | 157 ScopedPixelBufferObject pixel_buffer_object_; |
| 159 VideoFrameBuffer buffers_[kNumBuffers]; | 158 VideoFrameBuffer buffers_[kNumBuffers]; |
| 160 | 159 |
| 161 // Current display configuration. | 160 // Current display configuration. |
| 162 std::vector<CGDirectDisplayID> display_ids_; | 161 std::vector<CGDirectDisplayID> display_ids_; |
| 163 SkIRect desktop_bounds_; | 162 SkIRect desktop_bounds_; |
| 164 | 163 |
| 165 // A thread-safe list of invalid rectangles, and the size of the most | 164 // A thread-safe list of invalid rectangles, and the size of the most |
| 166 // recently captured screen. | 165 // recently captured screen. |
| 167 VideoFrameCapturerHelper helper_; | 166 VideoFrameCapturerHelper helper_; |
| 168 | 167 |
| 169 // Callback notified whenever the cursor shape is changed. | |
| 170 CursorShapeChangedCallback cursor_shape_changed_callback_; | |
| 171 | |
| 172 // Image of the last cursor that we sent to the client. | 168 // Image of the last cursor that we sent to the client. |
| 173 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; | 169 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; |
| 174 | 170 |
| 175 // The current buffer with valid data for reading. | 171 // The current buffer with valid data for reading. |
| 176 int current_buffer_; | 172 int current_buffer_; |
| 177 | 173 |
| 178 // The previous buffer into which we captured, or NULL for the first capture | 174 // The previous buffer into which we captured, or NULL for the first capture |
| 179 // for a particular screen resolution. | 175 // for a particular screen resolution. |
| 180 uint8* last_buffer_; | 176 uint8* last_buffer_; |
| 181 | 177 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 200 CGDisplayBaseAddressFunc cg_display_base_address_; | 196 CGDisplayBaseAddressFunc cg_display_base_address_; |
| 201 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; | 197 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; |
| 202 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; | 198 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; |
| 203 base::ScopedNativeLibrary opengl_library_; | 199 base::ScopedNativeLibrary opengl_library_; |
| 204 CGLSetFullScreenFunc cgl_set_full_screen_; | 200 CGLSetFullScreenFunc cgl_set_full_screen_; |
| 205 | 201 |
| 206 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac); | 202 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac); |
| 207 }; | 203 }; |
| 208 | 204 |
| 209 VideoFrameCapturerMac::VideoFrameCapturerMac() | 205 VideoFrameCapturerMac::VideoFrameCapturerMac() |
| 210 : cgl_context_(NULL), | 206 : delegate_(NULL), |
| 207 cgl_context_(NULL), | |
| 211 current_buffer_(0), | 208 current_buffer_(0), |
| 212 last_buffer_(NULL), | 209 last_buffer_(NULL), |
| 213 pixel_format_(media::VideoFrame::RGB32), | 210 pixel_format_(media::VideoFrame::RGB32), |
| 214 display_configuration_capture_event_(false, true), | 211 display_configuration_capture_event_(false, true), |
| 215 power_assertion_id_display_(kIOPMNullAssertionID), | 212 power_assertion_id_display_(kIOPMNullAssertionID), |
| 216 power_assertion_id_user_(kIOPMNullAssertionID), | 213 power_assertion_id_user_(kIOPMNullAssertionID), |
| 217 cg_display_base_address_(NULL), | 214 cg_display_base_address_(NULL), |
| 218 cg_display_bytes_per_row_(NULL), | 215 cg_display_bytes_per_row_(NULL), |
| 219 cg_display_bits_per_pixel_(NULL), | 216 cg_display_bits_per_pixel_(NULL), |
| 220 cgl_set_full_screen_(NULL) | 217 cgl_set_full_screen_(NULL) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 cgl_context_ = NULL; | 263 cgl_context_ = NULL; |
| 267 } | 264 } |
| 268 // The buffers might be in use by the encoder, so don't delete them here. | 265 // The buffers might be in use by the encoder, so don't delete them here. |
| 269 // Instead, mark them as "needs update"; next time the buffers are used by | 266 // Instead, mark them as "needs update"; next time the buffers are used by |
| 270 // the capturer, they will be recreated if necessary. | 267 // the capturer, they will be recreated if necessary. |
| 271 for (int i = 0; i < kNumBuffers; ++i) { | 268 for (int i = 0; i < kNumBuffers; ++i) { |
| 272 buffers_[i].set_needs_update(); | 269 buffers_[i].set_needs_update(); |
| 273 } | 270 } |
| 274 } | 271 } |
| 275 | 272 |
| 276 void VideoFrameCapturerMac::Start(const CursorShapeChangedCallback& callback) { | 273 void VideoFrameCapturerMac::Start(Delegate* delegate) { |
| 277 cursor_shape_changed_callback_ = callback; | 274 DCHECK(delegate_ == NULL); |
| 275 | |
| 276 delegate_ = delegate; | |
| 278 | 277 |
| 279 // Create power management assertions to wake the display and prevent it from | 278 // Create power management assertions to wake the display and prevent it from |
| 280 // going to sleep on user idle. | 279 // going to sleep on user idle. |
| 281 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above | 280 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above |
| 282 // instead of the following two assertions. | 281 // instead of the following two assertions. |
| 283 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, | 282 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, |
| 284 kIOPMAssertionLevelOn, | 283 kIOPMAssertionLevelOn, |
| 285 CFSTR("Chrome Remote Desktop connection active"), | 284 CFSTR("Chrome Remote Desktop connection active"), |
| 286 &power_assertion_id_display_); | 285 &power_assertion_id_display_); |
| 287 // This assertion ensures that the display is woken up if it already asleep | 286 // This assertion ensures that the display is woken up if it already asleep |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 304 } | 303 } |
| 305 | 304 |
| 306 media::VideoFrame::Format VideoFrameCapturerMac::pixel_format() const { | 305 media::VideoFrame::Format VideoFrameCapturerMac::pixel_format() const { |
| 307 return pixel_format_; | 306 return pixel_format_; |
| 308 } | 307 } |
| 309 | 308 |
| 310 void VideoFrameCapturerMac::InvalidateRegion(const SkRegion& invalid_region) { | 309 void VideoFrameCapturerMac::InvalidateRegion(const SkRegion& invalid_region) { |
| 311 helper_.InvalidateRegion(invalid_region); | 310 helper_.InvalidateRegion(invalid_region); |
| 312 } | 311 } |
| 313 | 312 |
| 314 void VideoFrameCapturerMac::CaptureInvalidRegion( | 313 void VideoFrameCapturerMac::CaptureInvalidRegion() { |
|
simonmorris
2012/11/07 20:35:21
DCHECK(delegate_ != NULL) ?
alexeypa (please no reviews)
2012/11/07 20:54:41
Same as before.
| |
| 315 const CaptureCompletedCallback& callback) { | |
| 316 // Only allow captures when the display configuration is not occurring. | 314 // Only allow captures when the display configuration is not occurring. |
| 317 scoped_refptr<CaptureData> data; | 315 scoped_refptr<CaptureData> data; |
| 318 | 316 |
| 319 // Critical section shared with DisplaysReconfigured(...). | 317 // Critical section shared with DisplaysReconfigured(...). |
| 320 CHECK(display_configuration_capture_event_.TimedWait( | 318 CHECK(display_configuration_capture_event_.TimedWait( |
| 321 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); | 319 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); |
| 322 SkRegion region; | 320 SkRegion region; |
| 323 helper_.SwapInvalidRegion(®ion); | 321 helper_.SwapInvalidRegion(®ion); |
| 324 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; | 322 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; |
| 325 current_buffer.Update(SkISize::Make(desktop_bounds_.width(), | 323 current_buffer.Update(SkISize::Make(desktop_bounds_.width(), |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 355 data = new CaptureData(planes, current_buffer.size(), pixel_format()); | 353 data = new CaptureData(planes, current_buffer.size(), pixel_format()); |
| 356 data->set_dpi(current_buffer.dpi()); | 354 data->set_dpi(current_buffer.dpi()); |
| 357 data->mutable_dirty_region() = region; | 355 data->mutable_dirty_region() = region; |
| 358 | 356 |
| 359 current_buffer_ = (current_buffer_ + 1) % kNumBuffers; | 357 current_buffer_ = (current_buffer_ + 1) % kNumBuffers; |
| 360 helper_.set_size_most_recent(data->size()); | 358 helper_.set_size_most_recent(data->size()); |
| 361 display_configuration_capture_event_.Signal(); | 359 display_configuration_capture_event_.Signal(); |
| 362 | 360 |
| 363 CaptureCursor(); | 361 CaptureCursor(); |
| 364 | 362 |
| 365 callback.Run(data); | 363 delegate->OnCaptureCompleted(data); |
| 366 } | 364 } |
| 367 | 365 |
| 368 void VideoFrameCapturerMac::CaptureCursor() { | 366 void VideoFrameCapturerMac::CaptureCursor() { |
|
simonmorris
2012/11/07 20:35:21
Return if delegate_ is NULL?
alexeypa (please no reviews)
2012/11/07 20:54:41
|delegate_| cannot be NULL. That check was a devel
| |
| 369 if (cursor_shape_changed_callback_.is_null()) { | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 NSCursor* cursor = [NSCursor currentSystemCursor]; | 367 NSCursor* cursor = [NSCursor currentSystemCursor]; |
| 374 if (cursor == nil) { | 368 if (cursor == nil) { |
| 375 return; | 369 return; |
| 376 } | 370 } |
| 377 | 371 |
| 378 NSImage* nsimage = [cursor image]; | 372 NSImage* nsimage = [cursor image]; |
| 379 NSPoint hotspot = [cursor hotSpot]; | 373 NSPoint hotspot = [cursor hotSpot]; |
| 380 NSSize size = [nsimage size]; | 374 NSSize size = [nsimage size]; |
| 381 CGImageRef image = [nsimage CGImageForProposedRect:NULL | 375 CGImageRef image = [nsimage CGImageForProposedRect:NULL |
| 382 context:nil | 376 context:nil |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 cursor_proto->mutable_data()->resize(data_size); | 432 cursor_proto->mutable_data()->resize(data_size); |
| 439 uint8* cursor_tgt_data = const_cast<uint8*>(reinterpret_cast<const uint8*>( | 433 uint8* cursor_tgt_data = const_cast<uint8*>(reinterpret_cast<const uint8*>( |
| 440 cursor_proto->mutable_data()->data())); | 434 cursor_proto->mutable_data()->data())); |
| 441 | 435 |
| 442 memcpy(cursor_tgt_data, cursor_src_data, data_size); | 436 memcpy(cursor_tgt_data, cursor_src_data, data_size); |
| 443 | 437 |
| 444 cursor_proto->set_width(size.width); | 438 cursor_proto->set_width(size.width); |
| 445 cursor_proto->set_height(size.height); | 439 cursor_proto->set_height(size.height); |
| 446 cursor_proto->set_hotspot_x(hotspot.x); | 440 cursor_proto->set_hotspot_x(hotspot.x); |
| 447 cursor_proto->set_hotspot_y(hotspot.y); | 441 cursor_proto->set_hotspot_y(hotspot.y); |
| 448 cursor_shape_changed_callback_.Run(cursor_proto.Pass()); | 442 delegate_->OnCursorShapeChanged(cursor_proto.Pass()); |
| 449 | 443 |
| 450 // Record the last cursor image that we sent. | 444 // Record the last cursor image that we sent. |
| 451 current_cursor_.reset(CGImageCreateCopy(image)); | 445 current_cursor_.reset(CGImageCreateCopy(image)); |
| 452 } | 446 } |
| 453 | 447 |
| 454 void VideoFrameCapturerMac::GlBlitFast(const VideoFrameBuffer& buffer, | 448 void VideoFrameCapturerMac::GlBlitFast(const VideoFrameBuffer& buffer, |
| 455 const SkRegion& region) { | 449 const SkRegion& region) { |
| 456 const int buffer_height = buffer.size().height(); | 450 const int buffer_height = buffer.size().height(); |
| 457 const int buffer_width = buffer.size().width(); | 451 const int buffer_width = buffer.size().width(); |
| 458 | 452 |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 830 VideoFrameCapturer* VideoFrameCapturer::Create() { | 824 VideoFrameCapturer* VideoFrameCapturer::Create() { |
| 831 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac(); | 825 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac(); |
| 832 if (!capturer->Init()) { | 826 if (!capturer->Init()) { |
| 833 delete capturer; | 827 delete capturer; |
| 834 capturer = NULL; | 828 capturer = NULL; |
| 835 } | 829 } |
| 836 return capturer; | 830 return capturer; |
| 837 } | 831 } |
| 838 | 832 |
| 839 } // namespace remoting | 833 } // namespace remoting |
| OLD | NEW |