Avoid a frame copy in WindowCapturerMac
By wraping the cg_data instead of copying it. We had the infrastructure
for it since the work around iosurface, we were just not using it.
Also having a centralized DesktopFrameCGImage::CreateFromCGImage helper
will be useful to parse the ICC Profile at only one place.
Bug: chromium:945468
Change-Id: I69f179064fd9045d992a7baea35820c38e24dacc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133640
Commit-Queue: Julien Isorce <julien.isorce@chromium.org>
Reviewed-by: Jamie Walch <jamiewalch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#27696}
diff --git a/modules/desktop_capture/mac/desktop_frame_cgimage.h b/modules/desktop_capture/mac/desktop_frame_cgimage.h
index bf8be1b..8e00666 100644
--- a/modules/desktop_capture/mac/desktop_frame_cgimage.h
+++ b/modules/desktop_capture/mac/desktop_frame_cgimage.h
@@ -27,9 +27,18 @@
static std::unique_ptr<DesktopFrameCGImage> CreateForDisplay(
CGDirectDisplayID display_id);
+ // Create an image containing a snaphot of the given window at the time this
+ // is being called. This also works when the window is overlapped or in
+ // another workspace.
+ static std::unique_ptr<DesktopFrameCGImage> CreateForWindow(
+ CGWindowID window_id);
+
~DesktopFrameCGImage() override;
private:
+ static std::unique_ptr<DesktopFrameCGImage> CreateFromCGImage(
+ rtc::ScopedCFTypeRef<CGImageRef> cg_image);
+
// This constructor expects |cg_image| to hold a non-null CGImageRef.
DesktopFrameCGImage(DesktopSize size,
int stride,
diff --git a/modules/desktop_capture/mac/desktop_frame_cgimage.mm b/modules/desktop_capture/mac/desktop_frame_cgimage.mm
index 23afaaa..784b04f 100644
--- a/modules/desktop_capture/mac/desktop_frame_cgimage.mm
+++ b/modules/desktop_capture/mac/desktop_frame_cgimage.mm
@@ -24,6 +24,26 @@
return nullptr;
}
+ return DesktopFrameCGImage::CreateFromCGImage(cg_image);
+}
+
+// static
+std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateForWindow(CGWindowID window_id) {
+ rtc::ScopedCFTypeRef<CGImageRef> cg_image(
+ CGWindowListCreateImage(CGRectNull,
+ kCGWindowListOptionIncludingWindow,
+ window_id,
+ kCGWindowImageBoundsIgnoreFraming));
+ if (!cg_image) {
+ return nullptr;
+ }
+
+ return DesktopFrameCGImage::CreateFromCGImage(cg_image);
+}
+
+// static
+std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateFromCGImage(
+ rtc::ScopedCFTypeRef<CGImageRef> cg_image) {
// Verify that the image has 32-bit depth.
int bits_per_pixel = CGImageGetBitsPerPixel(cg_image.get());
if (bits_per_pixel / 8 != DesktopFrame::kBytesPerPixel) {
diff --git a/modules/desktop_capture/window_capturer_mac.mm b/modules/desktop_capture/window_capturer_mac.mm
index 979b3b8..fae3f98 100644
--- a/modules/desktop_capture/window_capturer_mac.mm
+++ b/modules/desktop_capture/window_capturer_mac.mm
@@ -21,6 +21,7 @@
#include "modules/desktop_capture/desktop_frame.h"
#include "modules/desktop_capture/mac/desktop_configuration.h"
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
+#include "modules/desktop_capture/mac/desktop_frame_cgimage.h"
#include "modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
#include "modules/desktop_capture/mac/window_list_utils.h"
#include "modules/desktop_capture/window_finder_mac.h"
@@ -171,41 +172,13 @@
on_screen_window = full_screen_window;
}
- CGImageRef window_image = CGWindowListCreateImage(
- CGRectNull, kCGWindowListOptionIncludingWindow,
- on_screen_window, kCGWindowImageBoundsIgnoreFraming);
-
- if (!window_image) {
+ std::unique_ptr<DesktopFrame> frame = DesktopFrameCGImage::CreateForWindow(on_screen_window);
+ if (!frame) {
RTC_LOG(LS_WARNING) << "Temporarily failed to capture window.";
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
return;
}
- int bits_per_pixel = CGImageGetBitsPerPixel(window_image);
- if (bits_per_pixel != 32) {
- RTC_LOG(LS_ERROR) << "Unsupported window image depth: " << bits_per_pixel;
- CFRelease(window_image);
- callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
- return;
- }
-
- int width = CGImageGetWidth(window_image);
- int height = CGImageGetHeight(window_image);
- CGDataProviderRef provider = CGImageGetDataProvider(window_image);
- CFDataRef cf_data = CGDataProviderCopyData(provider);
- std::unique_ptr<DesktopFrame> frame(
- new BasicDesktopFrame(DesktopSize(width, height)));
-
- int src_stride = CGImageGetBytesPerRow(window_image);
- const uint8_t* src_data = CFDataGetBytePtr(cf_data);
- for (int y = 0; y < height; ++y) {
- memcpy(frame->data() + frame->stride() * y, src_data + src_stride * y,
- DesktopFrame::kBytesPerPixel * width);
- }
-
- CFRelease(cf_data);
- CFRelease(window_image);
-
frame->mutable_updated_region()->SetRect(
DesktopRect::MakeSize(frame->size()));
frame->set_top_left(GetWindowBounds(on_screen_window).top_left());