wgc_capturer_win.h (7567B)
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 <cstddef> 19 #include <map> 20 #include <memory> 21 22 #include "api/scoped_refptr.h" 23 #include "modules/desktop_capture/desktop_capture_options.h" 24 #include "modules/desktop_capture/desktop_capture_types.h" 25 #include "modules/desktop_capture/desktop_capturer.h" 26 #include "modules/desktop_capture/full_screen_window_detector.h" 27 #include "modules/desktop_capture/win/screen_capture_utils.h" 28 #include "modules/desktop_capture/win/wgc_capture_session.h" 29 #include "modules/desktop_capture/win/wgc_capture_source.h" 30 #include "modules/desktop_capture/win/window_capture_utils.h" 31 32 namespace webrtc { 33 34 // Checks if the WGC API is present and supported on the system. 35 bool IsWgcSupported(CaptureType capture_type); 36 37 // WgcCapturerWin is initialized with an implementation of this base class, 38 // which it uses to find capturable sources of a particular type. This way, 39 // WgcCapturerWin can remain source-agnostic. 40 class SourceEnumerator { 41 public: 42 virtual ~SourceEnumerator() = default; 43 44 virtual bool FindAllSources(DesktopCapturer::SourceList* sources) = 0; 45 }; 46 47 class WindowEnumerator final : public SourceEnumerator { 48 public: 49 explicit WindowEnumerator(bool enumerate_current_process_windows) 50 : enumerate_current_process_windows_(enumerate_current_process_windows) {} 51 52 WindowEnumerator(const WindowEnumerator&) = delete; 53 WindowEnumerator& operator=(const WindowEnumerator&) = delete; 54 55 ~WindowEnumerator() override = default; 56 57 bool FindAllSources(DesktopCapturer::SourceList* sources) override { 58 // WGC fails to capture windows with the WS_EX_TOOLWINDOW style, so we 59 // provide it as a filter to ensure windows with the style are not returned. 60 return window_capture_helper_.EnumerateCapturableWindows( 61 sources, enumerate_current_process_windows_, WS_EX_TOOLWINDOW); 62 } 63 64 private: 65 WindowCaptureHelperWin window_capture_helper_; 66 bool enumerate_current_process_windows_; 67 }; 68 69 class ScreenEnumerator final : public SourceEnumerator { 70 public: 71 ScreenEnumerator() = default; 72 73 ScreenEnumerator(const ScreenEnumerator&) = delete; 74 ScreenEnumerator& operator=(const ScreenEnumerator&) = delete; 75 76 ~ScreenEnumerator() override = default; 77 78 bool FindAllSources(DesktopCapturer::SourceList* sources) override { 79 return GetScreenList(sources); 80 } 81 }; 82 83 // A capturer that uses the Window.Graphics.Capture APIs. It is suitable for 84 // both window and screen capture (but only one type per instance). Consumers 85 // should not instantiate this class directly, instead they should use 86 // `CreateRawWindowCapturer()` or `CreateRawScreenCapturer()` to receive a 87 // capturer appropriate for the type of source they want to capture. 88 class WgcCapturerWin : public DesktopCapturer { 89 public: 90 WgcCapturerWin(const DesktopCaptureOptions& options, 91 std::unique_ptr<WgcCaptureSourceFactory> source_factory, 92 std::unique_ptr<SourceEnumerator> source_enumerator, 93 bool allow_delayed_capturable_check); 94 95 WgcCapturerWin(const WgcCapturerWin&) = delete; 96 WgcCapturerWin& operator=(const WgcCapturerWin&) = delete; 97 98 ~WgcCapturerWin() override; 99 100 static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer( 101 const DesktopCaptureOptions& options, 102 bool allow_delayed_capturable_check = false); 103 104 static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer( 105 const DesktopCaptureOptions& options); 106 107 // DesktopCapturer interface. 108 bool GetSourceList(SourceList* sources) override; 109 bool SelectSource(SourceId id) override; 110 bool FocusOnSelectedSource() override; 111 void Start(Callback* callback) override; 112 void CaptureFrame() override; 113 114 // Used in WgcCapturerTests. 115 bool IsSourceBeingCaptured(SourceId id); 116 void SetUpFullScreenDetectorForTest( 117 bool use_heuristic, 118 DesktopCapturer::SourceId source_id, 119 bool fullscreen_slide_show_started_after_capture_start = true); 120 121 private: 122 typedef HRESULT(WINAPI* CreateDispatcherQueueControllerFunc)( 123 DispatcherQueueOptions, 124 ABI::Windows::System::IDispatcherQueueController**); 125 126 DesktopCaptureOptions options_; 127 128 // We need to either create or ensure that someone else created a 129 // `DispatcherQueue` on the current thread so that events will be delivered 130 // on the current thread rather than an arbitrary thread. A 131 // `DispatcherQueue`'s lifetime is tied to the thread's, and we don't post 132 // any work to it, so we don't need to hold a reference. 133 bool dispatcher_queue_created_ = false; 134 135 // Statically linking to CoreMessaging.lib is disallowed in Chromium, so we 136 // load it at runtime. 137 HMODULE core_messaging_library_ = NULL; 138 CreateDispatcherQueueControllerFunc create_dispatcher_queue_controller_func_ = 139 nullptr; 140 141 // Factory to create a WgcCaptureSource for us whenever SelectSource is 142 // called. Initialized at construction with a source-specific implementation. 143 std::unique_ptr<WgcCaptureSourceFactory> source_factory_; 144 145 // The source enumerator helps us find capturable sources of the appropriate 146 // type. Initialized at construction with a source-specific implementation. 147 std::unique_ptr<SourceEnumerator> source_enumerator_; 148 149 // The WgcCaptureSource represents the source we are capturing. It tells us 150 // if the source is capturable and it creates the GraphicsCaptureItem for us. 151 std::unique_ptr<WgcCaptureSource> capture_source_; 152 153 // DesktopCapturer::SourceId of the source that was selected by the user. It 154 // might not necessarily correspond to the `capture_source_` when the 155 // `full_screen_window_detector_` is active. 156 DesktopCapturer::SourceId selected_source_id_; 157 158 // A map of all the sources we are capturing and the associated 159 // WgcCaptureSession. Frames for the current source (indicated via 160 // SelectSource) will be retrieved from the appropriate session when 161 // requested via CaptureFrame. 162 // This helps us efficiently capture multiple sources (e.g. when consumers 163 // are trying to display a list of available capture targets with thumbnails). 164 std::map<SourceId, WgcCaptureSession> ongoing_captures_; 165 166 // The callback that we deliver frames to, synchronously, before CaptureFrame 167 // returns. 168 Callback* callback_ = nullptr; 169 170 // WgcCaptureSource::IsCapturable is expensive to run. So, caller can 171 // delay capturable check till capture frame is called if the WgcCapturerWin 172 // is used as a fallback capturer. 173 bool allow_delayed_capturable_check_ = false; 174 175 // A Direct3D11 device that is shared amongst the WgcCaptureSessions, who 176 // require one to perform the capture. 177 Microsoft::WRL::ComPtr<::ID3D11Device> d3d11_device_; 178 179 // This allows us to find full screen windows for applications in some 180 // specific cases. 181 scoped_refptr<FullScreenWindowDetector> full_screen_window_detector_; 182 183 // Used to make sure that we only log the usage of fullscreen detection once. 184 bool fullscreen_usage_logged_ = false; 185 }; 186 187 } // namespace webrtc 188 189 #endif // MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_