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

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

Issue 1988783003: Use std::unique_ptr<> to pass frame ownership in DesktopCapturer impls. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 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) 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 21 matching lines...) Expand all
32 namespace { 32 namespace {
33 33
34 // Constants from dwmapi.h. 34 // Constants from dwmapi.h.
35 const UINT DWM_EC_DISABLECOMPOSITION = 0; 35 const UINT DWM_EC_DISABLECOMPOSITION = 0;
36 const UINT DWM_EC_ENABLECOMPOSITION = 1; 36 const UINT DWM_EC_ENABLECOMPOSITION = 1;
37 37
38 const wchar_t kDwmapiLibraryName[] = L"dwmapi.dll"; 38 const wchar_t kDwmapiLibraryName[] = L"dwmapi.dll";
39 39
40 } // namespace 40 } // namespace
41 41
42 ScreenCapturerWinGdi::ScreenCapturerWinGdi(const DesktopCaptureOptions& options) 42 ScreenCapturerWinGdi::ScreenCapturerWinGdi(
43 : callback_(NULL), 43 const DesktopCaptureOptions& options) {
44 current_screen_id_(kFullDesktopScreenId),
45 desktop_dc_(NULL),
46 memory_dc_(NULL),
47 dwmapi_library_(NULL),
48 composition_func_(NULL),
49 set_thread_execution_state_failed_(false) {
50 if (options.disable_effects()) { 44 if (options.disable_effects()) {
51 // Load dwmapi.dll dynamically since it is not available on XP. 45 // Load dwmapi.dll dynamically since it is not available on XP.
52 if (!dwmapi_library_) 46 if (!dwmapi_library_)
53 dwmapi_library_ = LoadLibrary(kDwmapiLibraryName); 47 dwmapi_library_ = LoadLibrary(kDwmapiLibraryName);
54 48
55 if (dwmapi_library_) { 49 if (dwmapi_library_) {
56 composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>( 50 composition_func_ = reinterpret_cast<DwmEnableCompositionFunc>(
57 GetProcAddress(dwmapi_library_, "DwmEnableComposition")); 51 GetProcAddress(dwmapi_library_, "DwmEnableComposition"));
58 } 52 }
59 } 53 }
(...skipping 30 matching lines...) Expand all
90 set_thread_execution_state_failed_ = true; 84 set_thread_execution_state_failed_ = true;
91 LOG_F(LS_WARNING) << "Failed to make system & display power assertion: " 85 LOG_F(LS_WARNING) << "Failed to make system & display power assertion: "
92 << GetLastError(); 86 << GetLastError();
93 } 87 }
94 } 88 }
95 89
96 // Make sure the GDI capture resources are up-to-date. 90 // Make sure the GDI capture resources are up-to-date.
97 PrepareCaptureResources(); 91 PrepareCaptureResources();
98 92
99 if (!CaptureImage()) { 93 if (!CaptureImage()) {
100 callback_->OnCaptureCompleted(NULL); 94 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
101 return; 95 return;
102 } 96 }
103 97
104 const DesktopFrame* current_frame = queue_.current_frame(); 98 const DesktopFrame* current_frame = queue_.current_frame();
105 const DesktopFrame* last_frame = queue_.previous_frame(); 99 const DesktopFrame* last_frame = queue_.previous_frame();
106 if (last_frame && last_frame->size().equals(current_frame->size())) { 100 if (last_frame && last_frame->size().equals(current_frame->size())) {
107 // Make sure the differencer is set up correctly for these previous and 101 // Make sure the differencer is set up correctly for these previous and
108 // current screens. 102 // current screens.
109 if (!differ_.get() || 103 if (!differ_.get() ||
110 (differ_->width() != current_frame->size().width()) || 104 (differ_->width() != current_frame->size().width()) ||
(...skipping 12 matching lines...) Expand all
123 helper_.InvalidateRegion(region); 117 helper_.InvalidateRegion(region);
124 } else { 118 } else {
125 // No previous frame is available, or the screen is resized. Invalidate the 119 // No previous frame is available, or the screen is resized. Invalidate the
126 // whole screen. 120 // whole screen.
127 helper_.InvalidateScreen(current_frame->size()); 121 helper_.InvalidateScreen(current_frame->size());
128 } 122 }
129 123
130 helper_.set_size_most_recent(current_frame->size()); 124 helper_.set_size_most_recent(current_frame->size());
131 125
132 // Emit the current frame. 126 // Emit the current frame.
133 DesktopFrame* frame = queue_.current_frame()->Share(); 127 std::unique_ptr<DesktopFrame> frame = queue_.current_frame()->Share();
134 frame->set_dpi(DesktopVector( 128 frame->set_dpi(DesktopVector(
135 GetDeviceCaps(desktop_dc_, LOGPIXELSX), 129 GetDeviceCaps(desktop_dc_, LOGPIXELSX),
136 GetDeviceCaps(desktop_dc_, LOGPIXELSY))); 130 GetDeviceCaps(desktop_dc_, LOGPIXELSY)));
137 frame->mutable_updated_region()->Clear(); 131 frame->mutable_updated_region()->Clear();
138 helper_.TakeInvalidRegion(frame->mutable_updated_region()); 132 helper_.TakeInvalidRegion(frame->mutable_updated_region());
139 frame->set_capture_time_ms( 133 frame->set_capture_time_ms(
140 (rtc::TimeNanos() - capture_start_time_nanos) / 134 (rtc::TimeNanos() - capture_start_time_nanos) /
141 rtc::kNumNanosecsPerMillisec); 135 rtc::kNumNanosecsPerMillisec);
142 callback_->OnCaptureCompleted(frame); 136 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
143 } 137 }
144 138
145 bool ScreenCapturerWinGdi::GetScreenList(ScreenList* screens) { 139 bool ScreenCapturerWinGdi::GetScreenList(ScreenList* screens) {
146 return webrtc::GetScreenList(screens); 140 return webrtc::GetScreenList(screens);
147 } 141 }
148 142
149 bool ScreenCapturerWinGdi::SelectScreen(ScreenId id) { 143 bool ScreenCapturerWinGdi::SelectScreen(ScreenId id) {
150 bool valid = IsScreenValid(id, &current_device_key_); 144 bool valid = IsScreenValid(id, &current_device_key_);
151 if (valid) 145 if (valid)
152 current_screen_id_ = id; 146 current_screen_id_ = id;
(...skipping 10 matching lines...) Expand all
163 // will restore Aero automatically if the process exits. This has no effect 157 // will restore Aero automatically if the process exits. This has no effect
164 // under Windows 8 or higher. See crbug.com/124018. 158 // under Windows 8 or higher. See crbug.com/124018.
165 if (composition_func_) 159 if (composition_func_)
166 (*composition_func_)(DWM_EC_DISABLECOMPOSITION); 160 (*composition_func_)(DWM_EC_DISABLECOMPOSITION);
167 } 161 }
168 162
169 void ScreenCapturerWinGdi::PrepareCaptureResources() { 163 void ScreenCapturerWinGdi::PrepareCaptureResources() {
170 // Switch to the desktop receiving user input if different from the current 164 // Switch to the desktop receiving user input if different from the current
171 // one. 165 // one.
172 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop()); 166 std::unique_ptr<Desktop> input_desktop(Desktop::GetInputDesktop());
173 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 167 if (input_desktop && !desktop_.IsSame(*input_desktop)) {
174 // Release GDI resources otherwise SetThreadDesktop will fail. 168 // Release GDI resources otherwise SetThreadDesktop will fail.
175 if (desktop_dc_) { 169 if (desktop_dc_) {
176 ReleaseDC(NULL, desktop_dc_); 170 ReleaseDC(NULL, desktop_dc_);
177 desktop_dc_ = NULL; 171 desktop_dc_ = nullptr;
178 } 172 }
179 173
180 if (memory_dc_) { 174 if (memory_dc_) {
181 DeleteDC(memory_dc_); 175 DeleteDC(memory_dc_);
182 memory_dc_ = NULL; 176 memory_dc_ = nullptr;
183 } 177 }
184 178
185 // If SetThreadDesktop() fails, the thread is still assigned a desktop. 179 // If SetThreadDesktop() fails, the thread is still assigned a desktop.
186 // So we can continue capture screen bits, just from the wrong desktop. 180 // So we can continue capture screen bits, just from the wrong desktop.
187 desktop_.SetThreadDesktop(input_desktop.release()); 181 desktop_.SetThreadDesktop(input_desktop.release());
188 182
189 // Re-assert our vote to disable Aero. 183 // Re-assert our vote to disable Aero.
190 // See crbug.com/124018 and crbug.com/129906. 184 // See crbug.com/124018 and crbug.com/129906.
191 if (composition_func_ != NULL) { 185 if (composition_func_) {
192 (*composition_func_)(DWM_EC_DISABLECOMPOSITION); 186 (*composition_func_)(DWM_EC_DISABLECOMPOSITION);
193 } 187 }
194 } 188 }
195 189
196 // If the display bounds have changed then recreate GDI resources. 190 // If the display bounds have changed then recreate GDI resources.
197 // TODO(wez): Also check for pixel format changes. 191 // TODO(wez): Also check for pixel format changes.
198 DesktopRect screen_rect(DesktopRect::MakeXYWH( 192 DesktopRect screen_rect(DesktopRect::MakeXYWH(
199 GetSystemMetrics(SM_XVIRTUALSCREEN), 193 GetSystemMetrics(SM_XVIRTUALSCREEN),
200 GetSystemMetrics(SM_YVIRTUALSCREEN), 194 GetSystemMetrics(SM_YVIRTUALSCREEN),
201 GetSystemMetrics(SM_CXVIRTUALSCREEN), 195 GetSystemMetrics(SM_CXVIRTUALSCREEN),
202 GetSystemMetrics(SM_CYVIRTUALSCREEN))); 196 GetSystemMetrics(SM_CYVIRTUALSCREEN)));
203 if (!screen_rect.equals(desktop_dc_rect_)) { 197 if (!screen_rect.equals(desktop_dc_rect_)) {
204 if (desktop_dc_) { 198 if (desktop_dc_) {
205 ReleaseDC(NULL, desktop_dc_); 199 ReleaseDC(NULL, desktop_dc_);
206 desktop_dc_ = NULL; 200 desktop_dc_ = nullptr;
207 } 201 }
208 if (memory_dc_) { 202 if (memory_dc_) {
209 DeleteDC(memory_dc_); 203 DeleteDC(memory_dc_);
210 memory_dc_ = NULL; 204 memory_dc_ = nullptr;
211 } 205 }
212 desktop_dc_rect_ = DesktopRect(); 206 desktop_dc_rect_ = DesktopRect();
213 } 207 }
214 208
215 if (desktop_dc_ == NULL) { 209 if (!desktop_dc_) {
216 assert(memory_dc_ == NULL); 210 assert(!memory_dc_);
217 211
218 // Create GDI device contexts to capture from the desktop into memory. 212 // Create GDI device contexts to capture from the desktop into memory.
219 desktop_dc_ = GetDC(NULL); 213 desktop_dc_ = GetDC(nullptr);
220 if (!desktop_dc_) 214 if (!desktop_dc_)
221 abort(); 215 abort();
222 memory_dc_ = CreateCompatibleDC(desktop_dc_); 216 memory_dc_ = CreateCompatibleDC(desktop_dc_);
223 if (!memory_dc_) 217 if (!memory_dc_)
224 abort(); 218 abort();
225 219
226 desktop_dc_rect_ = screen_rect; 220 desktop_dc_rect_ = screen_rect;
227 221
228 // Make sure the frame buffers will be reallocated. 222 // Make sure the frame buffers will be reallocated.
229 queue_.Reset(); 223 queue_.Reset();
230 224
231 helper_.ClearInvalidRegion(); 225 helper_.ClearInvalidRegion();
232 } 226 }
233 } 227 }
234 228
235 bool ScreenCapturerWinGdi::CaptureImage() { 229 bool ScreenCapturerWinGdi::CaptureImage() {
236 DesktopRect screen_rect = 230 DesktopRect screen_rect =
237 GetScreenRect(current_screen_id_, current_device_key_); 231 GetScreenRect(current_screen_id_, current_device_key_);
238 if (screen_rect.is_empty()) 232 if (screen_rect.is_empty())
239 return false; 233 return false;
240 234
241 DesktopSize size = screen_rect.size(); 235 DesktopSize size = screen_rect.size();
242 // If the current buffer is from an older generation then allocate a new one. 236 // If the current buffer is from an older generation then allocate a new one.
243 // Note that we can't reallocate other buffers at this point, since the caller 237 // Note that we can't reallocate other buffers at this point, since the caller
244 // may still be reading from them. 238 // may still be reading from them.
245 if (!queue_.current_frame() || 239 if (!queue_.current_frame() ||
246 !queue_.current_frame()->size().equals(screen_rect.size())) { 240 !queue_.current_frame()->size().equals(screen_rect.size())) {
247 assert(desktop_dc_ != NULL); 241 assert(desktop_dc_);
248 assert(memory_dc_ != NULL); 242 assert(memory_dc_);
249 243
250 std::unique_ptr<DesktopFrame> buffer(DesktopFrameWin::Create( 244 std::unique_ptr<DesktopFrame> buffer = DesktopFrameWin::Create(
251 size, shared_memory_factory_.get(), desktop_dc_)); 245 size, shared_memory_factory_.get(), desktop_dc_);
252 if (!buffer) 246 if (!buffer)
253 return false; 247 return false;
254 queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(buffer.release())); 248 queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(buffer)));
255 } 249 }
256 250
257 // Select the target bitmap into the memory dc and copy the rect from desktop 251 // Select the target bitmap into the memory dc and copy the rect from desktop
258 // to memory. 252 // to memory.
259 DesktopFrameWin* current = static_cast<DesktopFrameWin*>( 253 DesktopFrameWin* current = static_cast<DesktopFrameWin*>(
260 queue_.current_frame()->GetUnderlyingFrame()); 254 queue_.current_frame()->GetUnderlyingFrame());
261 HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap()); 255 HGDIOBJ previous_object = SelectObject(memory_dc_, current->bitmap());
262 if (previous_object != NULL) { 256 if (previous_object) {
263 BitBlt(memory_dc_, 257 BitBlt(memory_dc_, 0, 0, screen_rect.width(), screen_rect.height(),
264 0, 0, screen_rect.width(), screen_rect.height(), 258 desktop_dc_, screen_rect.left(), screen_rect.top(),
265 desktop_dc_,
266 screen_rect.left(), screen_rect.top(),
267 SRCCOPY | CAPTUREBLT); 259 SRCCOPY | CAPTUREBLT);
268 260
269 // Select back the previously selected object to that the device contect 261 // Select back the previously selected object to that the device contect
270 // could be destroyed independently of the bitmap if needed. 262 // could be destroyed independently of the bitmap if needed.
271 SelectObject(memory_dc_, previous_object); 263 SelectObject(memory_dc_, previous_object);
272 } 264 }
273 return true; 265 return true;
274 } 266 }
275 267
276 } // namespace webrtc 268 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698