From 63383506207b8a11b0bd3fb79f59312fb69b19e1 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 28 Nov 2022 09:25:08 -0800 Subject: [PATCH] chore: cherry-pick 7196a42b42ce from chromium (#36458) * chore: cherry-pick 7196a42b42ce from chromium * chore: update patches Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com> --- patches/chromium/.patches | 1 + .../chromium/cherry-pick-7196a42b42ce.patch | 251 ++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 patches/chromium/cherry-pick-7196a42b42ce.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 9ec071b6d5604..c07995b093a12 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -120,3 +120,4 @@ fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch preconnect_manager.patch fix_remove_caption-removing_style_call.patch build_allow_electron_to_use_exec_script.patch +cherry-pick-7196a42b42ce.patch diff --git a/patches/chromium/cherry-pick-7196a42b42ce.patch b/patches/chromium/cherry-pick-7196a42b42ce.patch new file mode 100644 index 0000000000000..b0bc5e06cd8c8 --- /dev/null +++ b/patches/chromium/cherry-pick-7196a42b42ce.patch @@ -0,0 +1,251 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Johannes Kron +Date: Thu, 17 Nov 2022 19:54:33 +0000 +Subject: Reconfigure stream on window resize when using ScreenCaptureKit + +Bug: chromium:1352405 +Change-Id: I315104eb4ee985a2d04ea90f01341129c6307501 +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4027202 +Reviewed-by: ccameron chromium +Reviewed-by: Robert Sesek +Commit-Queue: Johannes Kron +Cr-Commit-Position: refs/heads/main@{#1072984} + +diff --git a/content/browser/media/capture/screen_capture_kit_device_mac.mm b/content/browser/media/capture/screen_capture_kit_device_mac.mm +index c17f6f076fc852df85d5deb919434458b886db37..5d640a372f1649e0e2cb7e1828dbb3c66eb1e4d7 100644 +--- a/content/browser/media/capture/screen_capture_kit_device_mac.mm ++++ b/content/browser/media/capture/screen_capture_kit_device_mac.mm +@@ -6,15 +6,18 @@ + + #import + ++#include "base/mac/foundation_util.h" + #include "base/mac/scoped_nsobject.h" + #include "base/task/bind_post_task.h" + #include "base/threading/thread_checker.h" + #include "base/timer/timer.h" + #include "content/browser/media/capture/io_surface_capture_device_base_mac.h" ++#include "third_party/abseil-cpp/absl/types/optional.h" + #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h" + #include "ui/gfx/native_widget_types.h" + +-using SampleCallback = base::RepeatingCallback; ++using SampleCallback = base::RepeatingCallback)>; + using ErrorCallback = base::RepeatingClosure; + + API_AVAILABLE(macos(12.3)) +@@ -45,17 +48,64 @@ - (void)stream:(SCStream*)stream + CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); + if (!pixelBuffer) + return; ++ ++ // Read out width, height and scaling from metadata to determine the captured ++ // content size. ++ absl::optional contentSize; ++ CFArrayRef attachmentsArray = ++ CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false); ++ if (attachmentsArray && CFArrayGetCount(attachmentsArray) > 0) { ++ CFDictionaryRef attachment = base::mac::CFCast( ++ CFArrayGetValueAtIndex(attachmentsArray, 0)); ++ if (attachment) { ++ CFDictionaryRef contentRectValue = base::mac::CFCast( ++ CFDictionaryGetValue(attachment, SCStreamFrameInfoContentRect)); ++ CFNumberRef contentScaleValue = base::mac::CFCast( ++ CFDictionaryGetValue(attachment, SCStreamFrameInfoContentScale)); ++ if (contentRectValue && contentScaleValue) { ++ CGRect contentRect = {}; ++ bool succeed = CGRectMakeWithDictionaryRepresentation(contentRectValue, ++ &contentRect); ++ float contentScale = 1.0f; ++ succeed &= CFNumberGetValue(contentScaleValue, kCFNumberFloatType, ++ &contentScale); ++ if (succeed) { ++ contentSize.emplace(round(contentRect.size.width / contentScale), ++ round(contentRect.size.height / contentScale)); ++ } ++ } ++ } ++ } + IOSurfaceRef ioSurface = CVPixelBufferGetIOSurface(pixelBuffer); + if (!ioSurface) + return; + _sampleCallback.Run( +- gfx::ScopedInUseIOSurface(ioSurface, base::scoped_policy::RETAIN)); ++ gfx::ScopedInUseIOSurface(ioSurface, base::scoped_policy::RETAIN), ++ contentSize); + } + + - (void)stream:(SCStream*)stream didStopWithError:(NSError*)error { + _errorCallback.Run(); + } + +++ (base::scoped_nsobject) ++ createStreamConfigurationWithFrameSize:(gfx::Size)frameSize ++ destRectInFrame:(gfx::RectF)destRectInFrame ++ frameRate:(float)frameRate { ++ base::scoped_nsobject config( ++ [[SCStreamConfiguration alloc] init]); ++ [config setWidth:frameSize.width()]; ++ [config setHeight:frameSize.height()]; ++ [config setPixelFormat:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]; ++ [config setDestinationRect:destRectInFrame.ToCGRect()]; ++ [config setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)]; ++ [config setScalesToFit:YES]; ++ [config setShowsCursor:YES]; ++ [config setColorSpaceName:kCGColorSpaceSRGB]; ++ [config setMinimumFrameInterval:CMTimeMakeWithSeconds(1 / frameRate, 1)]; ++ return config; ++} ++ + @end + + namespace content { +@@ -95,7 +145,6 @@ void OnShareableContentCreated( + } + + base::scoped_nsobject filter; +- gfx::Size content_size; + switch (source_.type) { + case DesktopMediaID::TYPE_SCREEN: + for (SCDisplay* display : [content displays]) { +@@ -112,7 +161,8 @@ void OnShareableContentCreated( + filter.reset([[SCContentFilter alloc] + initWithDisplay:display + excludingWindows:exclude_windows]); +- content_size = gfx::Size([display width], [display height]); ++ stream_config_content_size_ = ++ gfx::Size([display width], [display height]); + break; + } + } +@@ -123,7 +173,7 @@ void OnShareableContentCreated( + filter.reset([[SCContentFilter alloc] + initWithDesktopIndependentWindow:window]); + CGRect frame = [window frame]; +- content_size = gfx::Size(frame.size); ++ stream_config_content_size_ = gfx::Size(frame.size); + break; + } + } +@@ -142,22 +192,16 @@ void OnShareableContentCreated( + gfx::RectF dest_rect_in_frame; + actual_capture_format_ = capture_params().requested_format; + actual_capture_format_.pixel_format = media::PIXEL_FORMAT_NV12; +- ComputeFrameSizeAndDestRect(content_size, actual_capture_format_.frame_size, ++ ComputeFrameSizeAndDestRect(stream_config_content_size_, ++ actual_capture_format_.frame_size, + dest_rect_in_frame); +- +- base::scoped_nsobject config( +- [[SCStreamConfiguration alloc] init]); +- [config setWidth:actual_capture_format_.frame_size.width()]; +- [config setHeight:actual_capture_format_.frame_size.height()]; +- [config setPixelFormat:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]; +- [config setDestinationRect:dest_rect_in_frame.ToCGRect()]; +- [config setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)]; +- [config setScalesToFit:YES]; +- [config setShowsCursor:YES]; +- [config setColorSpaceName:kCGColorSpaceSRGB]; +- [config +- setMinimumFrameInterval:CMTimeMakeWithSeconds( +- 1 / actual_capture_format_.frame_rate, 1)]; ++ base::scoped_nsobject config = ++ [ScreenCaptureKitDeviceHelper ++ createStreamConfigurationWithFrameSize:actual_capture_format_ ++ .frame_size ++ destRectInFrame:dest_rect_in_frame ++ frameRate:actual_capture_format_ ++ .frame_rate]; + stream_.reset([[SCStream alloc] initWithFilter:filter + configuration:config + delegate:helper_]); +@@ -203,9 +247,71 @@ void OnStreamStopped(bool error) { + return; + } + } +- void OnStreamSample(gfx::ScopedInUseIOSurface io_surface) { +- // TODO(https://crbug.com/1309653): Reconfigure the stream if the IOSurface +- // should be resized. ++ void OnStreamSample(gfx::ScopedInUseIOSurface io_surface, ++ absl::optional content_size) { ++ if (requested_capture_format_) { ++ // Does the size of io_surface match the requested format? ++ size_t io_surface_width = IOSurfaceGetWidth(io_surface); ++ size_t io_surface_height = IOSurfaceGetHeight(io_surface); ++ DVLOG(3) << "Waiting for new capture format, " ++ << requested_capture_format_->frame_size.width() << " x " ++ << requested_capture_format_->frame_size.height() ++ << ". IO surface size " << io_surface_width << " x " ++ << io_surface_height; ++ if (static_cast(requested_capture_format_->frame_size.width()) == ++ io_surface_width && ++ static_cast(requested_capture_format_->frame_size.height()) == ++ io_surface_height) { ++ actual_capture_format_ = requested_capture_format_.value(); ++ requested_capture_format_.reset(); ++ } ++ } else { ++ // No current request for new capture format. Check to see if content_size ++ // has changed and requires an updated configuration. ++ if (content_size && ++ (stream_config_content_size_.width() != content_size->width() || ++ stream_config_content_size_.height() != content_size->height())) { ++ DVLOG(3) << "Content size changed to " << content_size->width() << " x " ++ << content_size->height() << ". It was " ++ << stream_config_content_size_.width() << " x " ++ << stream_config_content_size_.height(); ++ stream_config_content_size_ = content_size.value(); ++ gfx::RectF dest_rect_in_frame; ++ gfx::Size new_frame_size; ++ ComputeFrameSizeAndDestRect(stream_config_content_size_, new_frame_size, ++ dest_rect_in_frame); ++ if (new_frame_size.width() != ++ actual_capture_format_.frame_size.width() || ++ new_frame_size.height() != ++ actual_capture_format_.frame_size.height()) { ++ DVLOG(3) << "Calling updateConfiguration with new frame size: " ++ << new_frame_size.width() << " x " ++ << new_frame_size.height(); ++ requested_capture_format_ = actual_capture_format_; ++ requested_capture_format_->frame_size = new_frame_size; ++ // Update stream configuration. ++ base::scoped_nsobject config = ++ [ScreenCaptureKitDeviceHelper ++ createStreamConfigurationWithFrameSize: ++ requested_capture_format_->frame_size ++ destRectInFrame:dest_rect_in_frame ++ frameRate: ++ requested_capture_format_-> ++ frame_rate]; ++ [stream_ ++ updateConfiguration:config ++ completionHandler:^(NSError* _Nullable error) { ++ if (error) { ++ client()->OnError( ++ media::VideoCaptureError::kScreenCaptureKitStreamError, ++ FROM_HERE, "Error on updateConfiguration"); ++ } ++ }]; ++ } ++ } ++ } ++ // TODO(https://crbug.com/1352405): Set visible rect to make it possible to ++ // crop the frame when it's rendered/encoded. + OnReceivedIOSurfaceFromStream(io_surface, actual_capture_format_); + } + void OnStreamError() { +@@ -257,6 +363,13 @@ void OnStop() override { + // The actual format of the video frames that are sent to `client`. + media::VideoCaptureFormat actual_capture_format_; + ++ // The requested format if a request to update the configuration has been ++ // sent. ++ absl::optional requested_capture_format_; ++ ++ // The size of the content at the time that we configured the stream. ++ gfx::Size stream_config_content_size_; ++ + // Helper class that acts as output and delegate for `stream_`. + base::scoped_nsobject helper_; +