xref: /aosp_15_r20/external/webrtc/modules/desktop_capture/win/wgc_capturer_win.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_
12 #define MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_
13 
14 #include <DispatcherQueue.h>
15 #include <d3d11.h>
16 #include <wrl/client.h>
17 
18 #include <map>
19 #include <memory>
20 
21 #include "modules/desktop_capture/desktop_capture_options.h"
22 #include "modules/desktop_capture/desktop_capturer.h"
23 #include "modules/desktop_capture/win/screen_capture_utils.h"
24 #include "modules/desktop_capture/win/wgc_capture_session.h"
25 #include "modules/desktop_capture/win/wgc_capture_source.h"
26 #include "modules/desktop_capture/win/window_capture_utils.h"
27 
28 namespace webrtc {
29 
30 // Checks if the WGC API is present and supported on the system.
31 bool IsWgcSupported(CaptureType capture_type);
32 
33 // WgcCapturerWin is initialized with an implementation of this base class,
34 // which it uses to find capturable sources of a particular type. This way,
35 // WgcCapturerWin can remain source-agnostic.
36 class SourceEnumerator {
37  public:
38   virtual ~SourceEnumerator() = default;
39 
40   virtual bool FindAllSources(DesktopCapturer::SourceList* sources) = 0;
41 };
42 
43 class WindowEnumerator final : public SourceEnumerator {
44  public:
WindowEnumerator(bool enumerate_current_process_windows)45   explicit WindowEnumerator(bool enumerate_current_process_windows)
46       : enumerate_current_process_windows_(enumerate_current_process_windows) {}
47 
48   WindowEnumerator(const WindowEnumerator&) = delete;
49   WindowEnumerator& operator=(const WindowEnumerator&) = delete;
50 
51   ~WindowEnumerator() override = default;
52 
FindAllSources(DesktopCapturer::SourceList * sources)53   bool FindAllSources(DesktopCapturer::SourceList* sources) override {
54     // WGC fails to capture windows with the WS_EX_TOOLWINDOW style, so we
55     // provide it as a filter to ensure windows with the style are not returned.
56     return window_capture_helper_.EnumerateCapturableWindows(
57         sources, enumerate_current_process_windows_, WS_EX_TOOLWINDOW);
58   }
59 
60  private:
61   WindowCaptureHelperWin window_capture_helper_;
62   bool enumerate_current_process_windows_;
63 };
64 
65 class ScreenEnumerator final : public SourceEnumerator {
66  public:
67   ScreenEnumerator() = default;
68 
69   ScreenEnumerator(const ScreenEnumerator&) = delete;
70   ScreenEnumerator& operator=(const ScreenEnumerator&) = delete;
71 
72   ~ScreenEnumerator() override = default;
73 
FindAllSources(DesktopCapturer::SourceList * sources)74   bool FindAllSources(DesktopCapturer::SourceList* sources) override {
75     return webrtc::GetScreenList(sources);
76   }
77 };
78 
79 // A capturer that uses the Window.Graphics.Capture APIs. It is suitable for
80 // both window and screen capture (but only one type per instance). Consumers
81 // should not instantiate this class directly, instead they should use
82 // `CreateRawWindowCapturer()` or `CreateRawScreenCapturer()` to receive a
83 // capturer appropriate for the type of source they want to capture.
84 class WgcCapturerWin : public DesktopCapturer {
85  public:
86   WgcCapturerWin(const DesktopCaptureOptions& options,
87                  std::unique_ptr<WgcCaptureSourceFactory> source_factory,
88                  std::unique_ptr<SourceEnumerator> source_enumerator,
89                  bool allow_delayed_capturable_check);
90 
91   WgcCapturerWin(const WgcCapturerWin&) = delete;
92   WgcCapturerWin& operator=(const WgcCapturerWin&) = delete;
93 
94   ~WgcCapturerWin() override;
95 
96   static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer(
97       const DesktopCaptureOptions& options,
98       bool allow_delayed_capturable_check = false);
99 
100   static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer(
101       const DesktopCaptureOptions& options);
102 
103   // DesktopCapturer interface.
104   bool GetSourceList(SourceList* sources) override;
105   bool SelectSource(SourceId id) override;
106   bool FocusOnSelectedSource() override;
107   void Start(Callback* callback) override;
108   void CaptureFrame() override;
109 
110   // Used in WgcCapturerTests.
111   bool IsSourceBeingCaptured(SourceId id);
112 
113  private:
114   typedef HRESULT(WINAPI* CreateDispatcherQueueControllerFunc)(
115       DispatcherQueueOptions,
116       ABI::Windows::System::IDispatcherQueueController**);
117 
118   DesktopCaptureOptions options_;
119 
120   // We need to either create or ensure that someone else created a
121   // `DispatcherQueue` on the current thread so that events will be delivered
122   // on the current thread rather than an arbitrary thread. A
123   // `DispatcherQueue`'s lifetime is tied to the thread's, and we don't post
124   // any work to it, so we don't need to hold a reference.
125   bool dispatcher_queue_created_ = false;
126 
127   // Statically linking to CoreMessaging.lib is disallowed in Chromium, so we
128   // load it at runtime.
129   HMODULE core_messaging_library_ = NULL;
130   CreateDispatcherQueueControllerFunc create_dispatcher_queue_controller_func_ =
131       nullptr;
132 
133   // Factory to create a WgcCaptureSource for us whenever SelectSource is
134   // called. Initialized at construction with a source-specific implementation.
135   std::unique_ptr<WgcCaptureSourceFactory> source_factory_;
136 
137   // The source enumerator helps us find capturable sources of the appropriate
138   // type. Initialized at construction with a source-specific implementation.
139   std::unique_ptr<SourceEnumerator> source_enumerator_;
140 
141   // The WgcCaptureSource represents the source we are capturing. It tells us
142   // if the source is capturable and it creates the GraphicsCaptureItem for us.
143   std::unique_ptr<WgcCaptureSource> capture_source_;
144 
145   // A map of all the sources we are capturing and the associated
146   // WgcCaptureSession. Frames for the current source (indicated via
147   // SelectSource) will be retrieved from the appropriate session when
148   // requested via CaptureFrame.
149   // This helps us efficiently capture multiple sources (e.g. when consumers
150   // are trying to display a list of available capture targets with thumbnails).
151   std::map<SourceId, WgcCaptureSession> ongoing_captures_;
152 
153   // The callback that we deliver frames to, synchronously, before CaptureFrame
154   // returns.
155   Callback* callback_ = nullptr;
156 
157   // WgcCaptureSource::IsCapturable is expensive to run. So, caller can
158   // delay capturable check till capture frame is called if the WgcCapturerWin
159   // is used as a fallback capturer.
160   bool allow_delayed_capturable_check_ = false;
161 
162   // A Direct3D11 device that is shared amongst the WgcCaptureSessions, who
163   // require one to perform the capture.
164   Microsoft::WRL::ComPtr<::ID3D11Device> d3d11_device_;
165 };
166 
167 }  // namespace webrtc
168 
169 #endif  // MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_
170