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

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

Powered by Google App Engine
This is Rietveld 408576698