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_CAPTURE_SESSION_H_ 12 #define MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURE_SESSION_H_ 13 14 #include <d3d11.h> 15 #include <windows.graphics.capture.h> 16 #include <windows.graphics.h> 17 #include <wrl/client.h> 18 19 #include <memory> 20 21 #include "api/sequence_checker.h" 22 #include "modules/desktop_capture/desktop_capture_options.h" 23 #include "modules/desktop_capture/win/wgc_capture_source.h" 24 #include "rtc_base/event.h" 25 26 namespace webrtc { 27 28 class WgcCaptureSession final { 29 public: 30 WgcCaptureSession( 31 Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device, 32 Microsoft::WRL::ComPtr< 33 ABI::Windows::Graphics::Capture::IGraphicsCaptureItem> item, 34 ABI::Windows::Graphics::SizeInt32 size); 35 36 // Disallow copy and assign. 37 WgcCaptureSession(const WgcCaptureSession&) = delete; 38 WgcCaptureSession& operator=(const WgcCaptureSession&) = delete; 39 40 ~WgcCaptureSession(); 41 42 HRESULT StartCapture(const DesktopCaptureOptions& options); 43 44 // Returns a frame from the frame pool, if any are present. 45 HRESULT GetFrame(std::unique_ptr<DesktopFrame>* output_frame); 46 IsCaptureStarted()47 bool IsCaptureStarted() const { 48 RTC_DCHECK_RUN_ON(&sequence_checker_); 49 return is_capture_started_; 50 } 51 52 // We keep 2 buffers in the frame pool to balance the staleness of the frame 53 // with having to wait for frames to arrive too frequently. Too many buffers 54 // will lead to a high latency, and too few will lead to poor performance. 55 // We make this public for tests. 56 static constexpr int kNumBuffers = 2; 57 58 private: 59 // Initializes `mapped_texture_` with the properties of the `src_texture`, 60 // overrides the values of some necessary properties like the 61 // D3D11_CPU_ACCESS_READ flag. Also has optional parameters for what size 62 // `mapped_texture_` should be, if they aren't provided we will use the size 63 // of `src_texture`. 64 HRESULT CreateMappedTexture( 65 Microsoft::WRL::ComPtr<ID3D11Texture2D> src_texture, 66 UINT width = 0, 67 UINT height = 0); 68 69 // Event handler for `item_`'s Closed event. 70 HRESULT OnItemClosed( 71 ABI::Windows::Graphics::Capture::IGraphicsCaptureItem* sender, 72 IInspectable* event_args); 73 74 // Event handler for `frame_pool_`'s FrameArrived event. 75 HRESULT OnFrameArrived( 76 ABI::Windows::Graphics::Capture::IDirect3D11CaptureFramePool* sender, 77 IInspectable* event_args); 78 79 void RemoveEventHandlers(); 80 81 // We wait on this event in `GetFrame` if there are no frames in the pool. 82 // `OnFrameArrived` will set the event so we can proceed. 83 rtc::Event wait_for_frame_event_; 84 int frames_in_pool_; 85 86 // We're willing to wait for a frame a little longer if it's the first one. 87 bool first_frame_ = true; 88 89 std::unique_ptr<EventRegistrationToken> frame_arrived_token_; 90 std::unique_ptr<EventRegistrationToken> item_closed_token_; 91 92 // A Direct3D11 Device provided by the caller. We use this to create an 93 // IDirect3DDevice, and also to create textures that will hold the image data. 94 Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_; 95 96 // This item represents what we are capturing, we use it to create the 97 // capture session, and also to listen for the Closed event. 98 Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem> 99 item_; 100 101 // The IDirect3DDevice is necessary to instantiate the frame pool. 102 Microsoft::WRL::ComPtr< 103 ABI::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice> 104 direct3d_device_; 105 106 // The frame pool is where frames are deposited during capture, we retrieve 107 // them from here with TryGetNextFrame(). 108 Microsoft::WRL::ComPtr< 109 ABI::Windows::Graphics::Capture::IDirect3D11CaptureFramePool> 110 frame_pool_; 111 112 // This texture holds the final image data. We made it a member so we can 113 // reuse it, instead of having to create a new texture every time we grab a 114 // frame. 115 Microsoft::WRL::ComPtr<ID3D11Texture2D> mapped_texture_; 116 117 // This is the size of `mapped_texture_` and the buffers in `frame_pool_`. We 118 // store this as a member so we can compare it to the size of incoming frames 119 // and resize if necessary. 120 ABI::Windows::Graphics::SizeInt32 size_; 121 122 // The capture session lets us set properties about the capture before it 123 // starts such as whether to capture the mouse cursor, and it lets us tell WGC 124 // to start capturing frames. 125 Microsoft::WRL::ComPtr< 126 ABI::Windows::Graphics::Capture::IGraphicsCaptureSession> 127 session_; 128 129 bool item_closed_ = false; 130 bool is_capture_started_ = false; 131 132 SequenceChecker sequence_checker_; 133 }; 134 135 } // namespace webrtc 136 137 #endif // MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURE_SESSION_H_ 138