Index: webrtc/modules/desktop_capture/screen_capturer_mac.mm |
diff --git a/webrtc/modules/desktop_capture/screen_capturer_mac.mm b/webrtc/modules/desktop_capture/screen_capturer_mac.mm |
index 7cb468f7087195fd8d7462996edb03dcad8aeba4..c41dc4d7a3b4ba59e4ebe6880f1e090dae5386b5 100644 |
--- a/webrtc/modules/desktop_capture/screen_capturer_mac.mm |
+++ b/webrtc/modules/desktop_capture/screen_capturer_mac.mm |
@@ -168,8 +168,7 @@ DesktopRect GetExcludedWindowPixelBounds(CGWindowID window, |
// pixels. The caller should release the returned CGImageRef and CFDataRef. |
CGImageRef CreateExcludedWindowRegionImage(const DesktopRect& pixel_bounds, |
float dip_to_pixel_scale, |
- CFArrayRef window_list, |
- CFDataRef* data_ref) { |
+ CFArrayRef window_list) { |
CGRect window_bounds; |
// The origin is in DIP while the size is in physical pixels. That's what |
// CGWindowListCreateImageFromArray expects. |
@@ -178,13 +177,8 @@ CGImageRef CreateExcludedWindowRegionImage(const DesktopRect& pixel_bounds, |
window_bounds.size.width = pixel_bounds.width(); |
window_bounds.size.height = pixel_bounds.height(); |
- CGImageRef excluded_image = CGWindowListCreateImageFromArray( |
+ return CGWindowListCreateImageFromArray( |
window_bounds, window_list, kCGWindowImageDefault); |
- |
- CGDataProviderRef provider = CGImageGetDataProvider(excluded_image); |
- *data_ref = CGDataProviderCopyData(provider); |
- assert(*data_ref); |
- return excluded_image; |
} |
// A class to perform video frame capturing for mac. |
@@ -694,7 +688,6 @@ bool ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame, |
DesktopRect excluded_window_bounds; |
CGImageRef excluded_image = NULL; |
- CFDataRef excluded_window_region_data = NULL; |
if (excluded_window_ && window_list) { |
// Get the region of the excluded window relative the primary display. |
excluded_window_bounds = GetExcludedWindowPixelBounds( |
@@ -705,17 +698,30 @@ bool ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame, |
// than captuing the whole display. |
if (!excluded_window_bounds.is_empty()) { |
excluded_image = CreateExcludedWindowRegionImage( |
- excluded_window_bounds, |
- display_config.dip_to_pixel_scale, |
- window_list, |
- &excluded_window_region_data); |
+ excluded_window_bounds, display_config.dip_to_pixel_scale, |
+ window_list); |
} |
} |
// Create an image containing a snapshot of the display. |
CGImageRef image = CGDisplayCreateImage(display_config.id); |
- if (image == NULL) |
+ if (image == NULL) { |
+ if (excluded_image) |
+ CFRelease(excluded_image); |
continue; |
+ } |
+ |
+ // Verify that the image has 32-bit depth. |
+ int bits_per_pixel = CGImageGetBitsPerPixel(image); |
+ if (bits_per_pixel / 8 != DesktopFrame::kBytesPerPixel) { |
+ LOG(LS_ERROR) << "CGDisplayCreateImage() returned imaged with " |
+ << bits_per_pixel |
+ << " bits per pixel. Only 32-bit depth is supported."; |
+ CFRelease(image); |
+ if (excluded_image) |
+ CFRelease(excluded_image); |
+ return false; |
+ } |
// Request access to the raw pixel data via the image's DataProvider. |
CGDataProviderRef provider = CGImageGetDataProvider(image); |
@@ -724,50 +730,51 @@ bool ScreenCapturerMac::CgBlitPostLion(const DesktopFrame& frame, |
const uint8_t* display_base_address = CFDataGetBytePtr(data); |
int src_bytes_per_row = CGImageGetBytesPerRow(image); |
- int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; |
- // Calculate where in the output buffer the display's origin is. |
- uint8_t* out_ptr = frame.data() + |
- (display_bounds.left() * src_bytes_per_pixel) + |
- (display_bounds.top() * frame.stride()); |
+ // |image| size may be different from display_bounds in case the screen was |
+ // resized recently. |
+ copy_region.IntersectWith( |
+ DesktopRect::MakeWH(CGImageGetWidth(image), CGImageGetHeight(image))); |
// Copy the dirty region from the display buffer into our desktop buffer. |
+ uint8_t* out_ptr = frame.GetFrameDataAtPos(display_bounds.top_left()); |
for (DesktopRegion::Iterator i(copy_region); !i.IsAtEnd(); i.Advance()) { |
- CopyRect(display_base_address, |
- src_bytes_per_row, |
- out_ptr, |
- frame.stride(), |
- src_bytes_per_pixel, |
- i.rect()); |
+ CopyRect(display_base_address, src_bytes_per_row, out_ptr, frame.stride(), |
+ DesktopFrame::kBytesPerPixel, i.rect()); |
} |
- // Copy the region of the excluded window to the frame. |
+ CFRelease(data); |
+ CFRelease(image); |
+ |
if (excluded_image) { |
- assert(excluded_window_region_data); |
- display_base_address = CFDataGetBytePtr(excluded_window_region_data); |
+ CGDataProviderRef provider = CGImageGetDataProvider(excluded_image); |
+ CFDataRef excluded_image_data = CGDataProviderCopyData(provider); |
+ assert(excluded_image_data); |
+ display_base_address = CFDataGetBytePtr(excluded_image_data); |
src_bytes_per_row = CGImageGetBytesPerRow(excluded_image); |
// Translate the bounds relative to the desktop, because |frame| data |
// starts from the desktop top-left corner. |
DesktopRect window_bounds_relative_to_desktop(excluded_window_bounds); |
- window_bounds_relative_to_desktop.Translate( |
- -screen_pixel_bounds_.left(), -screen_pixel_bounds_.top()); |
- out_ptr = frame.data() + |
- (window_bounds_relative_to_desktop.left() * src_bytes_per_pixel) + |
- (window_bounds_relative_to_desktop.top() * frame.stride()); |
+ window_bounds_relative_to_desktop.Translate(-screen_pixel_bounds_.left(), |
+ -screen_pixel_bounds_.top()); |
+ |
+ DesktopRect rect_to_copy = |
+ DesktopRect::MakeSize(excluded_window_bounds.size()); |
+ rect_to_copy.IntersectWith(DesktopRect::MakeWH( |
+ CGImageGetWidth(excluded_image), CGImageGetHeight(excluded_image))); |
+ |
+ if (CGImageGetBitsPerPixel(excluded_image) / 8 == |
+ DesktopFrame::kBytesPerPixel) { |
+ CopyRect(display_base_address, src_bytes_per_row, |
+ frame.GetFrameDataAtPos( |
+ window_bounds_relative_to_desktop.top_left()), |
+ frame.stride(), DesktopFrame::kBytesPerPixel, rect_to_copy); |
+ } |
- CopyRect(display_base_address, |
- src_bytes_per_row, |
- out_ptr, |
- frame.stride(), |
- src_bytes_per_pixel, |
- DesktopRect::MakeSize(excluded_window_bounds.size())); |
- CFRelease(excluded_window_region_data); |
+ CFRelease(excluded_image_data); |
CFRelease(excluded_image); |
} |
- |
- CFRelease(data); |
- CFRelease(image); |
} |
if (window_list) |
CFRelease(window_list); |