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