OLD | NEW |
---|---|
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 |
(...skipping 17 matching lines...) Expand all Loading... | |
28 | 28 |
29 // kMagnifierWindowClass has to be "Magnifier" according to the Magnification | 29 // kMagnifierWindowClass has to be "Magnifier" according to the Magnification |
30 // API. The other strings can be anything. | 30 // API. The other strings can be anything. |
31 static LPCTSTR kMagnifierHostClass = L"ScreenCapturerWinMagnifierHost"; | 31 static LPCTSTR kMagnifierHostClass = L"ScreenCapturerWinMagnifierHost"; |
32 static LPCTSTR kHostWindowName = L"MagnifierHost"; | 32 static LPCTSTR kHostWindowName = L"MagnifierHost"; |
33 static LPCTSTR kMagnifierWindowClass = L"Magnifier"; | 33 static LPCTSTR kMagnifierWindowClass = L"Magnifier"; |
34 static LPCTSTR kMagnifierWindowName = L"MagnifierWindow"; | 34 static LPCTSTR kMagnifierWindowName = L"MagnifierWindow"; |
35 | 35 |
36 Atomic32 ScreenCapturerWinMagnifier::tls_index_(TLS_OUT_OF_INDEXES); | 36 Atomic32 ScreenCapturerWinMagnifier::tls_index_(TLS_OUT_OF_INDEXES); |
37 | 37 |
38 ScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier( | 38 ScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier() = default; |
39 std::unique_ptr<DesktopCapturer> fallback_capturer) | |
40 : fallback_capturer_(std::move(fallback_capturer)) {} | |
41 | |
42 ScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() { | 39 ScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() { |
43 // DestroyWindow must be called before MagUninitialize. magnifier_window_ is | 40 // DestroyWindow must be called before MagUninitialize. magnifier_window_ is |
44 // destroyed automatically when host_window_ is destroyed. | 41 // destroyed automatically when host_window_ is destroyed. |
45 if (host_window_) | 42 if (host_window_) |
46 DestroyWindow(host_window_); | 43 DestroyWindow(host_window_); |
47 | 44 |
48 if (magnifier_initialized_) | 45 if (magnifier_initialized_) |
49 mag_uninitialize_func_(); | 46 mag_uninitialize_func_(); |
50 | 47 |
51 if (mag_lib_handle_) | 48 if (mag_lib_handle_) |
52 FreeLibrary(mag_lib_handle_); | 49 FreeLibrary(mag_lib_handle_); |
53 | 50 |
54 if (desktop_dc_) | 51 if (desktop_dc_) |
55 ReleaseDC(NULL, desktop_dc_); | 52 ReleaseDC(NULL, desktop_dc_); |
56 } | 53 } |
57 | 54 |
58 void ScreenCapturerWinMagnifier::Start(Callback* callback) { | 55 void ScreenCapturerWinMagnifier::Start(Callback* callback) { |
59 RTC_DCHECK(!callback_); | 56 RTC_DCHECK(!callback_); |
60 RTC_DCHECK(callback); | 57 RTC_DCHECK(callback); |
61 callback_ = callback; | 58 callback_ = callback; |
62 | 59 |
63 if (!InitializeMagnifier()) { | 60 if (!InitializeMagnifier()) { |
64 LOG_F(LS_WARNING) << "Switching to fallback screen capturer becuase " | 61 LOG_F(LS_WARNING) << "Magnifier initialization failed."; |
65 "magnifier initialization failed."; | |
66 StartFallbackCapturer(); | |
67 } | 62 } |
68 } | 63 } |
69 | 64 |
70 void ScreenCapturerWinMagnifier::SetSharedMemoryFactory( | 65 void ScreenCapturerWinMagnifier::SetSharedMemoryFactory( |
71 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { | 66 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { |
72 shared_memory_factory_ = std::move(shared_memory_factory); | 67 shared_memory_factory_ = std::move(shared_memory_factory); |
73 } | 68 } |
74 | 69 |
75 void ScreenCapturerWinMagnifier::CaptureFrame() { | 70 void ScreenCapturerWinMagnifier::CaptureFrame() { |
76 if (!magnifier_initialized_ || | 71 RTC_DCHECK(callback_); |
77 !magnifier_capture_succeeded_ || | 72 if (!magnifier_initialized_) { |
78 GetSystemMetrics(SM_CMONITORS) != 1) { | 73 LOG_F(LS_WARNING) << "Magnifier initialization failed."; |
79 // Do not try to use the magnifier if it failed before and in multi-screen | 74 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); |
80 // setup (where the API crashes sometimes). | |
81 LOG_F(LS_WARNING) << "Switching to the fallback screen capturer because " | |
82 "initialization or last capture attempt failed, or " | |
83 "execute on multi-screen system."; | |
84 StartFallbackCapturer(); | |
85 fallback_capturer_->CaptureFrame(); | |
86 return; | 75 return; |
87 } | 76 } |
88 | 77 |
89 int64_t capture_start_time_nanos = rtc::TimeNanos(); | 78 int64_t capture_start_time_nanos = rtc::TimeNanos(); |
90 | 79 |
91 // Switch to the desktop receiving user input if different from the current | 80 // Switch to the desktop receiving user input if different from the current |
92 // one. | 81 // one. |
93 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); | 82 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); |
94 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { | 83 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { |
95 // Release GDI resources otherwise SetThreadDesktop will fail. | 84 // Release GDI resources otherwise SetThreadDesktop will fail. |
96 if (desktop_dc_) { | 85 if (desktop_dc_) { |
97 ReleaseDC(NULL, desktop_dc_); | 86 ReleaseDC(NULL, desktop_dc_); |
98 desktop_dc_ = NULL; | 87 desktop_dc_ = NULL; |
99 } | 88 } |
100 // If SetThreadDesktop() fails, the thread is still assigned a desktop. | 89 // If SetThreadDesktop() fails, the thread is still assigned a desktop. |
101 // So we can continue capture screen bits, just from the wrong desktop. | 90 // So we can continue capture screen bits, just from the wrong desktop. |
102 desktop_.SetThreadDesktop(input_desktop.release()); | 91 desktop_.SetThreadDesktop(input_desktop.release()); |
103 } | 92 } |
104 | 93 |
105 DesktopRect rect = GetScreenRect(current_screen_id_, current_device_key_); | 94 DesktopRect rect = GetScreenRect(current_screen_id_, current_device_key_); |
106 queue_.MoveToNextFrame(); | 95 queue_.MoveToNextFrame(); |
107 CreateCurrentFrameIfNecessary(rect.size()); | 96 CreateCurrentFrameIfNecessary(rect.size()); |
108 // CaptureImage may fail in some situations, e.g. windows8 metro mode. So | 97 // CaptureImage may fail in some situations, e.g. windows8 metro mode. So |
109 // defer to the fallback capturer if magnifier capturer did not work. | 98 // defer to the fallback capturer if magnifier capturer did not work. |
110 if (!CaptureImage(rect)) { | 99 if (!CaptureImage(rect)) { |
111 LOG_F(LS_WARNING) << "Switching to the fallback screen capturer because " | 100 LOG_F(LS_WARNING) << "Magnifier capturer failed to capture a frame."; |
112 "last capture attempt failed."; | 101 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); |
113 StartFallbackCapturer(); | |
114 fallback_capturer_->CaptureFrame(); | |
115 return; | 102 return; |
116 } | 103 } |
117 | 104 |
118 // Emit the current frame. | 105 // Emit the current frame. |
119 std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share(); | 106 std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share(); |
120 frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX), | 107 frame->set_dpi(DesktopVector(GetDeviceCaps(desktop_dc_, LOGPIXELSX), |
121 GetDeviceCaps(desktop_dc_, LOGPIXELSY))); | 108 GetDeviceCaps(desktop_dc_, LOGPIXELSY))); |
122 frame->mutable_updated_region()->SetRect( | 109 frame->mutable_updated_region()->SetRect( |
123 DesktopRect::MakeSize(frame->size())); | 110 DesktopRect::MakeSize(frame->size())); |
124 frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) / | 111 frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) / |
125 rtc::kNumNanosecsPerMillisec); | 112 rtc::kNumNanosecsPerMillisec); |
126 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); | 113 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); |
127 } | 114 } |
128 | 115 |
129 bool ScreenCapturerWinMagnifier::GetSourceList(SourceList* sources) { | 116 bool ScreenCapturerWinMagnifier::GetSourceList(SourceList* sources) { |
130 return webrtc::GetScreenList(sources); | 117 return webrtc::GetScreenList(sources); |
131 } | 118 } |
132 | 119 |
133 bool ScreenCapturerWinMagnifier::SelectSource(SourceId id) { | 120 bool ScreenCapturerWinMagnifier::SelectSource(SourceId id) { |
134 bool valid = IsScreenValid(id, ¤t_device_key_); | 121 if (IsScreenValid(id, ¤t_device_key_)) { |
122 current_screen_id_ = id; | |
123 return true; | |
124 } | |
135 | 125 |
136 // Set current_screen_id_ even if the fallback capturer is being used, so we | 126 return false; |
137 // can switch back to the magnifier when possible. | |
138 if (valid) | |
139 current_screen_id_ = id; | |
140 | |
141 if (fallback_capturer_started_) | |
142 fallback_capturer_->SelectSource(id); | |
143 | |
144 return valid; | |
145 } | 127 } |
146 | 128 |
147 void ScreenCapturerWinMagnifier::SetExcludedWindow(WindowId excluded_window) { | 129 void ScreenCapturerWinMagnifier::SetExcludedWindow(WindowId excluded_window) { |
148 excluded_window_ = (HWND)excluded_window; | 130 excluded_window_ = (HWND)excluded_window; |
149 if (excluded_window_ && magnifier_initialized_) { | 131 if (excluded_window_ && magnifier_initialized_) { |
150 set_window_filter_list_func_( | 132 set_window_filter_list_func_( |
151 magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_); | 133 magnifier_window_, MW_FILTERMODE_EXCLUDE, 1, &excluded_window_); |
152 } | 134 } |
153 } | 135 } |
154 | 136 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
203 owner->OnCaptured(srcdata, srcheader); | 185 owner->OnCaptured(srcdata, srcheader); |
204 | 186 |
205 return TRUE; | 187 return TRUE; |
206 } | 188 } |
207 | 189 |
208 // TODO(zijiehe): These functions are available on Windows Vista or upper, so we | 190 // TODO(zijiehe): These functions are available on Windows Vista or upper, so we |
209 // do not need to use LoadLibrary and GetProcAddress anymore. Use regular | 191 // do not need to use LoadLibrary and GetProcAddress anymore. Use regular |
210 // include and function calls instead of a dynamical loaded library. | 192 // include and function calls instead of a dynamical loaded library. |
211 bool ScreenCapturerWinMagnifier::InitializeMagnifier() { | 193 bool ScreenCapturerWinMagnifier::InitializeMagnifier() { |
212 RTC_DCHECK(!magnifier_initialized_); | 194 RTC_DCHECK(!magnifier_initialized_); |
195 | |
196 if (GetSystemMetrics(SM_CMONITORS) != 1) { | |
197 // Do not try to use the magnifier if it failed before and in multi-screen | |
Hzj_jie
2017/02/22 19:26:51
Sorry, I forgot to update this comment. Here "if i
| |
198 // setup (where the API crashes sometimes). | |
199 LOG_F(LS_WARNING) << "Magnifier capturer cannot work on multi-screen " | |
200 "system."; | |
201 return false; | |
202 } | |
203 | |
213 desktop_dc_ = GetDC(nullptr); | 204 desktop_dc_ = GetDC(nullptr); |
214 | 205 |
215 mag_lib_handle_ = LoadLibrary(L"Magnification.dll"); | 206 mag_lib_handle_ = LoadLibrary(L"Magnification.dll"); |
216 if (!mag_lib_handle_) | 207 if (!mag_lib_handle_) |
217 return false; | 208 return false; |
218 | 209 |
219 // Initialize Magnification API function pointers. | 210 // Initialize Magnification API function pointers. |
220 mag_initialize_func_ = reinterpret_cast<MagInitializeFunc>( | 211 mag_initialize_func_ = reinterpret_cast<MagInitializeFunc>( |
221 GetProcAddress(mag_lib_handle_, "MagInitialize")); | 212 GetProcAddress(mag_lib_handle_, "MagInitialize")); |
222 mag_uninitialize_func_ = reinterpret_cast<MagUninitializeFunc>( | 213 mag_uninitialize_func_ = reinterpret_cast<MagUninitializeFunc>( |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 if (!queue_.current_frame() || !queue_.current_frame()->size().equals(size)) { | 360 if (!queue_.current_frame() || !queue_.current_frame()->size().equals(size)) { |
370 std::unique_ptr<DesktopFrame> frame = | 361 std::unique_ptr<DesktopFrame> frame = |
371 shared_memory_factory_ | 362 shared_memory_factory_ |
372 ? SharedMemoryDesktopFrame::Create(size, | 363 ? SharedMemoryDesktopFrame::Create(size, |
373 shared_memory_factory_.get()) | 364 shared_memory_factory_.get()) |
374 : std::unique_ptr<DesktopFrame>(new BasicDesktopFrame(size)); | 365 : std::unique_ptr<DesktopFrame>(new BasicDesktopFrame(size)); |
375 queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame))); | 366 queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame))); |
376 } | 367 } |
377 } | 368 } |
378 | 369 |
379 void ScreenCapturerWinMagnifier::StartFallbackCapturer() { | |
380 RTC_DCHECK(fallback_capturer_); | |
381 if (!fallback_capturer_started_) { | |
382 fallback_capturer_started_ = true; | |
383 | |
384 fallback_capturer_->Start(callback_); | |
385 fallback_capturer_->SelectSource(current_screen_id_); | |
386 } | |
387 } | |
388 | |
389 } // namespace webrtc | 370 } // namespace webrtc |
OLD | NEW |