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

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

Issue 2319383002: Several minor changes to ScreenCapturerWinMagnifier (Closed)
Patch Set: Created 4 years, 3 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) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 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/screen_capturer_win_magnifier.h" 11 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h"
12 12
13 #include <assert.h>
14
15 #include <utility> 13 #include <utility>
16 14
15 #include "webrtc/base/checks.h"
17 #include "webrtc/base/timeutils.h" 16 #include "webrtc/base/timeutils.h"
18 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" 17 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
19 #include "webrtc/modules/desktop_capture/desktop_frame.h" 18 #include "webrtc/modules/desktop_capture/desktop_frame.h"
20 #include "webrtc/modules/desktop_capture/desktop_frame_win.h" 19 #include "webrtc/modules/desktop_capture/desktop_frame_win.h"
21 #include "webrtc/modules/desktop_capture/desktop_region.h" 20 #include "webrtc/modules/desktop_capture/desktop_region.h"
22 #include "webrtc/modules/desktop_capture/differ.h" 21 #include "webrtc/modules/desktop_capture/differ.h"
23 #include "webrtc/modules/desktop_capture/mouse_cursor.h" 22 #include "webrtc/modules/desktop_capture/mouse_cursor.h"
24 #include "webrtc/modules/desktop_capture/win/cursor.h" 23 #include "webrtc/modules/desktop_capture/win/cursor.h"
25 #include "webrtc/modules/desktop_capture/win/desktop.h" 24 #include "webrtc/modules/desktop_capture/win/desktop.h"
26 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" 25 #include "webrtc/modules/desktop_capture/win/screen_capture_utils.h"
27 #include "webrtc/system_wrappers/include/logging.h" 26 #include "webrtc/system_wrappers/include/logging.h"
28 27
29 namespace webrtc { 28 namespace webrtc {
30 29
31 // kMagnifierWindowClass has to be "Magnifier" according to the Magnification 30 // kMagnifierWindowClass has to be "Magnifier" according to the Magnification
32 // API. The other strings can be anything. 31 // API. The other strings can be anything.
33 static LPCTSTR kMagnifierHostClass = L"ScreenCapturerWinMagnifierHost"; 32 static LPCTSTR kMagnifierHostClass = L"ScreenCapturerWinMagnifierHost";
34 static LPCTSTR kHostWindowName = L"MagnifierHost"; 33 static LPCTSTR kHostWindowName = L"MagnifierHost";
35 static LPCTSTR kMagnifierWindowClass = L"Magnifier"; 34 static LPCTSTR kMagnifierWindowClass = L"Magnifier";
36 static LPCTSTR kMagnifierWindowName = L"MagnifierWindow"; 35 static LPCTSTR kMagnifierWindowName = L"MagnifierWindow";
37 36 thread_local static ScreenCapturerWinMagnifier* kCurrent;
Sergey Ulanov 2016/09/19 20:53:18 - thread_local is not listed on chromium-cpp.appsp
Hzj_jie 2016/09/19 22:05:23 Emmm, a Google internal mail thread shows thread_l
Sergey Ulanov 2016/09/19 22:21:25 __declspec(thread) seems used in some third-party
38 Atomic32 ScreenCapturerWinMagnifier::tls_index_(TLS_OUT_OF_INDEXES);
39 37
40 ScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier( 38 ScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier(
41 std::unique_ptr<ScreenCapturer> fallback_capturer) 39 std::unique_ptr<ScreenCapturer> fallback_capturer)
42 : fallback_capturer_(std::move(fallback_capturer)) {} 40 : fallback_capturer_(std::move(fallback_capturer)) {}
43 41
44 ScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() { 42 ScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() {
45 // DestroyWindow must be called before MagUninitialize. magnifier_window_ is 43 // DestroyWindow must be called before MagUninitialize. magnifier_window_ is
46 // destroyed automatically when host_window_ is destroyed. 44 // destroyed automatically when host_window_ is destroyed.
47 if (host_window_) 45 if (host_window_)
48 DestroyWindow(host_window_); 46 DestroyWindow(host_window_);
49 47
50 if (magnifier_initialized_) 48 if (magnifier_initialized_)
51 mag_uninitialize_func_(); 49 mag_uninitialize_func_();
52 50
53 if (mag_lib_handle_) 51 if (mag_lib_handle_)
54 FreeLibrary(mag_lib_handle_); 52 FreeLibrary(mag_lib_handle_);
55 53
56 if (desktop_dc_) 54 if (desktop_dc_)
57 ReleaseDC(NULL, desktop_dc_); 55 ReleaseDC(NULL, desktop_dc_);
58 } 56 }
59 57
60 void ScreenCapturerWinMagnifier::Start(Callback* callback) { 58 void ScreenCapturerWinMagnifier::Start(Callback* callback) {
61 assert(!callback_); 59 assert(!callback_);
62 assert(callback); 60 assert(callback);
63 callback_ = callback; 61 callback_ = callback;
64 62
65 InitializeMagnifier(); 63 if (!InitializeMagnifier()) {
64 StartFallbackCapturer();
65 }
66 } 66 }
67 67
68 void ScreenCapturerWinMagnifier::SetSharedMemoryFactory( 68 void ScreenCapturerWinMagnifier::SetSharedMemoryFactory(
69 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { 69 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) {
70 shared_memory_factory_ = std::move(shared_memory_factory); 70 shared_memory_factory_ = std::move(shared_memory_factory);
71 } 71 }
72 72
73 void ScreenCapturerWinMagnifier::Capture(const DesktopRegion& region) { 73 void ScreenCapturerWinMagnifier::Capture(const DesktopRegion& region) {
74 int64_t capture_start_time_nanos = rtc::TimeNanos(); 74 int64_t capture_start_time_nanos = rtc::TimeNanos();
75 75
76 queue_.MoveToNextFrame(); 76 queue_.MoveToNextFrame();
77 77
78 // Request that the system not power-down the system, or the display hardware.
79 if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) {
80 if (!set_thread_execution_state_failed_) {
81 set_thread_execution_state_failed_ = true;
82 LOG_F(LS_WARNING) << "Failed to make system & display power assertion: "
83 << GetLastError();
84 }
85 }
86 // Switch to the desktop receiving user input if different from the current 78 // Switch to the desktop receiving user input if different from the current
87 // one. 79 // one.
88 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); 80 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop());
89 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 81 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) {
90 // Release GDI resources otherwise SetThreadDesktop will fail. 82 // Release GDI resources otherwise SetThreadDesktop will fail.
91 if (desktop_dc_) { 83 if (desktop_dc_) {
92 ReleaseDC(NULL, desktop_dc_); 84 ReleaseDC(NULL, desktop_dc_);
93 desktop_dc_ = NULL; 85 desktop_dc_ = NULL;
94 } 86 }
95 // If SetThreadDesktop() fails, the thread is still assigned a desktop. 87 // If SetThreadDesktop() fails, the thread is still assigned a desktop.
96 // So we can continue capture screen bits, just from the wrong desktop. 88 // So we can continue capture screen bits, just from the wrong desktop.
97 desktop_.SetThreadDesktop(input_desktop.release()); 89 desktop_.SetThreadDesktop(input_desktop.release());
98 } 90 }
99 91
100 bool succeeded = false; 92 bool succeeded = false;
101 93
102 // Do not try to use the magnifier if it failed before and in multi-screen 94 // Do not try to use the magnifier if it failed before and in multi-screen
103 // setup (where the API crashes sometimes). 95 // setup (where the API crashes sometimes).
104 if (magnifier_initialized_ && (GetSystemMetrics(SM_CMONITORS) == 1) && 96 if (magnifier_initialized_ && magnifier_capture_succeeded_) {
105 magnifier_capture_succeeded_) {
106 DesktopRect rect = GetScreenRect(current_screen_id_, current_device_key_); 97 DesktopRect rect = GetScreenRect(current_screen_id_, current_device_key_);
107 CreateCurrentFrameIfNecessary(rect.size()); 98 CreateCurrentFrameIfNecessary(rect.size());
108 99
109 // CaptureImage may fail in some situations, e.g. windows8 metro mode. 100 // CaptureImage may fail in some situations, e.g. windows8 metro mode.
110 succeeded = CaptureImage(rect); 101 succeeded = CaptureImage(rect);
111 } 102 }
112 103
113 // Defer to the fallback capturer if magnifier capturer did not work. 104 // Defer to the fallback capturer if magnifier capturer did not work.
114 if (!succeeded) { 105 if (!succeeded) {
115 LOG_F(LS_WARNING) << "Switching to the fallback screen capturer."; 106 LOG_F(LS_WARNING) << "Switching to the fallback screen capturer.";
116 StartFallbackCapturer(); 107 StartFallbackCapturer();
117 fallback_capturer_->Capture(region); 108 fallback_capturer_->Capture(region);
118 return; 109 return;
119 } 110 }
120 111
121 const DesktopFrame* current_frame = queue_.current_frame(); 112 const DesktopFrame* current_frame = queue_.current_frame();
122 const DesktopFrame* last_frame = queue_.previous_frame(); 113 const DesktopFrame* last_frame = queue_.previous_frame();
114 DesktopRegion updated_region;
123 if (last_frame && last_frame->size().equals(current_frame->size())) { 115 if (last_frame && last_frame->size().equals(current_frame->size())) {
124 // Make sure the differencer is set up correctly for these previous and 116 // Make sure the differencer is set up correctly for these previous and
125 // current screens. 117 // current screens.
126 if (!differ_.get() || (differ_->width() != current_frame->size().width()) || 118 if (!differ_.get() || (differ_->width() != current_frame->size().width()) ||
127 (differ_->height() != current_frame->size().height()) || 119 (differ_->height() != current_frame->size().height()) ||
128 (differ_->bytes_per_row() != current_frame->stride())) { 120 (differ_->bytes_per_row() != current_frame->stride())) {
129 differ_.reset(new Differ(current_frame->size().width(), 121 differ_.reset(new Differ(current_frame->size().width(),
130 current_frame->size().height(), 122 current_frame->size().height(),
131 DesktopFrame::kBytesPerPixel, 123 DesktopFrame::kBytesPerPixel,
132 current_frame->stride())); 124 current_frame->stride()));
133 } 125 }
134 126
135 // Calculate difference between the two last captured frames. 127 // Calculate difference between the two last captured frames.
136 DesktopRegion region;
137 differ_->CalcDirtyRegion( 128 differ_->CalcDirtyRegion(
Sergey Ulanov 2016/09/19 20:53:18 Do we need to keep the differ here?
Hzj_jie 2016/09/19 22:05:23 No, but all the differs will be removed in https:/
138 last_frame->data(), current_frame->data(), &region); 129 last_frame->data(), current_frame->data(), &updated_region);
139 helper_.InvalidateRegion(region);
140 } else { 130 } else {
141 // No previous frame is available, or the screen is resized. Invalidate the 131 updated_region.SetRect(DesktopRect::MakeSize(current_frame->size()));
142 // whole screen.
143 helper_.InvalidateScreen(current_frame->size());
144 } 132 }
145 133
146 helper_.set_size_most_recent(current_frame->size());
147
148 // Emit the current frame. 134 // Emit the current frame.
149 std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share(); 135 std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share();
150 frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX), 136 frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX),
151 GetDeviceCaps(desktop_dc_, LOGPIXELSY))); 137 GetDeviceCaps(desktop_dc_, LOGPIXELSY)));
152 frame->mutable_updated_region()->Clear(); 138 frame->mutable_updated_region()->Swap(&updated_region);
153 helper_.TakeInvalidRegion(frame->mutable_updated_region());
154 frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) / 139 frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) /
155 rtc::kNumNanosecsPerMillisec); 140 rtc::kNumNanosecsPerMillisec);
156 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); 141 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
157 } 142 }
158 143
159 bool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) { 144 bool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) {
160 return webrtc::GetScreenList(screens); 145 return webrtc::GetScreenList(screens);
161 } 146 }
162 147
163 bool ScreenCapturerWinMagnifier::SelectScreen(ScreenId id) { 148 bool ScreenCapturerWinMagnifier::SelectScreen(ScreenId id) {
(...skipping 29 matching lines...) Expand all
193 LOG_F(LS_WARNING) << "Failed to call SetWindowPos: " << GetLastError() 178 LOG_F(LS_WARNING) << "Failed to call SetWindowPos: " << GetLastError()
194 << ". Rect = {" << rect.left() << ", " << rect.top() 179 << ". Rect = {" << rect.left() << ", " << rect.top()
195 << ", " << rect.right() << ", " << rect.bottom() << "}"; 180 << ", " << rect.right() << ", " << rect.bottom() << "}";
196 return false; 181 return false;
197 } 182 }
198 183
199 magnifier_capture_succeeded_ = false; 184 magnifier_capture_succeeded_ = false;
200 185
201 RECT native_rect = {rect.left(), rect.top(), rect.right(), rect.bottom()}; 186 RECT native_rect = {rect.left(), rect.top(), rect.right(), rect.bottom()};
202 187
188 kCurrent = this;
203 // OnCaptured will be called via OnMagImageScalingCallback and fill in the 189 // OnCaptured will be called via OnMagImageScalingCallback and fill in the
204 // frame before set_window_source_func_ returns. 190 // frame before set_window_source_func_ returns.
205 result = set_window_source_func_(magnifier_window_, native_rect); 191 result = set_window_source_func_(magnifier_window_, native_rect);
206 192
207 if (!result) { 193 if (!result) {
208 LOG_F(LS_WARNING) << "Failed to call MagSetWindowSource: " << GetLastError() 194 LOG_F(LS_WARNING) << "Failed to call MagSetWindowSource: " << GetLastError()
209 << ". Rect = {" << rect.left() << ", " << rect.top() 195 << ". Rect = {" << rect.left() << ", " << rect.top()
210 << ", " << rect.right() << ", " << rect.bottom() << "}"; 196 << ", " << rect.right() << ", " << rect.bottom() << "}";
211 return false; 197 return false;
212 } 198 }
213 199
214 return magnifier_capture_succeeded_; 200 return magnifier_capture_succeeded_;
215 } 201 }
216 202
217 BOOL ScreenCapturerWinMagnifier::OnMagImageScalingCallback( 203 BOOL ScreenCapturerWinMagnifier::OnMagImageScalingCallback(
218 HWND hwnd, 204 HWND hwnd,
219 void* srcdata, 205 void* srcdata,
220 MAGIMAGEHEADER srcheader, 206 MAGIMAGEHEADER srcheader,
221 void* destdata, 207 void* destdata,
222 MAGIMAGEHEADER destheader, 208 MAGIMAGEHEADER destheader,
223 RECT unclipped, 209 RECT unclipped,
224 RECT clipped, 210 RECT clipped,
225 HRGN dirty) { 211 HRGN dirty) {
226 assert(tls_index_.Value() != static_cast<int32_t>(TLS_OUT_OF_INDEXES)); 212 RTC_DCHECK(kCurrent != nullptr);
Sergey Ulanov 2016/09/19 20:53:18 Please replace all asserts with RTC_DCHECK
Hzj_jie 2016/09/19 22:05:23 Done.
227 213 kCurrent->OnCaptured(srcdata, srcheader);
228 ScreenCapturerWinMagnifier* owner =
229 reinterpret_cast<ScreenCapturerWinMagnifier*>(
230 TlsGetValue(tls_index_.Value()));
231
232 owner->OnCaptured(srcdata, srcheader);
233
234 return TRUE; 214 return TRUE;
235 } 215 }
236 216
237 bool ScreenCapturerWinMagnifier::InitializeMagnifier() { 217 bool ScreenCapturerWinMagnifier::InitializeMagnifier() {
238 assert(!magnifier_initialized_); 218 assert(!magnifier_initialized_);
219 if (GetSystemMetrics(SM_CMONITORS) != 1) {
Sergey Ulanov 2016/09/19 20:53:18 I think it's better to keep this check in ScreenCa
Hzj_jie 2016/09/19 22:05:23 Good point. Updated.
220 // Do not try to use the magnifier if it failed before and in multi-screen
221 // setup (where the API crashes sometimes).
222 return false;
223 }
239 224
240 desktop_dc_ = GetDC(nullptr); 225 desktop_dc_ = GetDC(nullptr);
241 226
242 mag_lib_handle_ = LoadLibrary(L"Magnification.dll"); 227 mag_lib_handle_ = LoadLibrary(L"Magnification.dll");
243 if (!mag_lib_handle_) 228 if (!mag_lib_handle_)
244 return false; 229 return false;
245 230
246 // Initialize Magnification API function pointers. 231 // Initialize Magnification API function pointers.
247 mag_initialize_func_ = reinterpret_cast<MagInitializeFunc>( 232 mag_initialize_func_ = reinterpret_cast<MagInitializeFunc>(
248 GetProcAddress(mag_lib_handle_, "MagInitialize")); 233 GetProcAddress(mag_lib_handle_, "MagInitialize"));
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_); 323 magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_);
339 if (!result) { 324 if (!result) {
340 mag_uninitialize_func_(); 325 mag_uninitialize_func_();
341 LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: " 326 LOG_F(LS_WARNING) << "Failed to initialize ScreenCapturerWinMagnifier: "
342 << "error from MagSetWindowFilterList " 327 << "error from MagSetWindowFilterList "
343 << GetLastError(); 328 << GetLastError();
344 return false; 329 return false;
345 } 330 }
346 } 331 }
347 332
348 if (tls_index_.Value() == static_cast<int32_t>(TLS_OUT_OF_INDEXES)) {
349 // More than one threads may get here at the same time, but only one will
350 // write to tls_index_ using CompareExchange.
351 DWORD new_tls_index = TlsAlloc();
352 if (!tls_index_.CompareExchange(new_tls_index, TLS_OUT_OF_INDEXES))
353 TlsFree(new_tls_index);
354 }
355
356 assert(tls_index_.Value() != static_cast<int32_t>(TLS_OUT_OF_INDEXES));
357 TlsSetValue(tls_index_.Value(), this);
358
359 magnifier_initialized_ = true; 333 magnifier_initialized_ = true;
360 return true; 334 return true;
361 } 335 }
362 336
363 void ScreenCapturerWinMagnifier::OnCaptured(void* data, 337 void ScreenCapturerWinMagnifier::OnCaptured(void* data,
364 const MAGIMAGEHEADER& header) { 338 const MAGIMAGEHEADER& header) {
365 DesktopFrame* current_frame = queue_.current_frame(); 339 DesktopFrame* current_frame = queue_.current_frame();
366 340
367 // Verify the format. 341 // Verify the format.
368 // TODO(jiayl): support capturing sources with pixel formats other than RGBA. 342 // TODO(jiayl): support capturing sources with pixel formats other than RGBA.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 assert(fallback_capturer_); 384 assert(fallback_capturer_);
411 if (!fallback_capturer_started_) { 385 if (!fallback_capturer_started_) {
412 fallback_capturer_started_ = true; 386 fallback_capturer_started_ = true;
413 387
414 fallback_capturer_->Start(callback_); 388 fallback_capturer_->Start(callback_);
415 fallback_capturer_->SelectScreen(current_screen_id_); 389 fallback_capturer_->SelectScreen(current_screen_id_);
416 } 390 }
417 } 391 }
418 392
419 } // namespace webrtc 393 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698