Video capture PipeWire: always capture latest processed buffer

Both CaptureFrame() and ProcessBuffer() hold a lock over the frame queue
and it happens that one waits for the other, causing unnecessary delays
since we already work with a queue having two frames, but this way we
don't really need a queue. Instead, keep reference to the last processed
buffer, which we will always use in CaptureFrame() and update it every
time at the end of ProcessBuffer(). This avoid unnecessary waiting for
the lock over the queue to be released.

Bug: chromium:333945842
Change-Id: I4afeb1daacd342e92578a50ac6e1c89a691bb8f8
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/350042
Commit-Queue: Jan Grulich <grulja@gmail.com>
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#42394}
This commit is contained in:
Jan Grulich 2024-05-14 09:25:39 +02:00 committed by WebRTC LUCI CQ
parent ac4e0b6f46
commit 848980198e

View File

@ -83,6 +83,9 @@ class SharedScreenCastStreamPrivate {
webrtc::Mutex queue_lock_;
ScreenCaptureFrameQueue<SharedDesktopFrame> 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<MouseCursor> mouse_cursor_;
DesktopVector mouse_cursor_position_ = DesktopVector(-1, -1);
@ -603,13 +606,13 @@ void SharedScreenCastStreamPrivate::StopAndCleanupStream() {
std::unique_ptr<SharedDesktopFrame>
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<SharedDesktopFrame>{};
}
std::unique_ptr<SharedDesktopFrame> frame = queue_.current_frame()->Share();
std::unique_ptr<SharedDesktopFrame> 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<SharedDesktopFrame> frame = queue_.current_frame()->Share();
frame->set_capturer_id(DesktopCapturerId::kWaylandCapturerLinux);