Wayland: Allow setting custom resolution

This CL allows the users to propose custom resolution to server
for the captured pipewire streams.

Bug: chromium:1291247
Change-Id: Iaae2c73df1a5f5ebac651ce7d087af4c273113c4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/263360
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Commit-Queue: Salman Malik <salmanmalik@google.com>
Cr-Commit-Position: refs/heads/main@{#36979}
diff --git a/modules/desktop_capture/desktop_capture_options.h b/modules/desktop_capture/desktop_capture_options.h
index dd3cde0..4ee5259 100644
--- a/modules/desktop_capture/desktop_capture_options.h
+++ b/modules/desktop_capture/desktop_capture_options.h
@@ -188,6 +188,12 @@
       rtc::scoped_refptr<SharedScreenCastStream> stream) {
     screencast_stream_ = stream;
   }
+
+  void set_width(uint32_t width) { width_ = width; }
+  uint32_t get_width() const { return width_; }
+
+  void set_height(uint32_t height) { height_ = height; }
+  uint32_t get_height() const { return height_; }
 #endif
 
  private:
@@ -226,6 +232,8 @@
   bool detect_updated_region_ = false;
 #if defined(WEBRTC_USE_PIPEWIRE)
   bool allow_pipewire_ = false;
+  uint32_t width_ = 0;
+  uint32_t height_ = 0;
 #endif
 };
 
diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
index 0fc90e0..678f350 100644
--- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
+++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
@@ -44,8 +44,8 @@
                                                      uint32_t stream_node_id,
                                                      int fd) {
   if (result != RequestResponse::kSuccess ||
-      !options_.screencast_stream()->StartScreenCastStream(stream_node_id,
-                                                           fd)) {
+      !options_.screencast_stream()->StartScreenCastStream(
+          stream_node_id, fd, options_.get_width(), options_.get_height())) {
     capturer_failed_ = true;
     RTC_LOG(LS_ERROR) << "ScreenCastPortal failed: "
                       << static_cast<uint>(result);
diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
index 644569f..deb85a8 100644
--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
+++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
@@ -85,7 +85,10 @@
   SharedScreenCastStreamPrivate();
   ~SharedScreenCastStreamPrivate();
 
-  bool StartScreenCastStream(uint32_t stream_node_id, int fd);
+  bool StartScreenCastStream(uint32_t stream_node_id,
+                             int fd,
+                             uint32_t width = 0,
+                             uint32_t height = 0);
   void StopScreenCastStream();
   std::unique_ptr<DesktopFrame> CaptureFrame();
   std::unique_ptr<MouseCursor> CaptureCursor();
@@ -368,7 +371,9 @@
 RTC_NO_SANITIZE("cfi-icall")
 bool SharedScreenCastStreamPrivate::StartScreenCastStream(
     uint32_t stream_node_id,
-    int fd) {
+    int fd,
+    uint32_t width,
+    uint32_t height) {
 #if defined(WEBRTC_DLOPEN_PIPEWIRE)
   StubPathMap paths;
 
@@ -463,6 +468,12 @@
         pw_client_version_ >= kDmaBufModifierMinVersion;
     const bool has_required_pw_server_version =
         pw_server_version_ >= kDmaBufModifierMinVersion;
+    struct spa_rectangle resolution;
+    bool set_resolution = false;
+    if (width && height) {
+      resolution = SPA_RECTANGLE(width, height);
+      set_resolution = true;
+    }
     for (uint32_t format : {SPA_VIDEO_FORMAT_BGRA, SPA_VIDEO_FORMAT_RGBA,
                             SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx}) {
       // Modifiers can be used with PipeWire >= 0.3.33
@@ -471,12 +482,12 @@
 
         if (!modifiers_.empty()) {
           params.push_back(BuildFormat(&builder, format, modifiers_,
-                                       /*resolution=*/nullptr));
+                                       set_resolution ? &resolution : nullptr));
         }
       }
 
       params.push_back(BuildFormat(&builder, format, /*modifiers=*/{},
-                                   /*resolution=*/nullptr));
+                                   set_resolution ? &resolution : nullptr));
     }
 
     if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, pw_stream_node_id_,
@@ -734,8 +745,10 @@
 }
 
 bool SharedScreenCastStream::StartScreenCastStream(uint32_t stream_node_id,
-                                                   int fd) {
-  return private_->StartScreenCastStream(stream_node_id, fd);
+                                                   int fd,
+                                                   uint32_t width,
+                                                   uint32_t height) {
+  return private_->StartScreenCastStream(stream_node_id, fd, width, height);
 }
 
 void SharedScreenCastStream::StopScreenCastStream() {
diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.h b/modules/desktop_capture/linux/wayland/shared_screencast_stream.h
index 1e9fbe5..e8b79cb 100644
--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.h
+++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.h
@@ -30,7 +30,10 @@
   static rtc::scoped_refptr<SharedScreenCastStream> CreateDefault();
 
   bool StartScreenCastStream(uint32_t stream_node_id);
-  bool StartScreenCastStream(uint32_t stream_node_id, int fd);
+  bool StartScreenCastStream(uint32_t stream_node_id,
+                             int fd,
+                             uint32_t width = 0,
+                             uint32_t height = 0);
   void StopScreenCastStream();
 
   // Below functions return the most recent information we get from a