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

Side by Side Diff: webrtc/modules/desktop_capture/screen_capturer_mac.mm

Issue 1861893002: Fix screen capturers to initialize on the same thread on which Start() is called. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 8 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) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 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/screen_capturer.h" 11 #include "webrtc/modules/desktop_capture/screen_capturer.h"
12 12
13 #include <stddef.h> 13 #include <stddef.h>
14 14
15 #include <memory> 15 #include <memory>
16 #include <set> 16 #include <set>
17 17
18 #include <ApplicationServices/ApplicationServices.h> 18 #include <ApplicationServices/ApplicationServices.h>
19 #include <Cocoa/Cocoa.h> 19 #include <Cocoa/Cocoa.h>
20 #include <dlfcn.h> 20 #include <dlfcn.h>
21 #include <IOKit/pwr_mgt/IOPMLib.h> 21 #include <IOKit/pwr_mgt/IOPMLib.h>
22 #include <OpenGL/CGLMacro.h> 22 #include <OpenGL/CGLMacro.h>
23 #include <OpenGL/OpenGL.h> 23 #include <OpenGL/OpenGL.h>
24 24
25 #include "webrtc/base/checks.h"
25 #include "webrtc/base/macutils.h" 26 #include "webrtc/base/macutils.h"
27 #include "webrtc/base/thread_checker.h"
26 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" 28 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
27 #include "webrtc/modules/desktop_capture/desktop_frame.h" 29 #include "webrtc/modules/desktop_capture/desktop_frame.h"
28 #include "webrtc/modules/desktop_capture/desktop_geometry.h" 30 #include "webrtc/modules/desktop_capture/desktop_geometry.h"
29 #include "webrtc/modules/desktop_capture/desktop_region.h" 31 #include "webrtc/modules/desktop_capture/desktop_region.h"
30 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" 32 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
31 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h" 33 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
32 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h" 34 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h"
33 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" 35 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
34 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" 36 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h"
35 #include "webrtc/system_wrappers/include/logging.h" 37 #include "webrtc/system_wrappers/include/logging.h"
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 window_bounds, window_list, kCGWindowImageDefault); 183 window_bounds, window_list, kCGWindowImageDefault);
182 } 184 }
183 185
184 // A class to perform video frame capturing for mac. 186 // A class to perform video frame capturing for mac.
185 class ScreenCapturerMac : public ScreenCapturer { 187 class ScreenCapturerMac : public ScreenCapturer {
186 public: 188 public:
187 explicit ScreenCapturerMac( 189 explicit ScreenCapturerMac(
188 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor); 190 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor);
189 virtual ~ScreenCapturerMac(); 191 virtual ~ScreenCapturerMac();
190 192
191 bool Init();
192
193 // Overridden from ScreenCapturer: 193 // Overridden from ScreenCapturer:
194 void Start(Callback* callback) override; 194 void Start(Callback* callback) override;
195 void Capture(const DesktopRegion& region) override; 195 void Capture(const DesktopRegion& region) override;
196 void SetExcludedWindow(WindowId window) override; 196 void SetExcludedWindow(WindowId window) override;
197 bool GetScreenList(ScreenList* screens) override; 197 bool GetScreenList(ScreenList* screens) override;
198 bool SelectScreen(ScreenId id) override; 198 bool SelectScreen(ScreenId id) override;
199 199
200 private: 200 private:
201 bool Initialize();
202
201 void GlBlitFast(const DesktopFrame& frame, 203 void GlBlitFast(const DesktopFrame& frame,
202 const DesktopRegion& region); 204 const DesktopRegion& region);
203 void GlBlitSlow(const DesktopFrame& frame); 205 void GlBlitSlow(const DesktopFrame& frame);
204 void CgBlitPreLion(const DesktopFrame& frame, 206 void CgBlitPreLion(const DesktopFrame& frame,
205 const DesktopRegion& region); 207 const DesktopRegion& region);
206 // Returns false if the selected screen is no longer valid. 208 // Returns false if the selected screen is no longer valid.
207 bool CgBlitPostLion(const DesktopFrame& frame, 209 bool CgBlitPostLion(const DesktopFrame& frame,
208 const DesktopRegion& region); 210 const DesktopRegion& region);
209 211
210 // Called when the screen configuration is changed. 212 // Called when the screen configuration is changed.
(...skipping 10 matching lines...) Expand all
221 const CGRect *rect_array, 223 const CGRect *rect_array,
222 void *user_parameter); 224 void *user_parameter);
223 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta, 225 static void ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta,
224 size_t count, 226 size_t count,
225 const CGRect *rect_array, 227 const CGRect *rect_array,
226 void *user_parameter); 228 void *user_parameter);
227 void ReleaseBuffers(); 229 void ReleaseBuffers();
228 230
229 DesktopFrame* CreateFrame(); 231 DesktopFrame* CreateFrame();
230 232
231 Callback* callback_; 233 rtc::ThreadChecker thread_checker_;
232 234
233 CGLContextObj cgl_context_; 235 Callback* callback_ = nullptr;
236
237 CGLContextObj cgl_context_ = nullptr;
234 ScopedPixelBufferObject pixel_buffer_object_; 238 ScopedPixelBufferObject pixel_buffer_object_;
235 239
236 // Queue of the frames buffers. 240 // Queue of the frames buffers.
237 ScreenCaptureFrameQueue queue_; 241 ScreenCaptureFrameQueue queue_;
238 242
239 // Current display configuration. 243 // Current display configuration.
240 MacDesktopConfiguration desktop_config_; 244 MacDesktopConfiguration desktop_config_;
241 245
242 // Currently selected display, or 0 if the full desktop is selected. On OS X 246 // Currently selected display, or 0 if the full desktop is selected. On OS X
243 // 10.6 and before, this is always 0. 247 // 10.6 and before, this is always 0.
244 CGDirectDisplayID current_display_; 248 CGDirectDisplayID current_display_ = 0;
245 249
246 // The physical pixel bounds of the current screen. 250 // The physical pixel bounds of the current screen.
247 DesktopRect screen_pixel_bounds_; 251 DesktopRect screen_pixel_bounds_;
248 252
249 // The dip to physical pixel scale of the current screen. 253 // The dip to physical pixel scale of the current screen.
250 float dip_to_pixel_scale_; 254 float dip_to_pixel_scale_ = 1.0f;
251 255
252 // A thread-safe list of invalid rectangles, and the size of the most 256 // A thread-safe list of invalid rectangles, and the size of the most
253 // recently captured screen. 257 // recently captured screen.
254 ScreenCapturerHelper helper_; 258 ScreenCapturerHelper helper_;
255 259
256 // Contains an invalid region from the previous capture. 260 // Contains an invalid region from the previous capture.
257 DesktopRegion last_invalid_region_; 261 DesktopRegion last_invalid_region_;
258 262
259 // Monitoring display reconfiguration. 263 // Monitoring display reconfiguration.
260 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor_; 264 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor_;
261 265
262 // Power management assertion to prevent the screen from sleeping. 266 // Power management assertion to prevent the screen from sleeping.
263 IOPMAssertionID power_assertion_id_display_; 267 IOPMAssertionID power_assertion_id_display_ = kIOPMNullAssertionID;
264 268
265 // Power management assertion to indicate that the user is active. 269 // Power management assertion to indicate that the user is active.
266 IOPMAssertionID power_assertion_id_user_; 270 IOPMAssertionID power_assertion_id_user_ = kIOPMNullAssertionID;
267 271
268 // Dynamically link to deprecated APIs for Mac OS X 10.6 support. 272 // Dynamically link to deprecated APIs for Mac OS X 10.6 support.
269 void* app_services_library_; 273 void* app_services_library_ = nullptr;
270 CGDisplayBaseAddressFunc cg_display_base_address_; 274 CGDisplayBaseAddressFunc cg_display_base_address_ = nullptr;
271 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; 275 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_ = nullptr;
272 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; 276 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_ = nullptr;
273 void* opengl_library_; 277 void* opengl_library_ = nullptr;
274 CGLSetFullScreenFunc cgl_set_full_screen_; 278 CGLSetFullScreenFunc cgl_set_full_screen_;
275 279
276 CGWindowID excluded_window_; 280 CGWindowID excluded_window_ = 0;
277 281
278 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac); 282 RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac);
279 }; 283 };
280 284
281 // DesktopFrame wrapper that flips wrapped frame upside down by inverting 285 // DesktopFrame wrapper that flips wrapped frame upside down by inverting
282 // stride. 286 // stride.
283 class InvertedDesktopFrame : public DesktopFrame { 287 class InvertedDesktopFrame : public DesktopFrame {
284 public: 288 public:
285 // Takes ownership of |frame|. 289 // Takes ownership of |frame|.
286 InvertedDesktopFrame(DesktopFrame* frame) 290 InvertedDesktopFrame(DesktopFrame* frame)
287 : DesktopFrame( 291 : DesktopFrame(
288 frame->size(), -frame->stride(), 292 frame->size(), -frame->stride(),
289 frame->data() + (frame->size().height() - 1) * frame->stride(), 293 frame->data() + (frame->size().height() - 1) * frame->stride(),
290 frame->shared_memory()), 294 frame->shared_memory()),
291 original_frame_(frame) { 295 original_frame_(frame) {
292 set_dpi(frame->dpi()); 296 set_dpi(frame->dpi());
293 set_capture_time_ms(frame->capture_time_ms()); 297 set_capture_time_ms(frame->capture_time_ms());
294 mutable_updated_region()->Swap(frame->mutable_updated_region()); 298 mutable_updated_region()->Swap(frame->mutable_updated_region());
295 } 299 }
296 virtual ~InvertedDesktopFrame() {} 300 virtual ~InvertedDesktopFrame() {}
297 301
298 private: 302 private:
299 std::unique_ptr<DesktopFrame> original_frame_; 303 std::unique_ptr<DesktopFrame> original_frame_;
300 304
301 RTC_DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame); 305 RTC_DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame);
302 }; 306 };
303 307
304 ScreenCapturerMac::ScreenCapturerMac( 308 ScreenCapturerMac::ScreenCapturerMac(
305 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor) 309 rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor) {
306 : callback_(NULL), 310 // ScreenCapturer can be used on a thread different from the thread on which
307 cgl_context_(NULL), 311 // it's created.
308 current_display_(0), 312 thread_checker_.DetachFromThread();
Jamie 2016/04/06 01:17:31 Doesn't this belong in Initialize() in that case?
Sergey Ulanov 2016/04/06 21:39:41 ThreadChecker automatically attaches itself in the
Jamie 2016/04/07 00:38:51 Thanks for clarifying. I was confused by the equiv
309 dip_to_pixel_scale_(1.0f),
310 desktop_config_monitor_(desktop_config_monitor),
311 power_assertion_id_display_(kIOPMNullAssertionID),
312 power_assertion_id_user_(kIOPMNullAssertionID),
313 app_services_library_(NULL),
314 cg_display_base_address_(NULL),
315 cg_display_bytes_per_row_(NULL),
316 cg_display_bits_per_pixel_(NULL),
317 opengl_library_(NULL),
318 cgl_set_full_screen_(NULL),
319 excluded_window_(0) {
320 } 313 }
321 314
322 ScreenCapturerMac::~ScreenCapturerMac() { 315 ScreenCapturerMac::~ScreenCapturerMac() {
323 if (power_assertion_id_display_ != kIOPMNullAssertionID) { 316 if (power_assertion_id_display_ != kIOPMNullAssertionID) {
324 IOPMAssertionRelease(power_assertion_id_display_); 317 IOPMAssertionRelease(power_assertion_id_display_);
325 power_assertion_id_display_ = kIOPMNullAssertionID; 318 power_assertion_id_display_ = kIOPMNullAssertionID;
326 } 319 }
327 if (power_assertion_id_user_ != kIOPMNullAssertionID) { 320 if (power_assertion_id_user_ != kIOPMNullAssertionID) {
328 IOPMAssertionRelease(power_assertion_id_user_); 321 IOPMAssertionRelease(power_assertion_id_user_);
329 power_assertion_id_user_ = kIOPMNullAssertionID; 322 power_assertion_id_user_ = kIOPMNullAssertionID;
330 } 323 }
331 324
332 ReleaseBuffers(); 325 ReleaseBuffers();
333 UnregisterRefreshAndMoveHandlers(); 326 UnregisterRefreshAndMoveHandlers();
334 dlclose(app_services_library_); 327 dlclose(app_services_library_);
335 dlclose(opengl_library_); 328 dlclose(opengl_library_);
336 } 329 }
337 330
338 bool ScreenCapturerMac::Init() { 331 bool ScreenCapturerMac::Initialize() {
339 if (!RegisterRefreshAndMoveHandlers()) { 332 if (!RegisterRefreshAndMoveHandlers()) {
340 return false; 333 return false;
341 } 334 }
342 desktop_config_monitor_->Lock(); 335 desktop_config_monitor_->Lock();
343 desktop_config_ = desktop_config_monitor_->desktop_configuration(); 336 desktop_config_ = desktop_config_monitor_->desktop_configuration();
344 desktop_config_monitor_->Unlock(); 337 desktop_config_monitor_->Unlock();
345 ScreenConfigurationChanged(); 338 ScreenConfigurationChanged();
346 return true; 339 return true;
347 } 340 }
348 341
349 void ScreenCapturerMac::ReleaseBuffers() { 342 void ScreenCapturerMac::ReleaseBuffers() {
350 if (cgl_context_) { 343 if (cgl_context_) {
351 pixel_buffer_object_.Release(); 344 pixel_buffer_object_.Release();
352 CGLDestroyContext(cgl_context_); 345 CGLDestroyContext(cgl_context_);
353 cgl_context_ = NULL; 346 cgl_context_ = NULL;
354 } 347 }
355 // The buffers might be in use by the encoder, so don't delete them here. 348 // The buffers might be in use by the encoder, so don't delete them here.
356 // Instead, mark them as "needs update"; next time the buffers are used by 349 // Instead, mark them as "needs update"; next time the buffers are used by
357 // the capturer, they will be recreated if necessary. 350 // the capturer, they will be recreated if necessary.
358 queue_.Reset(); 351 queue_.Reset();
359 } 352 }
360 353
361 void ScreenCapturerMac::Start(Callback* callback) { 354 void ScreenCapturerMac::Start(Callback* callback) {
362 assert(!callback_); 355 RTC_DCHECK(thread_checker_.CalledOnValidThread());
363 assert(callback); 356 RTC_DCHECK(!callback_);
357 RTC_DCHECK(callback);
364 358
365 callback_ = callback; 359 callback_ = callback;
366 360
361 if (!Initialize()) {
362 callback_->OnInitializationFailed();
363 return;
364 }
365
367 // Create power management assertions to wake the display and prevent it from 366 // Create power management assertions to wake the display and prevent it from
368 // going to sleep on user idle. 367 // going to sleep on user idle.
369 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above 368 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above
370 // instead of the following two assertions. 369 // instead of the following two assertions.
371 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, 370 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
372 kIOPMAssertionLevelOn, 371 kIOPMAssertionLevelOn,
373 CFSTR("Chrome Remote Desktop connection active"), 372 CFSTR("Chrome Remote Desktop connection active"),
374 &power_assertion_id_display_); 373 &power_assertion_id_display_);
375 // This assertion ensures that the display is woken up if it already asleep 374 // This assertion ensures that the display is woken up if it already asleep
376 // (as used by Apple Remote Desktop). 375 // (as used by Apple Remote Desktop).
377 IOPMAssertionCreateWithName(CFSTR("UserIsActive"), 376 IOPMAssertionCreateWithName(CFSTR("UserIsActive"),
378 kIOPMAssertionLevelOn, 377 kIOPMAssertionLevelOn,
379 CFSTR("Chrome Remote Desktop connection active"), 378 CFSTR("Chrome Remote Desktop connection active"),
380 &power_assertion_id_user_); 379 &power_assertion_id_user_);
381 } 380 }
382 381
383 void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) { 382 void ScreenCapturerMac::Capture(const DesktopRegion& region_to_capture) {
383 RTC_DCHECK(thread_checker_.CalledOnValidThread());
384
384 TickTime capture_start_time = TickTime::Now(); 385 TickTime capture_start_time = TickTime::Now();
385 386
386 queue_.MoveToNextFrame(); 387 queue_.MoveToNextFrame();
387 388
388 desktop_config_monitor_->Lock(); 389 desktop_config_monitor_->Lock();
389 MacDesktopConfiguration new_config = 390 MacDesktopConfiguration new_config =
390 desktop_config_monitor_->desktop_configuration(); 391 desktop_config_monitor_->desktop_configuration();
391 if (!desktop_config_.Equals(new_config)) { 392 if (!desktop_config_.Equals(new_config)) {
392 desktop_config_ = new_config; 393 desktop_config_ = new_config;
393 // If the display configuraiton has changed then refresh capturer data 394 // If the display configuraiton has changed then refresh capturer data
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 // Signal that we are done capturing data from the display framebuffer, 443 // Signal that we are done capturing data from the display framebuffer,
443 // and accessing display structures. 444 // and accessing display structures.
444 desktop_config_monitor_->Unlock(); 445 desktop_config_monitor_->Unlock();
445 446
446 new_frame->set_capture_time_ms( 447 new_frame->set_capture_time_ms(
447 (TickTime::Now() - capture_start_time).Milliseconds()); 448 (TickTime::Now() - capture_start_time).Milliseconds());
448 callback_->OnCaptureCompleted(new_frame); 449 callback_->OnCaptureCompleted(new_frame);
449 } 450 }
450 451
451 void ScreenCapturerMac::SetExcludedWindow(WindowId window) { 452 void ScreenCapturerMac::SetExcludedWindow(WindowId window) {
453 RTC_DCHECK(thread_checker_.CalledOnValidThread());
452 excluded_window_ = window; 454 excluded_window_ = window;
453 } 455 }
454 456
455 bool ScreenCapturerMac::GetScreenList(ScreenList* screens) { 457 bool ScreenCapturerMac::GetScreenList(ScreenList* screens) {
456 assert(screens->size() == 0); 458 RTC_DCHECK(thread_checker_.CalledOnValidThread());
459 RTC_DCHECK(screens->size() == 0);
460
457 if (rtc::GetOSVersionName() < rtc::kMacOSLion) { 461 if (rtc::GetOSVersionName() < rtc::kMacOSLion) {
458 // Single monitor cast is not supported on pre OS X 10.7. 462 // Single monitor cast is not supported on pre OS X 10.7.
459 Screen screen; 463 Screen screen;
460 screen.id = kFullDesktopScreenId; 464 screen.id = kFullDesktopScreenId;
461 screens->push_back(screen); 465 screens->push_back(screen);
462 return true; 466 return true;
463 } 467 }
464 468
465 for (MacDisplayConfigurations::iterator it = desktop_config_.displays.begin(); 469 for (MacDisplayConfigurations::iterator it = desktop_config_.displays.begin();
466 it != desktop_config_.displays.end(); ++it) { 470 it != desktop_config_.displays.end(); ++it) {
467 Screen screen; 471 Screen screen;
468 screen.id = static_cast<ScreenId>(it->id); 472 screen.id = static_cast<ScreenId>(it->id);
469 screens->push_back(screen); 473 screens->push_back(screen);
470 } 474 }
471 return true; 475 return true;
472 } 476 }
473 477
474 bool ScreenCapturerMac::SelectScreen(ScreenId id) { 478 bool ScreenCapturerMac::SelectScreen(ScreenId id) {
479 RTC_DCHECK(thread_checker_.CalledOnValidThread());
480
475 if (rtc::GetOSVersionName() < rtc::kMacOSLion) { 481 if (rtc::GetOSVersionName() < rtc::kMacOSLion) {
476 // Ignore the screen selection on unsupported OS. 482 // Ignore the screen selection on unsupported OS.
477 assert(!current_display_); 483 assert(!current_display_);
478 return id == kFullDesktopScreenId; 484 return id == kFullDesktopScreenId;
479 } 485 }
480 486
481 if (id == kFullDesktopScreenId) { 487 if (id == kFullDesktopScreenId) {
482 current_display_ = 0; 488 current_display_ = 0;
483 } else { 489 } else {
484 const MacDisplayConfiguration* config = 490 const MacDisplayConfiguration* config =
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 return frame.release(); 979 return frame.release();
974 } 980 }
975 981
976 } // namespace 982 } // namespace
977 983
978 // static 984 // static
979 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) { 985 ScreenCapturer* ScreenCapturer::Create(const DesktopCaptureOptions& options) {
980 if (!options.configuration_monitor()) 986 if (!options.configuration_monitor())
981 return NULL; 987 return NULL;
982 988
983 std::unique_ptr<ScreenCapturerMac> capturer( 989 return new ScreenCapturerMac(options.configuration_monitor());
984 new ScreenCapturerMac(options.configuration_monitor()));
985 if (!capturer->Init())
986 capturer.reset();
987 return capturer.release();
988 } 990 }
989 991
990 } // namespace webrtc 992 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/desktop_capture/desktop_capturer.h ('k') | webrtc/modules/desktop_capture/screen_capturer_x11.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698