Source code

Revision control

Copy as Markdown

Other Tools

From: Michael Froman <mfroman@mozilla.com>
Date: Tue, 13 May 2025 22:39:00 +0000
Subject: Bug 1966238 - Cherry-pick upstream libwebrtc commit 21da644966
r?pehrsons!
Allow piping cropping info through DesktopFrameIOSurface
Bug: webrtc:367915807
Change-Id: I13bc7c9b1ca5a8ef8147b7b754ef273061d3988f
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Johannes Kron <kron@webrtc.org>
Commit-Queue: Andreas Pehrson <apehrson@mozilla.com>
Cr-Commit-Position: refs/heads/main@{#44352}
---
modules/desktop_capture/BUILD.gn | 1 +
.../mac/desktop_frame_iosurface.h | 17 ++++--
.../mac/desktop_frame_iosurface.mm | 53 +++++++++++++++----
3 files changed, 57 insertions(+), 14 deletions(-)
diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn
index 843a87950b..d6fd6e7e61 100644
--- a/modules/desktop_capture/BUILD.gn
+++ b/modules/desktop_capture/BUILD.gn
@@ -633,6 +633,7 @@ if (is_mac) {
"../../rtc_base:event_tracer",
"../../rtc_base:logging",
"../../rtc_base:macromagic",
+ "../../rtc_base:safe_conversions",
"../../rtc_base:timeutils",
"../../rtc_base/synchronization:mutex",
"../../rtc_base/system:rtc_export",
diff --git a/modules/desktop_capture/mac/desktop_frame_iosurface.h b/modules/desktop_capture/mac/desktop_frame_iosurface.h
index 73da0f693c..a696b35645 100644
--- a/modules/desktop_capture/mac/desktop_frame_iosurface.h
+++ b/modules/desktop_capture/mac/desktop_frame_iosurface.h
@@ -24,9 +24,10 @@ namespace webrtc {
class DesktopFrameIOSurface final : public DesktopFrame {
public:
// Lock an IOSurfaceRef containing a snapshot of a display. Return NULL if
- // failed to lock.
+ // failed to lock. `rect` specifies the portion of the surface that the
+ // DesktopFrame should be cropped to.
static std::unique_ptr<DesktopFrameIOSurface> Wrap(
- rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface);
+ rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface, CGRect rect = {});
~DesktopFrameIOSurface() override;
@@ -34,8 +35,16 @@ class DesktopFrameIOSurface final : public DesktopFrame {
DesktopFrameIOSurface& operator=(const DesktopFrameIOSurface&) = delete;
private:
- // This constructor expects `io_surface` to hold a non-null IOSurfaceRef.
- explicit DesktopFrameIOSurface(rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface);
+ // `io_surface` must hold a non-null IOSurfaceRef that is already locked.
+ // `data` is the address of the first byte of data in `io_surface`'s locked
+ // buffer.
+ // `width` and `height` make up the dimensions of `io_surface` in pixels.
+ // `stride` is the number of bytes of a single row of pixels in `data`.
+ DesktopFrameIOSurface(rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface,
+ uint8_t* data,
+ int32_t width,
+ int32_t height,
+ int32_t stride);
const rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
};
diff --git a/modules/desktop_capture/mac/desktop_frame_iosurface.mm b/modules/desktop_capture/mac/desktop_frame_iosurface.mm
index 11f2e9eaa2..0fa8e30ba2 100644
--- a/modules/desktop_capture/mac/desktop_frame_iosurface.mm
+++ b/modules/desktop_capture/mac/desktop_frame_iosurface.mm
@@ -12,12 +12,13 @@
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
namespace webrtc {
// static
std::unique_ptr<DesktopFrameIOSurface> DesktopFrameIOSurface::Wrap(
- rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface) {
+ rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface, CGRect rect) {
if (!io_surface) {
return nullptr;
}
@@ -42,18 +43,50 @@ std::unique_ptr<DesktopFrameIOSurface> DesktopFrameIOSurface::Wrap(
return nullptr;
}
- return std::unique_ptr<DesktopFrameIOSurface>(
- new DesktopFrameIOSurface(io_surface));
+ const size_t surface_width = IOSurfaceGetWidth(io_surface.get());
+ const size_t surface_height = IOSurfaceGetHeight(io_surface.get());
+ const int32_t stride =
+ checked_cast<int32_t>(IOSurfaceGetBytesPerRow(io_surface.get()));
+ uint8_t* const data =
+ static_cast<uint8_t*>(IOSurfaceGetBaseAddress(io_surface.get()));
+ int32_t width = checked_cast<int32_t>(surface_width);
+ int32_t height = checked_cast<int32_t>(surface_height);
+ ptrdiff_t offset = 0;
+ ptrdiff_t offset_columns = 0;
+ ptrdiff_t offset_rows = 0;
+ if (rect.size.width > 0 && rect.size.height > 0) {
+ width = checked_cast<int32_t>(std::floor(rect.size.width));
+ height = checked_cast<int32_t>(std::floor(rect.size.height));
+ offset_columns = checked_cast<ptrdiff_t>(std::ceil(rect.origin.x));
+ offset_rows = checked_cast<ptrdiff_t>(std::ceil(rect.origin.y));
+ offset = stride * offset_rows + bytes_per_pixel * offset_columns;
+ }
+
+ RTC_LOG(LS_VERBOSE) << "DesktopFrameIOSurface wrapping IOSurface with size "
+ << surface_width << "x" << surface_height
+ << ". Cropping to (" << offset_columns << ","
+ << offset_rows << "; " << width << "x" << height
+ << "). Stride=" << stride / bytes_per_pixel
+ << ", buffer-offset-px=" << offset / bytes_per_pixel
+ << ", buffer-offset-bytes=" << offset;
+
+ RTC_CHECK_GE(surface_width, offset_columns + width);
+ RTC_CHECK_GE(surface_height, offset_rows + height);
+ RTC_CHECK_GE(offset, 0);
+ RTC_CHECK_LE(offset + ((height - 1) * stride) + (width * bytes_per_pixel) - 1,
+ IOSurfaceGetAllocSize(io_surface.get()));
+
+ return std::unique_ptr<DesktopFrameIOSurface>(new DesktopFrameIOSurface(
+ io_surface, data + offset, width, height, stride));
}
DesktopFrameIOSurface::DesktopFrameIOSurface(
- rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface)
- : DesktopFrame(
- DesktopSize(IOSurfaceGetWidth(io_surface.get()),
- IOSurfaceGetHeight(io_surface.get())),
- IOSurfaceGetBytesPerRow(io_surface.get()),
- static_cast<uint8_t*>(IOSurfaceGetBaseAddress(io_surface.get())),
- nullptr),
+ rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface,
+ uint8_t* data,
+ int32_t width,
+ int32_t height,
+ int32_t stride)
+ : DesktopFrame(DesktopSize(width, height), stride, data, nullptr),
io_surface_(io_surface) {
RTC_DCHECK(io_surface_);
}