From 47732c54b61d2c606e974cd21bc6bfe187bb72f2 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Fri, 2 Dec 2022 15:56:24 +0100 Subject: [PATCH] Screencast: properly renegotiate stream when window size changes We need to completely renegotiate stream parameters in case of window size gets changed, otherwise no renegotiation will happen and clients will not accommodate to our changes. Fixes: https://github.com/obsproject/obs-studio/issues/7875 --- src/plugins/screencast/screencaststream.cpp | 22 ++++++++++++++++++++- src/plugins/screencast/screencaststream.h | 3 +++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/plugins/screencast/screencaststream.cpp b/src/plugins/screencast/screencaststream.cpp index 6f76f3713e..1efb0904f5 100644 --- a/src/plugins/screencast/screencaststream.cpp +++ b/src/plugins/screencast/screencaststream.cpp @@ -240,6 +240,8 @@ void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer) } #endif } + + stream->m_waitForNewBuffers = false; } void ScreenCastStream::onStreamRemoveBuffer(void *data, pw_buffer *buffer) @@ -259,6 +261,15 @@ void ScreenCastStream::onStreamRemoveBuffer(void *data, pw_buffer *buffer) } } +void ScreenCastStream::onStreamRenegotiateFormat(void *data, uint64_t) +{ + ScreenCastStream *stream = static_cast(data); + + char buffer[2048]; + auto params = stream->buildFormats(stream->m_dmabufParams.has_value(), buffer); + pw_stream_update_params(stream->pwStream, params.data(), params.count()); +} + ScreenCastStream::ScreenCastStream(ScreenCastSource *source, QObject *parent) : QObject(parent) , m_source(source) @@ -297,6 +308,8 @@ bool ScreenCastStream::init() return false; } + pwRenegotiate = pw_loop_add_event(pwCore.get()->pwMainLoop, onStreamRenegotiateFormat, this); + return true; } @@ -373,10 +386,17 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion) return; } + if (m_waitForNewBuffers) { + qCWarning(KWIN_SCREENCAST) << "Waiting for new buffers to be created"; + return; + } + const auto size = m_source->textureSize(); if (size != m_resolution) { m_resolution = size; - newStreamParams(); + m_waitForNewBuffers = true; + m_dmabufParams = std::nullopt; + pw_loop_signal_event(pwCore.get()->pwMainLoop, pwRenegotiate); return; } diff --git a/src/plugins/screencast/screencaststream.h b/src/plugins/screencast/screencaststream.h index c6483fd8bc..0de382152e 100644 --- a/src/plugins/screencast/screencaststream.h +++ b/src/plugins/screencast/screencaststream.h @@ -74,6 +74,7 @@ private: static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message); static void onStreamAddBuffer(void *data, pw_buffer *buffer); static void onStreamRemoveBuffer(void *data, pw_buffer *buffer); + static void onStreamRenegotiateFormat(void *data, uint64_t); bool createStream(); QVector buildFormats(bool fixate, char buffer[2048]); @@ -92,6 +93,7 @@ private: std::shared_ptr pwCore; std::unique_ptr m_source; struct pw_stream *pwStream = nullptr; + struct spa_source *pwRenegotiate = nullptr; spa_hook streamListener; pw_stream_events pwStreamEvents = {}; @@ -126,6 +128,7 @@ private: std::optional m_start; quint64 m_sequential = 0; bool m_hasDmaBuf = false; + bool m_waitForNewBuffers = false; }; } // namespace KWin