Bug 1409018 - Defer RegisterRefreshAndMoveHandlers call; r?pehrsons draft
authorDan Minor <dminor@mozilla.com>
Tue, 05 Jun 2018 08:13:01 -0400
changeset 807072 d87cd71811071441609b840d28fc6160b1483738
parent 807071 db59e01d00d021baf4f7a4b6bddffba702119508
child 807073 bb6477b50fc9598f4b14d216ffa049dc4ccbfc55
push id113037
push userbmo:dminor@mozilla.com
push dateWed, 13 Jun 2018 19:42:21 +0000
reviewerspehrsons
bugs1409018
milestone62.0a1
Bug 1409018 - Defer RegisterRefreshAndMoveHandlers call; r?pehrsons This defers the call to register the refresh and move handlers to the CaptureFrame() call so that they will be registered on the ScreenCapture thread. This also calls CFRunLoopInMode to process any pending sources in the run loop corresponding to the ScreenCapture thread so that the refresh and move notifications are received. MozReview-Commit-ID: G4aEchnGuUz
media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_mac.mm
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_mac.mm
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_mac.mm
@@ -358,16 +358,23 @@ class ScreenCapturerMac : public Desktop
   CGLSetFullScreenFunc cgl_set_full_screen_ = nullptr;
 
   CGWindowID excluded_window_ = 0;
 
   // A self-owned object that will destroy itself after ScreenCapturerMac and
   // all display streams have been destroyed..
   DisplayStreamManager* display_stream_manager_;
 
+  // Used to force CaptureFrame to update it's screen configuration
+  // and reregister event handlers. This ensure that this
+  // occurs on the ScreenCapture thread. Read and written from
+  // both the VideoCapture thread and ScreenCapture thread.
+  // Protected by desktop_config_monitor_.
+  bool update_screen_configuration_ = false;
+
   RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac);
 };
 
 // DesktopFrame wrapper that flips wrapped frame upside down by inverting
 // stride.
 class InvertedDesktopFrame : public DesktopFrame {
  public:
   InvertedDesktopFrame(std::unique_ptr<DesktopFrame> frame)
@@ -398,23 +405,32 @@ ScreenCapturerMac::ScreenCapturerMac(
 ScreenCapturerMac::~ScreenCapturerMac() {
   ReleaseBuffers();
   display_stream_manager_->PrepareForSelfDestruction();
   dlclose(app_services_library_);
   dlclose(opengl_library_);
 }
 
 bool ScreenCapturerMac::Init() {
+// MOZILLA: Calling RegisterRefreshAndMoveHandlers here causes us
+// to register on the VideoCapture thread rather than the ScreenCapture
+// thread which will result in us never receiving any notifications.
+// See Bug 1468509.
+/*
   desktop_config_monitor_->Lock();
   desktop_config_ = desktop_config_monitor_->desktop_configuration();
   desktop_config_monitor_->Unlock();
   if (!RegisterRefreshAndMoveHandlers()) {
     return false;
   }
   ScreenConfigurationChanged();
+*/
+  desktop_config_monitor_->Lock();
+  update_screen_configuration_ = true;
+  desktop_config_monitor_->Unlock();
   return true;
 }
 
 void ScreenCapturerMac::ReleaseBuffers() {
   if (cgl_context_) {
     pixel_buffer_object_.Release();
     CGLDestroyContext(cgl_context_);
     cgl_context_ = nullptr;
@@ -425,16 +441,19 @@ void ScreenCapturerMac::ReleaseBuffers()
   queue_.Reset();
 }
 
 void ScreenCapturerMac::Start(Callback* callback) {
   assert(!callback_);
   assert(callback);
 
   callback_ = callback;
+  desktop_config_monitor_->Lock();
+  update_screen_configuration_ = true;
+  desktop_config_monitor_->Unlock();
 }
 
 void ScreenCapturerMac::Stop() {
   if (power_assertion_id_display_ != kIOPMNullAssertionID) {
     IOPMAssertionRelease(power_assertion_id_display_);
     power_assertion_id_display_ = kIOPMNullAssertionID;
   }
   if (power_assertion_id_user_ != kIOPMNullAssertionID) {
@@ -443,23 +462,27 @@ void ScreenCapturerMac::Stop() {
   }
 
   callback_ = NULL;
 }
 
 void ScreenCapturerMac::CaptureFrame() {
   int64_t capture_start_time_nanos = rtc::TimeNanos();
 
+  // Spin RunLoop for 1/100th of a second, handling at most one source
+  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, true);
+
   queue_.MoveToNextFrame();
   RTC_DCHECK(!queue_.current_frame() || !queue_.current_frame()->IsShared());
 
   desktop_config_monitor_->Lock();
   MacDesktopConfiguration new_config =
       desktop_config_monitor_->desktop_configuration();
-  if (!desktop_config_.Equals(new_config)) {
+  if (update_screen_configuration_ || !desktop_config_.Equals(new_config)) {
+    update_screen_configuration_ = false;
     desktop_config_ = new_config;
     // If the display configuraiton has changed then refresh capturer data
     // structures. Occasionally, the refresh and move handlers are lost when
     // the screen mode changes, so re-register them here.
     UnregisterRefreshAndMoveHandlers();
     RegisterRefreshAndMoveHandlers();
     ScreenConfigurationChanged();
   }