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

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

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

Powered by Google App Engine
This is Rietveld 408576698