Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(623)

Side by Side Diff: webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h

Issue 2788863006: Merge ScreenCapturerWinDirectx::frames_ and contexts_ (Closed)
Patch Set: Resolve review comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ 11 #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
12 #define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ 12 #define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
13 13
14 #include <D3DCommon.h> 14 #include <D3DCommon.h>
15 15
16 #include <memory> 16 #include <memory>
17 #include <vector> 17 #include <vector>
18 18
19 #include "webrtc/base/criticalsection.h" 19 #include "webrtc/base/criticalsection.h"
20 #include "webrtc/modules/desktop_capture/desktop_geometry.h" 20 #include "webrtc/modules/desktop_capture/desktop_geometry.h"
21 #include "webrtc/modules/desktop_capture/desktop_region.h"
22 #include "webrtc/modules/desktop_capture/resolution_change_detector.h" 21 #include "webrtc/modules/desktop_capture/resolution_change_detector.h"
23 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" 22 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
24 #include "webrtc/modules/desktop_capture/win/d3d_device.h" 23 #include "webrtc/modules/desktop_capture/win/d3d_device.h"
25 #include "webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h" 24 #include "webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h"
25 #include "webrtc/modules/desktop_capture/win/dxgi_context.h"
26 #include "webrtc/modules/desktop_capture/win/dxgi_frame.h"
26 27
27 namespace webrtc { 28 namespace webrtc {
28 29
29 // A controller for all the objects we need to call Windows DirectX capture APIs 30 // A controller for all the objects we need to call Windows DirectX capture APIs
30 // It's a singleton because only one IDXGIOutputDuplication instance per monitor 31 // It's a singleton because only one IDXGIOutputDuplication instance per monitor
31 // is allowed per application. 32 // is allowed per application.
32 // 33 //
33 // Consumers should create a DxgiDuplicatorController::Context and keep it 34 // Consumers should create a DxgiDuplicatorController::Context and keep it
34 // throughout their lifetime, and pass it when calling Duplicate(). Consumers 35 // throughout their lifetime, and pass it when calling Duplicate(). Consumers
35 // can also call IsSupported() to determine whether the system supports DXGI 36 // can also call IsSupported() to determine whether the system supports DXGI
36 // duplicator or not. If a previous IsSupported() function call returns true, 37 // duplicator or not. If a previous IsSupported() function call returns true,
37 // but a later Duplicate() returns false, this usually means the display mode is 38 // but a later Duplicate() returns false, this usually means the display mode is
38 // changing. Consumers should retry after a while. (Typically 50 milliseconds, 39 // changing. Consumers should retry after a while. (Typically 50 milliseconds,
39 // but according to hardware performance, this time may vary.) 40 // but according to hardware performance, this time may vary.)
40 class DxgiDuplicatorController { 41 class DxgiDuplicatorController {
41 public: 42 public:
42 // A context to store the status of a single consumer of 43 using Context = DxgiFrameContext;
43 // DxgiDuplicatorController.
44 class Context {
45 public:
46 Context();
47 // Unregister this Context instance from all Dxgi duplicators during
48 // destructing.
49 ~Context();
50
51 // Reset current Context, so it will be reinitialized next time.
52 void Reset();
53
54 private:
55 friend class DxgiDuplicatorController;
56
57 // A Context will have an exactly same |identity_| as
58 // DxgiDuplicatorController, to ensure it has been correctly setted up after
59 // each DxgiDuplicatorController::Initialize().
60 int identity_ = 0;
61
62 // Child DxgiAdapterDuplicator::Context belongs to this Context.
63 std::vector<DxgiAdapterDuplicator::Context> contexts_;
64 };
65 44
66 // A collection of D3d information we are interested on, which may impact 45 // A collection of D3d information we are interested on, which may impact
67 // capturer performance or reliability. 46 // capturer performance or reliability.
68 struct D3dInfo { 47 struct D3dInfo {
69 // Each video adapter has its own D3D_FEATURE_LEVEL, so this structure 48 // Each video adapter has its own D3D_FEATURE_LEVEL, so this structure
70 // contains the minimum and maximium D3D_FEATURE_LEVELs current system 49 // contains the minimum and maximium D3D_FEATURE_LEVELs current system
71 // supports. 50 // supports.
72 // Both fields can be 0, which is the default value to indicate no valid 51 // Both fields can be 0, which is the default value to indicate no valid
73 // D3D_FEATURE_LEVEL has been retrieved from underlying OS APIs. 52 // D3D_FEATURE_LEVEL has been retrieved from underlying OS APIs.
74 D3D_FEATURE_LEVEL min_feature_level; 53 D3D_FEATURE_LEVEL min_feature_level;
75 D3D_FEATURE_LEVEL max_feature_level; 54 D3D_FEATURE_LEVEL max_feature_level;
76 55
77 // TODO(zijiehe): Add more fields, such as manufacturer name, mode, driver 56 // TODO(zijiehe): Add more fields, such as manufacturer name, mode, driver
78 // version. 57 // version.
79 }; 58 };
80 59
60 enum class Result {
61 SUCCEEDED,
62 FRAME_PREPARE_FAILED,
63 INITIALIZATION_FAILED,
64 DUPLICATION_FAILED,
65 INVALID_MONITOR_ID,
66 };
67
81 // Returns the singleton instance of DxgiDuplicatorController. 68 // Returns the singleton instance of DxgiDuplicatorController.
82 static DxgiDuplicatorController* Instance(); 69 static DxgiDuplicatorController* Instance();
83 70
84 // Destructs current instance. We need to make sure COM components and their 71 // Destructs current instance. We need to make sure COM components and their
85 // containers are destructed in correct order. 72 // containers are destructed in correct order. This function calls
73 // Deinitialize() to do the real work.
86 ~DxgiDuplicatorController(); 74 ~DxgiDuplicatorController();
87 75
88 // All the following functions implicitly call Initialize() function if 76 // All the following public functions implicitly call Initialize() function.
89 // current instance has not been initialized.
90 77
91 // Detects whether the system supports DXGI based capturer. 78 // Detects whether the system supports DXGI based capturer.
92 bool IsSupported(); 79 bool IsSupported();
93 80
94 // Calls Deinitialize() function with lock. Consumers can call this function
95 // to force the DxgiDuplicatorController to be reinitialized to avoid an
96 // expected failure in next Duplicate() call.
97 void Reset();
98
99 // Returns a copy of D3dInfo composed by last Initialize() function call. 81 // Returns a copy of D3dInfo composed by last Initialize() function call.
100 bool RetrieveD3dInfo(D3dInfo* info); 82 bool RetrieveD3dInfo(D3dInfo* info);
101 83
102 // Captures current screen and writes into target. Since we are using double 84 // Captures current screen and writes into |frame|.
103 // buffering, |last_frame|.updated_region() is used to represent the not
104 // updated regions in current |target| frame, which should also be copied this
105 // time.
106 // TODO(zijiehe): Windows cannot guarantee the frames returned by each 85 // TODO(zijiehe): Windows cannot guarantee the frames returned by each
107 // IDXGIOutputDuplication are synchronized. But we are using a totally 86 // IDXGIOutputDuplication are synchronized. But we are using a totally
108 // different threading model than the way Windows suggested, it's hard to 87 // different threading model than the way Windows suggested, it's hard to
109 // synchronize them manually. We should find a way to do it. 88 // synchronize them manually. We should find a way to do it.
110 bool Duplicate(Context* context, SharedDesktopFrame* target); 89 Result Duplicate(DxgiFrame* frame);
111 90
112 // Captures one monitor and writes into target. |monitor_id| should >= 0. If 91 // Captures one monitor and writes into target. |monitor_id| should >= 0. If
113 // |monitor_id| is greater than the total screen count of all the Duplicators, 92 // |monitor_id| is greater than the total screen count of all the Duplicators,
114 // this function returns false. 93 // this function returns false.
115 bool DuplicateMonitor(Context* context, 94 Result DuplicateMonitor(DxgiFrame* frame, int monitor_id);
116 int monitor_id,
117 SharedDesktopFrame* target);
118 95
119 // Returns dpi of current system. Returns an empty DesktopVector if system 96 // Returns dpi of current system. Returns an empty DesktopVector if system
120 // does not support DXGI based capturer. 97 // does not support DXGI based capturer.
121 DesktopVector dpi(); 98 DesktopVector dpi();
122 99
123 // Returns entire desktop size. Returns an empty DesktopRect if system does
124 // not support DXGI based capturer.
125 DesktopRect desktop_rect();
126
127 // Returns a DesktopSize to cover entire desktop_rect. This may be different
128 // than desktop_rect().size(), since top-left screen does not need to start
129 // from (0, 0).
130 DesktopSize desktop_size();
131
132 // Returns the size of one screen. |monitor_id| should be >= 0. If system does
133 // not support DXGI based capturer, or |monitor_id| is greater than the total
134 // screen count of all the Duplicators, this function returns an empty
135 // DesktopRect.
136 DesktopRect ScreenRect(int id);
137
138 // Returns the count of screens on the system. These screens can be retrieved 100 // Returns the count of screens on the system. These screens can be retrieved
139 // by an integer in the range of [0, ScreenCount()). If system does not 101 // by an integer in the range of [0, ScreenCount()). If system does not
140 // support DXGI based capturer, this function returns 0. 102 // support DXGI based capturer, this function returns 0.
141 int ScreenCount(); 103 int ScreenCount();
142 104
143 private: 105 private:
144 // Context calls private Unregister(Context*) function during 106 // DxgiFrameContext calls private Unregister(Context*) function during
145 // destructing. 107 // destructing.
146 friend class Context; 108 friend DxgiFrameContext::~DxgiFrameContext();
147 109
148 // A private constructor to ensure consumers to use 110 // A private constructor to ensure consumers to use
149 // DxgiDuplicatorController::Instance(). 111 // DxgiDuplicatorController::Instance().
150 DxgiDuplicatorController(); 112 DxgiDuplicatorController();
151 113
114 // Does the real duplication work. Setting |monitor_id| < 0 to capture entire
115 // screen. This function calls Initialize(). And if the duplication failed,
116 // this function calls Deinitialize() to ensure the Dxgi components can be
117 // reinitialized next time.
118 Result DoDuplicate(DxgiFrame* frame, int monitor_id);
119
152 // Unregisters Context from this instance and all DxgiAdapterDuplicator(s) 120 // Unregisters Context from this instance and all DxgiAdapterDuplicator(s)
153 // it owns. 121 // it owns.
154 void Unregister(const Context* const context); 122 void Unregister(const Context* const context);
155 123
156 // All functions below should be called in |lock_| locked scope. 124 // All functions below should be called in |lock_| locked scope and should be
125 // after a successful Initialize().
157 126
158 // If current instance has not been initialized, executes DoInitialize 127 // If current instance has not been initialized, executes DoInitialize()
159 // function, and returns initialize result. Otherwise directly returns true. 128 // function, and returns initialize result. Otherwise directly returns true.
129 // This function may calls Deinitialize() if initialization failed.
160 bool Initialize(); 130 bool Initialize();
161 131
132 // Does the real initialization work, this function should only be called in
133 // Initialize().
162 bool DoInitialize(); 134 bool DoInitialize();
163 135
164 // Clears all COM components referred by this instance. So next Duplicate() 136 // Clears all COM components referred by this instance. So next Duplicate()
165 // call will eventually initialize this instance again. 137 // call will eventually initialize this instance again.
166 void Deinitialize(); 138 void Deinitialize();
167 139
168 // A helper function to check whether a Context has been expired. 140 // A helper function to check whether a Context has been expired.
169 bool ContextExpired(const Context* const context) const; 141 bool ContextExpired(const Context* const context) const;
170 142
171 // Updates Context if needed. 143 // Updates Context if needed.
172 void Setup(Context* context); 144 void Setup(Context* context);
173 145
174 // Does the real duplication work. |monitor_id < 0| to capture entire screen.
175 bool DoDuplicate(Context* context,
176 int monitor_id,
177 SharedDesktopFrame* target);
178
179 bool DoDuplicateUnlocked(Context* context, 146 bool DoDuplicateUnlocked(Context* context,
180 int monitor_id, 147 int monitor_id,
181 SharedDesktopFrame* target); 148 SharedDesktopFrame* target);
182 149
183 // Captures all monitors. 150 // Captures all monitors.
184 bool DoDuplicateAll(Context* context, SharedDesktopFrame* target); 151 bool DoDuplicateAll(Context* context, SharedDesktopFrame* target);
185 152
186 // Captures one monitor. 153 // Captures one monitor.
187 bool DoDuplicateOne(Context* context, 154 bool DoDuplicateOne(Context* context,
188 int monitor_id, 155 int monitor_id,
189 SharedDesktopFrame* target); 156 SharedDesktopFrame* target);
190 157
191 // The minimum GetNumFramesCaptured() returned by |duplicators_|. 158 // The minimum GetNumFramesCaptured() returned by |duplicators_|.
192 int64_t GetNumFramesCaptured() const; 159 int64_t GetNumFramesCaptured() const;
193 160
194 int ScreenCountUnlocked(); 161 // Returns a DesktopSize to cover entire desktop_rect. This may be different
162 // than desktop_rect().size(), since top-left of the screen does not need to
163 // be started from (0, 0).
164 DesktopSize desktop_size() const;
165
166 // Returns the size of one screen. |id| should be >= 0. If system does not
167 // support DXGI based capturer, or |id| is greater than the total screen count
168 // of all the Duplicators, this function returns an empty DesktopRect.
169 DesktopRect ScreenRect(int id) const;
170
171 int ScreenCountUnlocked() const;
172
173 // Returns the desktop size of the selected screen |monitor_id|. Setting
174 // |monitor_id| < 0 to return the entire screen size.
175 DesktopSize SelectedDesktopSize(int monitor_id) const;
195 176
196 // Retries DoDuplicateAll() for several times until GetNumFramesCaptured() is 177 // Retries DoDuplicateAll() for several times until GetNumFramesCaptured() is
197 // large enough. Returns false if DoDuplicateAll() returns false, or 178 // large enough. Returns false if DoDuplicateAll() returns false, or
198 // GetNumFramesCaptured() has never reached the requirement. 179 // GetNumFramesCaptured() has never reached the requirement.
199 // According to http://crbug.com/682112, dxgi capturer returns a black frame 180 // According to http://crbug.com/682112, dxgi capturer returns a black frame
200 // during first several capture attempts. 181 // during first several capture attempts.
201 bool EnsureFrameCaptured(Context* context, SharedDesktopFrame* target); 182 bool EnsureFrameCaptured(Context* context, SharedDesktopFrame* target);
202 183
203 // This lock must be locked whenever accessing any of the following objects. 184 // This lock must be locked whenever accessing any of the following objects.
204 rtc::CriticalSection lock_; 185 rtc::CriticalSection lock_;
205 186
206 // A self-incremented integer to compare with the one in Context, to 187 // A self-incremented integer to compare with the one in Context. It ensures
207 // ensure a Context has been initialized after DxgiDuplicatorController. 188 // a Context instance is always initialized after DxgiDuplicatorController.
208 int identity_ = 0; 189 int identity_ = 0;
209 DesktopRect desktop_rect_; 190 DesktopRect desktop_rect_;
210 DesktopVector dpi_; 191 DesktopVector dpi_;
211 std::vector<DxgiAdapterDuplicator> duplicators_; 192 std::vector<DxgiAdapterDuplicator> duplicators_;
212 D3dInfo d3d_info_; 193 D3dInfo d3d_info_;
213 ResolutionChangeDetector resolution_change_detector_; 194 ResolutionChangeDetector resolution_change_detector_;
214 }; 195 };
215 196
216 } // namespace webrtc 197 } // namespace webrtc
217 198
218 #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ 199 #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
OLDNEW
« no previous file with comments | « webrtc/modules/desktop_capture/win/dxgi_context.cc ('k') | webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698