diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc index 4e042ef79e..15f9b1e55f 100644 --- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc +++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc @@ -83,6 +83,9 @@ class SharedScreenCastStreamPrivate { webrtc::Mutex queue_lock_; ScreenCaptureFrameQueue queue_ RTC_GUARDED_BY(&queue_lock_); + webrtc::Mutex latest_frame_lock_; + SharedDesktopFrame* latest_available_frame_ + RTC_GUARDED_BY(&latest_frame_lock_) = nullptr; std::unique_ptr mouse_cursor_; DesktopVector mouse_cursor_position_ = DesktopVector(-1, -1); @@ -603,13 +606,13 @@ void SharedScreenCastStreamPrivate::StopAndCleanupStream() { std::unique_ptr SharedScreenCastStreamPrivate::CaptureFrame() { - webrtc::MutexLock lock(&queue_lock_); + webrtc::MutexLock latest_frame_lock(&latest_frame_lock_); - if (!pw_stream_ || !queue_.current_frame()) { + if (!pw_stream_ || !latest_available_frame_) { return std::unique_ptr{}; } - std::unique_ptr frame = queue_.current_frame()->Share(); + std::unique_ptr frame = latest_available_frame_->Share(); if (use_damage_region_) { frame->mutable_updated_region()->Swap(&damage_region_); damage_region_.Clear(); @@ -842,6 +845,8 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { if (observer_) { observer_->OnFailedToProcessBuffer(); } + webrtc::MutexLock latest_frame_lock(&latest_frame_lock_); + latest_available_frame_ = nullptr; return; } @@ -860,9 +865,16 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { observer_->OnDesktopFrameChanged(); } + // We have to hold the lock over the latest_frame here already, since + // we are going to update damage region, which corresponds to the latest + // frame and is accessed in CaptureFrame() + webrtc::MutexLock latest_frame_lock(&latest_frame_lock_); + UpdateFrameUpdatedRegions(spa_buffer, *queue_.current_frame()); queue_.current_frame()->set_may_contain_cursor(is_cursor_embedded_); + latest_available_frame_ = queue_.current_frame(); + if (callback_) { std::unique_ptr frame = queue_.current_frame()->Share(); frame->set_capturer_id(DesktopCapturerId::kWaylandCapturerLinux);