Add SharedScreenCastStream::SetSharedMemoryFactory

Currently Chrome Remote Desktop needs to copy the BasicDesktopFrame into
a SharedMemoryDesktopFrame in order to pass it between processes. This
CL adds a new SetSharedMemoryFactory() method to SharedScreenCastStream,
which allows it to create a SharedMemoryDesktopFrame and copy the
content from the DMA buffer directly into the shared memory frame,
eliminating an unnecessary copy.

See http://crrev.com/c/7603221 for CRD's usage in Chromium.

Bug: chromium:475611769
Change-Id: I470b04241d3198ca9feb12e4fc502f96e7a4c13c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/452020
Commit-Queue: Yuwei Huang <yuweih@chromium.org>
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Auto-Submit: Yuwei Huang <yuweih@chromium.org>
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47001}
diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
index f420038..44eab8f 100644
--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
+++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
@@ -98,6 +98,10 @@
   void SetObserver(SharedScreenCastStream::Observer* observer) {
     observer_ = observer;
   }
+  void SetSharedMemoryFactory(
+      std::unique_ptr<webrtc::SharedMemoryFactory> shared_memory_factory) {
+    shared_memory_factory_ = std::move(shared_memory_factory);
+  }
   void StopScreenCastStream();
   std::unique_ptr<SharedDesktopFrame> CaptureFrame();
   std::unique_ptr<MouseCursor> CaptureCursor();
@@ -129,6 +133,7 @@
 
   int64_t modifier_;
   std::unique_ptr<EglDmaBuf> egl_dmabuf_;
+  std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
 
   // PipeWire types
   std::unique_ptr<PipeWireInitializer> pw_initializer_;
@@ -891,8 +896,15 @@
 
   if (!queue_.current_frame() ||
       !queue_.current_frame()->size().equals(frame_size_)) {
-    std::unique_ptr<DesktopFrame> frame(new BasicDesktopFrame(
-        DesktopSize(frame_size_.width(), frame_size_.height()), FOURCC_ARGB));
+    std::unique_ptr<DesktopFrame> frame;
+    if (shared_memory_factory_) {
+      frame = SharedMemoryDesktopFrame::Create(
+          DesktopSize(frame_size_.width(), frame_size_.height()), FOURCC_ARGB,
+          shared_memory_factory_.get());
+    } else {
+      frame = std::make_unique<BasicDesktopFrame>(
+          DesktopSize(frame_size_.width(), frame_size_.height()), FOURCC_ARGB);
+    }
     queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame)));
   }
 
@@ -1119,6 +1131,11 @@
   private_->SetObserver(observer);
 }
 
+void SharedScreenCastStream::SetSharedMemoryFactory(
+    std::unique_ptr<webrtc::SharedMemoryFactory> shared_memory_factory) {
+  private_->SetSharedMemoryFactory(std::move(shared_memory_factory));
+}
+
 void SharedScreenCastStream::StopScreenCastStream() {
   private_->StopScreenCastStream();
 }
diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.h b/modules/desktop_capture/linux/wayland/shared_screencast_stream.h
index 529803d..48d5004 100644
--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.h
+++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.h
@@ -70,6 +70,8 @@
   void UpdateScreenCastStreamFrameRate(uint32_t frame_rate);
   void SetUseDamageRegion(bool use_damage_region);
   void SetObserver(SharedScreenCastStream::Observer* observer);
+  void SetSharedMemoryFactory(
+      std::unique_ptr<webrtc::SharedMemoryFactory> shared_memory_factory);
   void StopScreenCastStream();
 
   // Below functions return the most recent information we get from a