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}
This commit is contained in:
parent
aec09a2d18
commit
5665572f47
@ -27,9 +27,18 @@ class DesktopFrameCGImage final : public DesktopFrame {
|
||||
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,
|
||||
|
||||
@ -24,6 +24,26 @@ std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateForDisplay(
|
||||
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) {
|
||||
|
||||
@ -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 @@ void WindowCapturerMac::CaptureFrame() {
|
||||
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());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user