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

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

Issue 2319383002: Several minor changes to ScreenCapturerWinMagnifier (Closed)
Patch Set: Add TODO to use include & regular function calls to replace dynamical loaded library 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
« no previous file with comments | « webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 24 matching lines...) Expand all
51 mag_uninitialize_func_(); 50 mag_uninitialize_func_();
52 51
53 if (mag_lib_handle_) 52 if (mag_lib_handle_)
54 FreeLibrary(mag_lib_handle_); 53 FreeLibrary(mag_lib_handle_);
55 54
56 if (desktop_dc_) 55 if (desktop_dc_)
57 ReleaseDC(NULL, desktop_dc_); 56 ReleaseDC(NULL, desktop_dc_);
58 } 57 }
59 58
60 void ScreenCapturerWinMagnifier::Start(Callback* callback) { 59 void ScreenCapturerWinMagnifier::Start(Callback* callback) {
61 assert(!callback_); 60 RTC_DCHECK(!callback_);
62 assert(callback); 61 RTC_DCHECK(callback);
63 callback_ = callback; 62 callback_ = callback;
64 63
65 InitializeMagnifier(); 64 if (!InitializeMagnifier()) {
65 LOG_F(LS_WARNING) << "Switching to fallback screen capturer becuase "
66 "magnifier initialization failed.";
67 StartFallbackCapturer();
68 }
66 } 69 }
67 70
68 void ScreenCapturerWinMagnifier::SetSharedMemoryFactory( 71 void ScreenCapturerWinMagnifier::SetSharedMemoryFactory(
69 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { 72 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) {
70 shared_memory_factory_ = std::move(shared_memory_factory); 73 shared_memory_factory_ = std::move(shared_memory_factory);
71 } 74 }
72 75
73 void ScreenCapturerWinMagnifier::Capture(const DesktopRegion& region) { 76 void ScreenCapturerWinMagnifier::Capture(const DesktopRegion& region) {
77 if (!magnifier_initialized_ ||
78 !magnifier_capture_succeeded_ ||
79 GetSystemMetrics(SM_CMONITORS) != 1) {
80 // Do not try to use the magnifier if it failed before and in multi-screen
81 // setup (where the API crashes sometimes).
82 LOG_F(LS_WARNING) << "Switching to the fallback screen capturer because "
83 "initialization or last capture attempt failed, or "
84 "execute on multi-screen system.";
85 StartFallbackCapturer();
86 fallback_capturer_->Capture(region);
87 return;
88 }
89
74 int64_t capture_start_time_nanos = rtc::TimeNanos(); 90 int64_t capture_start_time_nanos = rtc::TimeNanos();
75 91
76 queue_.MoveToNextFrame();
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 92 // Switch to the desktop receiving user input if different from the current
87 // one. 93 // one.
88 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); 94 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop());
89 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 95 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) {
90 // Release GDI resources otherwise SetThreadDesktop will fail. 96 // Release GDI resources otherwise SetThreadDesktop will fail.
91 if (desktop_dc_) { 97 if (desktop_dc_) {
92 ReleaseDC(NULL, desktop_dc_); 98 ReleaseDC(NULL, desktop_dc_);
93 desktop_dc_ = NULL; 99 desktop_dc_ = NULL;
94 } 100 }
95 // If SetThreadDesktop() fails, the thread is still assigned a desktop. 101 // If SetThreadDesktop() fails, the thread is still assigned a desktop.
96 // So we can continue capture screen bits, just from the wrong desktop. 102 // So we can continue capture screen bits, just from the wrong desktop.
97 desktop_.SetThreadDesktop(input_desktop.release()); 103 desktop_.SetThreadDesktop(input_desktop.release());
98 } 104 }
99 105
100 bool succeeded = false; 106 DesktopRect rect = GetScreenRect(current_screen_id_, current_device_key_);
101 107 queue_.MoveToNextFrame();
102 // Do not try to use the magnifier if it failed before and in multi-screen 108 CreateCurrentFrameIfNecessary(rect.size());
103 // setup (where the API crashes sometimes). 109 // CaptureImage may fail in some situations, e.g. windows8 metro mode. So
104 if (magnifier_initialized_ && (GetSystemMetrics(SM_CMONITORS) == 1) && 110 // defer to the fallback capturer if magnifier capturer did not work.
105 magnifier_capture_succeeded_) { 111 if (!CaptureImage(rect)) {
106 DesktopRect rect = GetScreenRect(current_screen_id_, current_device_key_); 112 LOG_F(LS_WARNING) << "Switching to the fallback screen capturer because "
107 CreateCurrentFrameIfNecessary(rect.size()); 113 "last capture attempt failed.";
108
109 // CaptureImage may fail in some situations, e.g. windows8 metro mode.
110 succeeded = CaptureImage(rect);
111 }
112
113 // Defer to the fallback capturer if magnifier capturer did not work.
114 if (!succeeded) {
115 LOG_F(LS_WARNING) << "Switching to the fallback screen capturer.";
116 StartFallbackCapturer(); 114 StartFallbackCapturer();
117 fallback_capturer_->Capture(region); 115 fallback_capturer_->Capture(region);
118 return; 116 return;
119 } 117 }
120 118
121 const DesktopFrame* current_frame = queue_.current_frame(); 119 const DesktopFrame* current_frame = queue_.current_frame();
122 const DesktopFrame* last_frame = queue_.previous_frame(); 120 const DesktopFrame* last_frame = queue_.previous_frame();
121 DesktopRegion updated_region;
123 if (last_frame && last_frame->size().equals(current_frame->size())) { 122 if (last_frame && last_frame->size().equals(current_frame->size())) {
124 // Make sure the differencer is set up correctly for these previous and 123 // Make sure the differencer is set up correctly for these previous and
125 // current screens. 124 // current screens.
126 if (!differ_.get() || (differ_->width() != current_frame->size().width()) || 125 if (!differ_.get() || (differ_->width() != current_frame->size().width()) ||
127 (differ_->height() != current_frame->size().height()) || 126 (differ_->height() != current_frame->size().height()) ||
128 (differ_->bytes_per_row() != current_frame->stride())) { 127 (differ_->bytes_per_row() != current_frame->stride())) {
129 differ_.reset(new Differ(current_frame->size().width(), 128 differ_.reset(new Differ(current_frame->size().width(),
130 current_frame->size().height(), 129 current_frame->size().height(),
131 DesktopFrame::kBytesPerPixel, 130 DesktopFrame::kBytesPerPixel,
132 current_frame->stride())); 131 current_frame->stride()));
133 } 132 }
134 133
135 // Calculate difference between the two last captured frames. 134 // Calculate difference between the two last captured frames.
136 DesktopRegion region;
137 differ_->CalcDirtyRegion( 135 differ_->CalcDirtyRegion(
138 last_frame->data(), current_frame->data(), &region); 136 last_frame->data(), current_frame->data(), &updated_region);
139 helper_.InvalidateRegion(region);
140 } else { 137 } else {
141 // No previous frame is available, or the screen is resized. Invalidate the 138 updated_region.SetRect(DesktopRect::MakeSize(current_frame->size()));
142 // whole screen.
143 helper_.InvalidateScreen(current_frame->size());
144 } 139 }
145 140
146 helper_.set_size_most_recent(current_frame->size());
147
148 // Emit the current frame. 141 // Emit the current frame.
149 std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share(); 142 std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share();
150 frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX), 143 frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX),
151 GetDeviceCaps(desktop_dc_, LOGPIXELSY))); 144 GetDeviceCaps(desktop_dc_, LOGPIXELSY)));
152 frame->mutable_updated_region()->Clear(); 145 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) / 146 frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) /
155 rtc::kNumNanosecsPerMillisec); 147 rtc::kNumNanosecsPerMillisec);
156 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); 148 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
157 } 149 }
158 150
159 bool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) { 151 bool ScreenCapturerWinMagnifier::GetScreenList(ScreenList* screens) {
160 return webrtc::GetScreenList(screens); 152 return webrtc::GetScreenList(screens);
161 } 153 }
162 154
163 bool ScreenCapturerWinMagnifier::SelectScreen(ScreenId id) { 155 bool ScreenCapturerWinMagnifier::SelectScreen(ScreenId id) {
(...skipping 12 matching lines...) Expand all
176 168
177 void ScreenCapturerWinMagnifier::SetExcludedWindow(WindowId excluded_window) { 169 void ScreenCapturerWinMagnifier::SetExcludedWindow(WindowId excluded_window) {
178 excluded_window_ = (HWND)excluded_window; 170 excluded_window_ = (HWND)excluded_window;
179 if (excluded_window_ && magnifier_initialized_) { 171 if (excluded_window_ && magnifier_initialized_) {
180 set_window_filter_list_func_( 172 set_window_filter_list_func_(
181 magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_); 173 magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_);
182 } 174 }
183 } 175 }
184 176
185 bool ScreenCapturerWinMagnifier::CaptureImage(const DesktopRect& rect) { 177 bool ScreenCapturerWinMagnifier::CaptureImage(const DesktopRect& rect) {
186 assert(magnifier_initialized_); 178 RTC_DCHECK(magnifier_initialized_);
187 179
188 // Set the magnifier control to cover the captured rect. The content of the 180 // Set the magnifier control to cover the captured rect. The content of the
189 // magnifier control will be the captured image. 181 // magnifier control will be the captured image.
190 BOOL result = SetWindowPos(magnifier_window_, NULL, rect.left(), rect.top(), 182 BOOL result = SetWindowPos(magnifier_window_, NULL, rect.left(), rect.top(),
191 rect.width(), rect.height(), 0); 183 rect.width(), rect.height(), 0);
192 if (!result) { 184 if (!result) {
193 LOG_F(LS_WARNING) << "Failed to call SetWindowPos: " << GetLastError() 185 LOG_F(LS_WARNING) << "Failed to call SetWindowPos: " << GetLastError()
194 << ". Rect = {" << rect.left() << ", " << rect.top() 186 << ". Rect = {" << rect.left() << ", " << rect.top()
195 << ", " << rect.right() << ", " << rect.bottom() << "}"; 187 << ", " << rect.right() << ", " << rect.bottom() << "}";
196 return false; 188 return false;
197 } 189 }
198 190
199 magnifier_capture_succeeded_ = false; 191 magnifier_capture_succeeded_ = false;
200 192
201 RECT native_rect = {rect.left(), rect.top(), rect.right(), rect.bottom()}; 193 RECT native_rect = {rect.left(), rect.top(), rect.right(), rect.bottom()};
202 194
195 RTC_DCHECK(tls_index_.Value() != static_cast<int32_t>(TLS_OUT_OF_INDEXES));
196 TlsSetValue(tls_index_.Value(), this);
203 // OnCaptured will be called via OnMagImageScalingCallback and fill in the 197 // OnCaptured will be called via OnMagImageScalingCallback and fill in the
204 // frame before set_window_source_func_ returns. 198 // frame before set_window_source_func_ returns.
205 result = set_window_source_func_(magnifier_window_, native_rect); 199 result = set_window_source_func_(magnifier_window_, native_rect);
206 200
207 if (!result) { 201 if (!result) {
208 LOG_F(LS_WARNING) << "Failed to call MagSetWindowSource: " << GetLastError() 202 LOG_F(LS_WARNING) << "Failed to call MagSetWindowSource: " << GetLastError()
209 << ". Rect = {" << rect.left() << ", " << rect.top() 203 << ". Rect = {" << rect.left() << ", " << rect.top()
210 << ", " << rect.right() << ", " << rect.bottom() << "}"; 204 << ", " << rect.right() << ", " << rect.bottom() << "}";
211 return false; 205 return false;
212 } 206 }
213 207
214 return magnifier_capture_succeeded_; 208 return magnifier_capture_succeeded_;
215 } 209 }
216 210
217 BOOL ScreenCapturerWinMagnifier::OnMagImageScalingCallback( 211 BOOL ScreenCapturerWinMagnifier::OnMagImageScalingCallback(
218 HWND hwnd, 212 HWND hwnd,
219 void* srcdata, 213 void* srcdata,
220 MAGIMAGEHEADER srcheader, 214 MAGIMAGEHEADER srcheader,
221 void* destdata, 215 void* destdata,
222 MAGIMAGEHEADER destheader, 216 MAGIMAGEHEADER destheader,
223 RECT unclipped, 217 RECT unclipped,
224 RECT clipped, 218 RECT clipped,
225 HRGN dirty) { 219 HRGN dirty) {
226 assert(tls_index_.Value() != static_cast<int32_t>(TLS_OUT_OF_INDEXES)); 220 RTC_DCHECK(tls_index_.Value() != static_cast<int32_t>(TLS_OUT_OF_INDEXES));
227
228 ScreenCapturerWinMagnifier* owner = 221 ScreenCapturerWinMagnifier* owner =
229 reinterpret_cast<ScreenCapturerWinMagnifier*>( 222 reinterpret_cast<ScreenCapturerWinMagnifier*>(
230 TlsGetValue(tls_index_.Value())); 223 TlsGetValue(tls_index_.Value()));
231 224 TlsSetValue(tls_index_.Value(), nullptr);
232 owner->OnCaptured(srcdata, srcheader); 225 owner->OnCaptured(srcdata, srcheader);
233 226
234 return TRUE; 227 return TRUE;
235 } 228 }
236 229
230 // TODO(zijiehe): These functions are available on Windows Vista or upper, so we
231 // do not need to use LoadLibrary and GetProcAddress anymore. Use regular
232 // include and function calls instead of a dynamical loaded library.
237 bool ScreenCapturerWinMagnifier::InitializeMagnifier() { 233 bool ScreenCapturerWinMagnifier::InitializeMagnifier() {
238 assert(!magnifier_initialized_); 234 RTC_DCHECK(!magnifier_initialized_);
239
240 desktop_dc_ = GetDC(nullptr); 235 desktop_dc_ = GetDC(nullptr);
241 236
242 mag_lib_handle_ = LoadLibrary(L"Magnification.dll"); 237 mag_lib_handle_ = LoadLibrary(L"Magnification.dll");
243 if (!mag_lib_handle_) 238 if (!mag_lib_handle_)
244 return false; 239 return false;
245 240
246 // Initialize Magnification API function pointers. 241 // Initialize Magnification API function pointers.
247 mag_initialize_func_ = reinterpret_cast<MagInitializeFunc>( 242 mag_initialize_func_ = reinterpret_cast<MagInitializeFunc>(
248 GetProcAddress(mag_lib_handle_, "MagInitialize")); 243 GetProcAddress(mag_lib_handle_, "MagInitialize"));
249 mag_uninitialize_func_ = reinterpret_cast<MagUninitializeFunc>( 244 mag_uninitialize_func_ = reinterpret_cast<MagUninitializeFunc>(
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 } 341 }
347 342
348 if (tls_index_.Value() == static_cast<int32_t>(TLS_OUT_OF_INDEXES)) { 343 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 344 // More than one threads may get here at the same time, but only one will
350 // write to tls_index_ using CompareExchange. 345 // write to tls_index_ using CompareExchange.
351 DWORD new_tls_index = TlsAlloc(); 346 DWORD new_tls_index = TlsAlloc();
352 if (!tls_index_.CompareExchange(new_tls_index, TLS_OUT_OF_INDEXES)) 347 if (!tls_index_.CompareExchange(new_tls_index, TLS_OUT_OF_INDEXES))
353 TlsFree(new_tls_index); 348 TlsFree(new_tls_index);
354 } 349 }
355 350
356 assert(tls_index_.Value() != static_cast<int32_t>(TLS_OUT_OF_INDEXES));
357 TlsSetValue(tls_index_.Value(), this);
358
359 magnifier_initialized_ = true; 351 magnifier_initialized_ = true;
360 return true; 352 return true;
361 } 353 }
362 354
363 void ScreenCapturerWinMagnifier::OnCaptured(void* data, 355 void ScreenCapturerWinMagnifier::OnCaptured(void* data,
364 const MAGIMAGEHEADER& header) { 356 const MAGIMAGEHEADER& header) {
365 DesktopFrame* current_frame = queue_.current_frame(); 357 DesktopFrame* current_frame = queue_.current_frame();
366 358
367 // Verify the format. 359 // Verify the format.
368 // TODO(jiayl): support capturing sources with pixel formats other than RGBA. 360 // TODO(jiayl): support capturing sources with pixel formats other than RGBA.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 std::unique_ptr<DesktopFrame> frame = 392 std::unique_ptr<DesktopFrame> frame =
401 shared_memory_factory_ 393 shared_memory_factory_
402 ? SharedMemoryDesktopFrame::Create(size, 394 ? SharedMemoryDesktopFrame::Create(size,
403 shared_memory_factory_.get()) 395 shared_memory_factory_.get())
404 : std::unique_ptr<DesktopFrame>(new BasicDesktopFrame(size)); 396 : std::unique_ptr<DesktopFrame>(new BasicDesktopFrame(size));
405 queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame))); 397 queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame)));
406 } 398 }
407 } 399 }
408 400
409 void ScreenCapturerWinMagnifier::StartFallbackCapturer() { 401 void ScreenCapturerWinMagnifier::StartFallbackCapturer() {
410 assert(fallback_capturer_); 402 RTC_DCHECK(fallback_capturer_);
411 if (!fallback_capturer_started_) { 403 if (!fallback_capturer_started_) {
412 fallback_capturer_started_ = true; 404 fallback_capturer_started_ = true;
413 405
414 fallback_capturer_->Start(callback_); 406 fallback_capturer_->Start(callback_);
415 fallback_capturer_->SelectScreen(current_screen_id_); 407 fallback_capturer_->SelectScreen(current_screen_id_);
416 } 408 }
417 } 409 }
418 410
419 } // namespace webrtc 411 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698