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

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

Issue 2937663003: Ensure Dxgi duplicator works correctly in session 0 (Closed)
Patch Set: Created 3 years, 6 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 #include "webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h" 11 #include "webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
12 12
13 #include <windows.h> 13 #include <windows.h>
14 14
15 #include <algorithm> 15 #include <algorithm>
16 #include <string> 16 #include <string>
17 17
18 #include "webrtc/base/checks.h" 18 #include "webrtc/base/checks.h"
19 #include "webrtc/base/logging.h"
19 #include "webrtc/base/timeutils.h" 20 #include "webrtc/base/timeutils.h"
21 #include "webrtc/base/win32.h"
20 #include "webrtc/modules/desktop_capture/desktop_capture_types.h" 22 #include "webrtc/modules/desktop_capture/desktop_capture_types.h"
21 #include "webrtc/modules/desktop_capture/win/dxgi_frame.h" 23 #include "webrtc/modules/desktop_capture/win/dxgi_frame.h"
22 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" 24 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h"
23 #include "webrtc/system_wrappers/include/sleep.h" 25 #include "webrtc/system_wrappers/include/sleep.h"
24 26
25 namespace webrtc { 27 namespace webrtc {
26 28
29 namespace {
30
31 bool IsRunningInSession0() {
32 DWORD session_id = 0;
33 if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &session_id)) {
34 LOG(LS_WARNING) << "Failed to retrieve current session Id, no priviledge?";
35 return true;
36 }
37 return session_id == 0;
38 }
39
40 } // namespace
41
27 // static 42 // static
28 DxgiDuplicatorController* DxgiDuplicatorController::Instance() { 43 DxgiDuplicatorController* DxgiDuplicatorController::Instance() {
29 // The static instance won't be deleted to ensure it can be used by other 44 // The static instance won't be deleted to ensure it can be used by other
30 // threads even during program exiting. 45 // threads even during program exiting.
31 static DxgiDuplicatorController* instance = new DxgiDuplicatorController(); 46 static DxgiDuplicatorController* instance = new DxgiDuplicatorController();
32 return instance; 47 return instance;
33 } 48 }
34 49
35 DxgiDuplicatorController::DxgiDuplicatorController() = default; 50 DxgiDuplicatorController::DxgiDuplicatorController() = default;
36 51
37 DxgiDuplicatorController::~DxgiDuplicatorController() { 52 DxgiDuplicatorController::~DxgiDuplicatorController() {
38 rtc::CritScope lock(&lock_); 53 rtc::CritScope lock(&lock_);
39 Deinitialize(); 54 Deinitialize();
40 } 55 }
41 56
42 bool DxgiDuplicatorController::IsSupported() { 57 bool DxgiDuplicatorController::IsSupported() {
43 rtc::CritScope lock(&lock_); 58 bool result = false;
44 return Initialize(); 59 {
60 rtc::CritScope lock(&lock_);
61 result = Initialize();
62 }
63
64 if (result) {
65 return true;
66 }
67
68 if (IsRunningInSession0()) {
69 LOG(LS_WARNING) << "Current binary is running in session 0. DXGI "
70 "components cannot be initialized. Fallback to use "
71 "Windows version to decide the support of DirectX "
72 "capturer. It may be inaccurate.";
73 return rtc::IsWindows8OrLater();
Sergey Ulanov 2017/06/26 23:41:41 In this case DX capturer is effectively unsupporte
Hzj_jie 2017/06/27 04:37:33 A very good point, I have moved this logic into ht
74 }
75
76 return false;
45 } 77 }
46 78
47 bool DxgiDuplicatorController::RetrieveD3dInfo(D3dInfo* info) { 79 bool DxgiDuplicatorController::RetrieveD3dInfo(D3dInfo* info) {
48 rtc::CritScope lock(&lock_); 80 bool result = false;
49 if (!Initialize()) { 81 {
50 return false; 82 rtc::CritScope lock(&lock_);
83 result = Initialize();
51 } 84 }
52 *info = d3d_info_; 85
53 return true; 86 if (result) {
87 *info = d3d_info_;
88 return true;
89 }
90
91 if (IsRunningInSession0()) {
92 LOG(LS_WARNING) << "Current binary is running in session 0. Initialization "
93 "of DXGI components are expected to fail. But "
94 "retrieving feature level is still supported.";
95 *info = d3d_info_;
96 return true;
97 }
98
99 return false;
54 } 100 }
55 101
56 DxgiDuplicatorController::Result 102 DxgiDuplicatorController::Result
57 DxgiDuplicatorController::Duplicate(DxgiFrame* frame) { 103 DxgiDuplicatorController::Duplicate(DxgiFrame* frame) {
58 return DoDuplicate(frame, -1); 104 return DoDuplicate(frame, -1);
59 } 105 }
60 106
61 DxgiDuplicatorController::Result 107 DxgiDuplicatorController::Result
62 DxgiDuplicatorController::DuplicateMonitor(DxgiFrame* frame, int monitor_id) { 108 DxgiDuplicatorController::DuplicateMonitor(DxgiFrame* frame, int monitor_id) {
63 RTC_DCHECK_GE(monitor_id, 0); 109 RTC_DCHECK_GE(monitor_id, 0);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // size. 143 // size.
98 // TODO(zijiehe): Confirm whether IDXGIOutput::GetDesc() and 144 // TODO(zijiehe): Confirm whether IDXGIOutput::GetDesc() and
99 // IDXGIOutputDuplication::GetDesc() can detect the resolution change without 145 // IDXGIOutputDuplication::GetDesc() can detect the resolution change without
100 // reinitialization. 146 // reinitialization.
101 if (resolution_change_detector_.IsChanged( 147 if (resolution_change_detector_.IsChanged(
102 GetScreenRect(kFullDesktopScreenId, std::wstring()).size())) { 148 GetScreenRect(kFullDesktopScreenId, std::wstring()).size())) {
103 Deinitialize(); 149 Deinitialize();
104 } 150 }
105 151
106 if (!Initialize()) { 152 if (!Initialize()) {
153 if (succeeded_duplications_ == 0 && IsRunningInSession0()) {
154 LOG(LS_WARNING) << "Current binary is running in session 0. DXGI "
155 "components cannot be initialized.";
156 return Result::UNSUPPORTED_SESSION;
157 }
158
107 // Cannot initialize COM components now, display mode may be changing. 159 // Cannot initialize COM components now, display mode may be changing.
108 return Result::INITIALIZATION_FAILED; 160 return Result::INITIALIZATION_FAILED;
109 } 161 }
110 162
111 if (!frame->Prepare(SelectedDesktopSize(monitor_id), monitor_id)) { 163 if (!frame->Prepare(SelectedDesktopSize(monitor_id), monitor_id)) {
112 return Result::FRAME_PREPARE_FAILED; 164 return Result::FRAME_PREPARE_FAILED;
113 } 165 }
114 166
115 frame->frame()->mutable_updated_region()->Clear(); 167 frame->frame()->mutable_updated_region()->Clear();
116 168
117 if (DoDuplicateUnlocked(frame->context(), monitor_id, frame->frame())) { 169 if (DoDuplicateUnlocked(frame->context(), monitor_id, frame->frame())) {
170 succeeded_duplications_++;
118 return Result::SUCCEEDED; 171 return Result::SUCCEEDED;
119 } 172 }
120 if (monitor_id >= ScreenCountUnlocked()) { 173 if (monitor_id >= ScreenCountUnlocked()) {
121 // It's a user error to provide a |monitor_id| larger than screen count. We 174 // It's a user error to provide a |monitor_id| larger than screen count. We
122 // do not need to deinitialize. 175 // do not need to deinitialize.
123 return Result::INVALID_MONITOR_ID; 176 return Result::INVALID_MONITOR_ID;
124 } 177 }
125 178
126 // If the |monitor_id| is valid, but DoDuplicateUnlocked() failed, something 179 // If the |monitor_id| is valid, but DoDuplicateUnlocked() failed, something
127 // must be wrong from capturer APIs. We should Deinitialize(). 180 // must be wrong from capturer APIs. We should Deinitialize().
(...skipping 27 matching lines...) Expand all
155 208
156 bool DxgiDuplicatorController::DoInitialize() { 209 bool DxgiDuplicatorController::DoInitialize() {
157 RTC_DCHECK(desktop_rect_.is_empty()); 210 RTC_DCHECK(desktop_rect_.is_empty());
158 RTC_DCHECK(duplicators_.empty()); 211 RTC_DCHECK(duplicators_.empty());
159 212
160 d3d_info_.min_feature_level = static_cast<D3D_FEATURE_LEVEL>(0); 213 d3d_info_.min_feature_level = static_cast<D3D_FEATURE_LEVEL>(0);
161 d3d_info_.max_feature_level = static_cast<D3D_FEATURE_LEVEL>(0); 214 d3d_info_.max_feature_level = static_cast<D3D_FEATURE_LEVEL>(0);
162 215
163 std::vector<D3dDevice> devices = D3dDevice::EnumDevices(); 216 std::vector<D3dDevice> devices = D3dDevice::EnumDevices();
164 if (devices.empty()) { 217 if (devices.empty()) {
218 LOG(LS_WARNING) << "No D3dDevice found.";
165 return false; 219 return false;
166 } 220 }
167 221
168 for (size_t i = 0; i < devices.size(); i++) { 222 for (size_t i = 0; i < devices.size(); i++) {
169 duplicators_.emplace_back(devices[i]);
170 if (!duplicators_.back().Initialize()) {
171 return false;
172 }
173
174 D3D_FEATURE_LEVEL feature_level = 223 D3D_FEATURE_LEVEL feature_level =
175 devices[i].d3d_device()->GetFeatureLevel(); 224 devices[i].d3d_device()->GetFeatureLevel();
176 if (d3d_info_.max_feature_level == 0 || 225 if (d3d_info_.max_feature_level == 0 ||
177 feature_level > d3d_info_.max_feature_level) { 226 feature_level > d3d_info_.max_feature_level) {
178 d3d_info_.max_feature_level = feature_level; 227 d3d_info_.max_feature_level = feature_level;
179 } 228 }
180 if (d3d_info_.min_feature_level == 0 || 229 if (d3d_info_.min_feature_level == 0 ||
181 feature_level < d3d_info_.min_feature_level) { 230 feature_level < d3d_info_.min_feature_level) {
182 d3d_info_.min_feature_level = feature_level; 231 d3d_info_.min_feature_level = feature_level;
183 } 232 }
184 233
234 DxgiAdapterDuplicator duplicator(devices[i]);
235 if (!duplicator.Initialize()) {
236 LOG(LS_WARNING) << "Failed to initialize DxgiAdapterDuplicator on "
237 "adapter "
238 << i;
239 continue;
Sergey Ulanov 2017/06/26 23:41:41 Why do we need to keep trying initialization after
Hzj_jie 2017/06/27 04:37:33 This issue happens when a virtual adapter is insta
240 }
241 RTC_DCHECK(!duplicator.desktop_rect().is_empty());
242 duplicators_.push_back(std::move(duplicator));
243
185 desktop_rect_.UnionWith(duplicators_.back().desktop_rect()); 244 desktop_rect_.UnionWith(duplicators_.back().desktop_rect());
186 } 245 }
187 TranslateRect(); 246 TranslateRect();
188 247
189 HDC hdc = GetDC(nullptr); 248 HDC hdc = GetDC(nullptr);
190 // Use old DPI value if failed. 249 // Use old DPI value if failed.
191 if (hdc) { 250 if (hdc) {
192 dpi_.set(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY)); 251 dpi_.set(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
193 ReleaseDC(nullptr, hdc); 252 ReleaseDC(nullptr, hdc);
194 } 253 }
195 254
196 identity_++; 255 identity_++;
197 return true; 256
257 if (duplicators_.empty()) {
258 LOG(LS_WARNING) << "Cannot initialize any DxgiAdapterDuplicator instance.";
259 }
260
261 return !duplicators_.empty();
198 } 262 }
199 263
200 void DxgiDuplicatorController::Deinitialize() { 264 void DxgiDuplicatorController::Deinitialize() {
201 desktop_rect_ = DesktopRect(); 265 desktop_rect_ = DesktopRect();
202 duplicators_.clear(); 266 duplicators_.clear();
203 resolution_change_detector_.Reset(); 267 resolution_change_detector_.Reset();
204 } 268 }
205 269
206 bool DxgiDuplicatorController::ContextExpired( 270 bool DxgiDuplicatorController::ContextExpired(
207 const Context* const context) const { 271 const Context* const context) const {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 void DxgiDuplicatorController::TranslateRect() { 436 void DxgiDuplicatorController::TranslateRect() {
373 const DesktopVector position = 437 const DesktopVector position =
374 DesktopVector().subtract(desktop_rect_.top_left()); 438 DesktopVector().subtract(desktop_rect_.top_left());
375 desktop_rect_.Translate(position); 439 desktop_rect_.Translate(position);
376 for (auto& duplicator : duplicators_) { 440 for (auto& duplicator : duplicators_) {
377 duplicator.TranslateRect(position); 441 duplicator.TranslateRect(position);
378 } 442 }
379 } 443 }
380 444
381 } // namespace webrtc 445 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698