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
--- 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();
}