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

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

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