Add DesktopFrameCGImage

No functional change. This makes the code more generic
and this reduces the size of screen_capturer_mac.mm

Bug: webrtc:8652
Change-Id: I37743ba385fea5e1b40df3b094bfc321b8d796ae
Reviewed-on: https://webrtc-review.googlesource.com/65082
Commit-Queue: Julien Isorce <julien.isorce@chromium.org>
Commit-Queue: Zijie He <zijiehe@chromium.org>
Reviewed-by: Zijie He <zijiehe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#22684}
This commit is contained in:
Julien Isorce 2018-03-29 22:35:44 +01:00 committed by Commit Bot
parent 9d6f73bfb2
commit c0719cedac
5 changed files with 129 additions and 21 deletions

View file

@ -175,6 +175,8 @@ if (is_mac) {
visibility = [ ":desktop_capture" ]
sources = [
"mac/desktop_configuration.mm",
"mac/desktop_frame_cgimage.h",
"mac/desktop_frame_cgimage.mm",
"mac/screen_capturer_mac.h",
"mac/screen_capturer_mac.mm",
"mouse_cursor_monitor_mac.mm",

View file

@ -4,6 +4,9 @@ include_rules = [
]
specific_include_rules = {
"desktop_frame_cgimage\.h": [
"+sdk/objc",
],
"screen_capturer_mac\.mm": [
"+sdk/objc",
],

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_DESKTOP_CAPTURE_MAC_DESKTOP_FRAME_CGIMAGE_H_
#define MODULES_DESKTOP_CAPTURE_MAC_DESKTOP_FRAME_CGIMAGE_H_
#include <CoreGraphics/CoreGraphics.h>
#include <memory>
#include "modules/desktop_capture/desktop_frame.h"
#include "sdk/objc/Framework/Classes/Common/scoped_cftyperef.h"
namespace webrtc {
class DesktopFrameCGImage final : public DesktopFrame {
public:
// Create an image containing a snapshot of the display at the time this is
// being called.
static std::unique_ptr<DesktopFrameCGImage> CreateForDisplay(
CGDirectDisplayID display_id);
~DesktopFrameCGImage() override;
private:
// This constructor expects |cg_image| to hold a non-null CGImageRef.
DesktopFrameCGImage(DesktopSize size,
int stride,
uint8_t* data,
rtc::ScopedCFTypeRef<CGImageRef> cg_image,
rtc::ScopedCFTypeRef<CFDataRef> cg_data);
const rtc::ScopedCFTypeRef<CGImageRef> cg_image_;
const rtc::ScopedCFTypeRef<CFDataRef> cg_data_;
RTC_DISALLOW_COPY_AND_ASSIGN(DesktopFrameCGImage);
};
} // namespace webrtc
#endif // MODULES_DESKTOP_CAPTURE_MAC_DESKTOP_FRAME_CGIMAGE_H_

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/desktop_capture/mac/desktop_frame_cgimage.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
namespace webrtc {
// static
std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateForDisplay(
CGDirectDisplayID display_id) {
// Create an image containing a snapshot of the display.
rtc::ScopedCFTypeRef<CGImageRef> cg_image(CGDisplayCreateImage(display_id));
if (!cg_image) {
return nullptr;
}
// Verify that the image has 32-bit depth.
int bits_per_pixel = CGImageGetBitsPerPixel(cg_image.get());
if (bits_per_pixel / 8 != DesktopFrame::kBytesPerPixel) {
RTC_LOG(LS_ERROR) << "CGDisplayCreateImage() returned imaged with " << bits_per_pixel
<< " bits per pixel. Only 32-bit depth is supported.";
return nullptr;
}
// Request access to the raw pixel data via the image's DataProvider.
CGDataProviderRef cg_provider = CGImageGetDataProvider(cg_image.get());
RTC_DCHECK(cg_provider);
// CGDataProviderCopyData returns a new data object containing a copy of the providers
// data.
rtc::ScopedCFTypeRef<CFDataRef> cg_data(CGDataProviderCopyData(cg_provider));
RTC_DCHECK(cg_data);
// CFDataGetBytePtr returns a read-only pointer to the bytes of a CFData object.
uint8_t* data = const_cast<uint8_t*>(CFDataGetBytePtr(cg_data.get()));
RTC_DCHECK(data);
DesktopSize size(CGImageGetWidth(cg_image.get()), CGImageGetHeight(cg_image.get()));
int stride = CGImageGetBytesPerRow(cg_image.get());
return std::unique_ptr<DesktopFrameCGImage>(
new DesktopFrameCGImage(size, stride, data, cg_image, cg_data));
}
DesktopFrameCGImage::DesktopFrameCGImage(DesktopSize size,
int stride,
uint8_t* data,
rtc::ScopedCFTypeRef<CGImageRef> cg_image,
rtc::ScopedCFTypeRef<CFDataRef> cg_data)
: DesktopFrame(size, stride, data, nullptr), cg_image_(cg_image), cg_data_(cg_data) {
RTC_DCHECK(cg_image_);
RTC_DCHECK(cg_data_);
}
DesktopFrameCGImage::~DesktopFrameCGImage() = default;
} // namespace webrtc

View file

@ -12,6 +12,7 @@
#include "modules/desktop_capture/mac/screen_capturer_mac.h"
#include "modules/desktop_capture/mac/desktop_frame_cgimage.h"
#include "rtc_base/checks.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/logging.h"
@ -405,32 +406,19 @@ bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame, const DesktopRegion& r
}
}
// Create an image containing a snapshot of the display.
rtc::ScopedCFTypeRef<CGImageRef> image(CGDisplayCreateImage(display_config.id));
if (!image) {
std::unique_ptr<DesktopFrameCGImage> frame_source =
DesktopFrameCGImage::CreateForDisplay(display_config.id);
if (!frame_source) {
continue;
}
// Verify that the image has 32-bit depth.
int bits_per_pixel = CGImageGetBitsPerPixel(image.get());
if (bits_per_pixel / 8 != DesktopFrame::kBytesPerPixel) {
RTC_LOG(LS_ERROR) << "CGDisplayCreateImage() returned imaged with " << bits_per_pixel
<< " bits per pixel. Only 32-bit depth is supported.";
return false;
}
const uint8_t* display_base_address = frame_source->data();
int src_bytes_per_row = frame_source->stride();
RTC_DCHECK(display_base_address);
// Request access to the raw pixel data via the image's DataProvider.
CGDataProviderRef provider = CGImageGetDataProvider(image.get());
rtc::ScopedCFTypeRef<CFDataRef> data(CGDataProviderCopyData(provider));
RTC_DCHECK(data);
const uint8_t* display_base_address = CFDataGetBytePtr(data.get());
int src_bytes_per_row = CGImageGetBytesPerRow(image.get());
// |image| size may be different from display_bounds in case the screen was
// |frame_source| size may be different from display_bounds in case the screen was
// resized recently.
copy_region.IntersectWith(
DesktopRect::MakeWH(CGImageGetWidth(image.get()), CGImageGetHeight(image.get())));
copy_region.IntersectWith(frame_source->rect());
// Copy the dirty region from the display buffer into our desktop buffer.
uint8_t* out_ptr = frame.GetFrameDataAtPos(display_bounds.top_left());