xref: /aosp_15_r20/external/webrtc/modules/desktop_capture/win/wgc_capture_session.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_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