Bug 1966238 - Cherry-pick upstream libwebrtc commit 83bd277b28 r=pehrsons,webrtc-reviewers

Upstream commit: https://webrtc.googlesource.com/src/+/83bd277b28d70213cc0c8b4a9c42cc8c46417711
       To ScreenCapturerSck add more elaborate logging

       This commit adds the capturer's `this` pointer address as an identifier
       to existing logging statements, and adds several others.

       Bug: webrtc:367915807
       Change-Id: I6daa404cd2ed20f0d50fd66eb6e066779c18df7a
       Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/365086
       Commit-Queue: Andreas Pehrson <apehrson@mozilla.com>
       Reviewed-by: Alexander Cooper <alcooper@chromium.org>
       Cr-Commit-Position: refs/heads/main@{#44209}

Differential Revision: https://phabricator.services.mozilla.com/D249155
This commit is contained in:
Michael Froman
2025-05-16 17:25:50 +00:00
committed by mfroman@mozilla.com
parent 5e5a1edeb9
commit 5fa01a1373
2 changed files with 52 additions and 17 deletions

View File

@@ -37,7 +37,8 @@ API_AVAILABLE(macos(14.0))
- (instancetype)initWithCapturer:(webrtc::ScreenCapturerSck*)capturer; - (instancetype)initWithCapturer:(webrtc::ScreenCapturerSck*)capturer;
- (void)onShareableContentCreated:(SCShareableContent*)content; - (void)onShareableContentCreated:(SCShareableContent*)content
error:(NSError*)error;
// Called just before the capturer is destroyed. This avoids a dangling pointer, // Called just before the capturer is destroyed. This avoids a dangling pointer,
// and prevents any new calls into a deleted capturer. If any method-call on the // and prevents any new calls into a deleted capturer. If any method-call on the
@@ -67,7 +68,7 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSck final
// Called by SckHelper when shareable content is returned by ScreenCaptureKit. // Called by SckHelper when shareable content is returned by ScreenCaptureKit.
// `content` will be nil if an error occurred. May run on an arbitrary thread. // `content` will be nil if an error occurred. May run on an arbitrary thread.
void OnShareableContentCreated(SCShareableContent* content); void OnShareableContentCreated(SCShareableContent* content, NSError* error);
// Called by SckHelper to notify of a newly captured frame. May run on an // Called by SckHelper to notify of a newly captured frame. May run on an
// arbitrary thread. // arbitrary thread.
@@ -132,15 +133,18 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSck final
ScreenCapturerSck::ScreenCapturerSck(const DesktopCaptureOptions& options) ScreenCapturerSck::ScreenCapturerSck(const DesktopCaptureOptions& options)
: capture_options_(options) { : capture_options_(options) {
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " created";
helper_ = [[SckHelper alloc] initWithCapturer:this]; helper_ = [[SckHelper alloc] initWithCapturer:this];
} }
ScreenCapturerSck::~ScreenCapturerSck() { ScreenCapturerSck::~ScreenCapturerSck() {
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " destroyed.";
[stream_ stopCaptureWithCompletionHandler:nil]; [stream_ stopCaptureWithCompletionHandler:nil];
[helper_ releaseCapturer]; [helper_ releaseCapturer];
} }
void ScreenCapturerSck::Start(DesktopCapturer::Callback* callback) { void ScreenCapturerSck::Start(DesktopCapturer::Callback* callback) {
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " " << __func__ << ".";
callback_ = callback; callback_ = callback;
desktop_config_ = desktop_config_ =
capture_options_.configuration_monitor()->desktop_configuration(); capture_options_.configuration_monitor()->desktop_configuration();
@@ -155,6 +159,8 @@ void ScreenCapturerSck::CaptureFrame() {
int64_t capture_start_time_millis = rtc::TimeMillis(); int64_t capture_start_time_millis = rtc::TimeMillis();
if (permanent_error_) { if (permanent_error_) {
RTC_LOG(LS_VERBOSE) << "ScreenCapturerSck " << this
<< " CaptureFrame() -> ERROR_PERMANENT";
callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
return; return;
} }
@@ -180,14 +186,20 @@ void ScreenCapturerSck::CaptureFrame() {
} }
if (frame) { if (frame) {
RTC_LOG(LS_VERBOSE) << "ScreenCapturerSck " << this
<< " CaptureFrame() -> SUCCESS";
frame->set_capture_time_ms(rtc::TimeSince(capture_start_time_millis)); frame->set_capture_time_ms(rtc::TimeSince(capture_start_time_millis));
callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} else { } else {
RTC_LOG(LS_VERBOSE) << "ScreenCapturerSck " << this
<< " CaptureFrame() -> ERROR_TEMPORARY";
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
} }
} }
bool ScreenCapturerSck::SelectSource(SourceId id) { bool ScreenCapturerSck::SelectSource(SourceId id) {
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " SelectSource(id=" << id
<< ").";
bool stream_started = false; bool stream_started = false;
{ {
MutexLock lock(&lock_); MutexLock lock(&lock_);
@@ -207,20 +219,26 @@ bool ScreenCapturerSck::SelectSource(SourceId id) {
return true; return true;
} }
void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) { void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content,
NSError* error) {
if (!content) { if (!content) {
RTC_LOG(LS_ERROR) << "getShareableContent failed."; RTC_LOG(LS_ERROR) << "ScreenCapturerSck " << this
<< " getShareableContent failed with error code "
<< (error ? error.code : 0) << ".";
permanent_error_ = true; permanent_error_ = true;
return; return;
} }
if (!content.displays.count) { if (!content.displays.count) {
RTC_LOG(LS_ERROR) << "getShareableContent returned no displays."; RTC_LOG(LS_ERROR) << "ScreenCapturerSck " << this
<< " getShareableContent returned no displays.";
permanent_error_ = true; permanent_error_ = true;
return; return;
} }
MutexLock lock(&lock_); MutexLock lock(&lock_);
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " " << __func__
<< ". current_display_=" << current_display_;
SCDisplay* captured_display; SCDisplay* captured_display;
for (SCDisplay* display in content.displays) { for (SCDisplay* display in content.displays) {
if (current_display_ == display.displayID) { if (current_display_ == display.displayID) {
@@ -231,11 +249,15 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
if (!captured_display) { if (!captured_display) {
if (current_display_ == if (current_display_ ==
static_cast<CGDirectDisplayID>(kFullDesktopScreenId)) { static_cast<CGDirectDisplayID>(kFullDesktopScreenId)) {
RTC_LOG(LS_WARNING) << "Full screen capture is not supported, falling " RTC_LOG(LS_WARNING) << "ScreenCapturerSck " << this
"back to first display."; << " Full screen "
"capture is not supported, falling back to first "
"display.";
} else { } else {
RTC_LOG(LS_WARNING) << "Display " << current_display_ RTC_LOG(LS_WARNING) << "ScreenCapturerSck " << this << " Display "
<< " not found, falling back to first display."; << current_display_
<< " not found, falling back to "
"first display.";
} }
captured_display = content.displays.firstObject; captured_display = content.displays.firstObject;
} }
@@ -257,10 +279,13 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
} }
if (stream_) { if (stream_) {
RTC_LOG(LS_INFO) << "Updating stream configuration."; RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this
<< " Updating stream configuration to size="
<< config.width << "x" << config.height << ".";
[stream_ updateContentFilter:filter completionHandler:nil]; [stream_ updateContentFilter:filter completionHandler:nil];
[stream_ updateConfiguration:config completionHandler:nil]; [stream_ updateConfiguration:config completionHandler:nil];
} else { } else {
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " Creating new stream.";
stream_ = [[SCStream alloc] initWithFilter:filter stream_ = [[SCStream alloc] initWithFilter:filter
configuration:config configuration:config
delegate:helper_]; delegate:helper_];
@@ -275,7 +300,8 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
error:&add_stream_output_error]; error:&add_stream_output_error];
if (!add_stream_output_result) { if (!add_stream_output_result) {
stream_ = nil; stream_ = nil;
RTC_LOG(LS_ERROR) << "addStreamOutput failed."; RTC_LOG(LS_ERROR) << "ScreenCapturerSck " << this
<< " addStreamOutput failed.";
permanent_error_ = true; permanent_error_ = true;
return; return;
} }
@@ -286,9 +312,10 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
// calls stopCaptureWithCompletionHandler on the stream, which cancels // calls stopCaptureWithCompletionHandler on the stream, which cancels
// this handler. // this handler.
permanent_error_ = true; permanent_error_ = true;
RTC_LOG(LS_ERROR) << "startCaptureWithCompletionHandler failed."; RTC_LOG(LS_ERROR) << "ScreenCapturerSck " << this
<< " Starting failed.";
} else { } else {
RTC_LOG(LS_INFO) << "Capture started."; RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " Capture started.";
} }
}; };
@@ -298,6 +325,9 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface, void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface,
CFDictionaryRef attachment) { CFDictionaryRef attachment) {
RTC_LOG(LS_VERBOSE) << "ScreenCapturerSck " << this << " " << __func__
<< " width=" << IOSurfaceGetWidth(io_surface)
<< ", height=" << IOSurfaceGetHeight(io_surface) << ".";
rtc::ScopedCFTypeRef<IOSurfaceRef> scoped_io_surface( rtc::ScopedCFTypeRef<IOSurfaceRef> scoped_io_surface(
io_surface, rtc::RetainPolicy::RETAIN); io_surface, rtc::RetainPolicy::RETAIN);
std::unique_ptr<DesktopFrameIOSurface> desktop_frame_io_surface = std::unique_ptr<DesktopFrameIOSurface> desktop_frame_io_surface =
@@ -362,12 +392,13 @@ void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface,
} }
void ScreenCapturerSck::StartOrReconfigureCapturer() { void ScreenCapturerSck::StartOrReconfigureCapturer() {
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << this << " " << __func__ << ".";
// The copy is needed to avoid capturing `this` in the Objective-C block. // The copy is needed to avoid capturing `this` in the Objective-C block.
// Accessing `helper_` inside the block is equivalent to `this->helper_` and // Accessing `helper_` inside the block is equivalent to `this->helper_` and
// would crash (UAF) if `this` is deleted before the block is executed. // would crash (UAF) if `this` is deleted before the block is executed.
SckHelper* local_helper = helper_; SckHelper* local_helper = helper_;
auto handler = ^(SCShareableContent* content, NSError* /* error */) { auto handler = ^(SCShareableContent* content, NSError* error) {
[local_helper onShareableContentCreated:content]; [local_helper onShareableContentCreated:content error:error];
}; };
[SCShareableContent getShareableContentWithCompletionHandler:handler]; [SCShareableContent getShareableContentWithCompletionHandler:handler];
@@ -408,10 +439,11 @@ std::unique_ptr<DesktopCapturer> CreateScreenCapturerSck(
return self; return self;
} }
- (void)onShareableContentCreated:(SCShareableContent*)content { - (void)onShareableContentCreated:(SCShareableContent*)content
error:(NSError*)error {
webrtc::MutexLock lock(&_capturer_lock); webrtc::MutexLock lock(&_capturer_lock);
if (_capturer) { if (_capturer) {
_capturer->OnShareableContentCreated(content); _capturer->OnShareableContentCreated(content, error);
} }
} }
@@ -446,6 +478,8 @@ std::unique_ptr<DesktopCapturer> CreateScreenCapturerSck(
- (void)releaseCapturer { - (void)releaseCapturer {
webrtc::MutexLock lock(&_capturer_lock); webrtc::MutexLock lock(&_capturer_lock);
RTC_LOG(LS_INFO) << "ScreenCapturerSck " << _capturer << " " << __func__
<< ".";
_capturer = nullptr; _capturer = nullptr;
} }

View File

@@ -0,0 +1 @@
We cherry-picked this in bug 1966238