Browse Source

Use native portal capture for Wayland broadcasts

master
evgeny 2 days ago
parent
commit
44c9c3bcaf
  1. 8
      tools/chatgui/CMakeLists.txt
  2. 24
      tools/chatgui/src/stream_publish_engine.cpp
  3. 4
      tools/chatgui/src/stream_publish_window.cpp

8
tools/chatgui/CMakeLists.txt

@ -196,6 +196,14 @@ if(QT_PACKAGE STREQUAL "Qt6" AND FFMPEG_FOUND)
endif()
endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/chatgui_capture_enabled.txt" "${GUI_CAPTURE_ENABLED}\n")
if(GUI_CAPTURE_ENABLED AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_package(Qt6 COMPONENTS DBus REQUIRED)
pkg_check_modules(STREAM_PIPEWIRE REQUIRED IMPORTED_TARGET libpipewire-0.3>=0.3.44)
add_library(chatgui_portal_capture STATIC src/stream_portal_capture.cpp)
target_link_libraries(chatgui_portal_capture PUBLIC Qt6::Multimedia Qt6::DBus PRIVATE utun PkgConfig::STREAM_PIPEWIRE)
target_compile_definitions(chatgui_stream_publish PUBLIC UTUN_STREAM_PORTAL)
target_link_libraries(chatgui_stream_publish PRIVATE chatgui_portal_capture)
endif()
if(GUI_CAPTURE_ENABLED AND UNIX AND NOT APPLE AND QT_FEATURE_xcb)
find_package(X11 REQUIRED COMPONENTS Xfixes)
target_sources(chatgui_stream_publish PRIVATE src/stream_screen_cursor.cpp)

24
tools/chatgui/src/stream_publish_engine.cpp

@ -34,6 +34,9 @@ extern "C" {
#ifdef UTUN_STREAM_X11_CURSOR
#include "stream_screen_cursor.h"
#endif
#ifdef UTUN_STREAM_PORTAL
#include "stream_portal_capture.h"
#endif
namespace {
int64_t monotonicUs() { return std::chrono::duration_cast<std::chrono::microseconds>(
@ -77,6 +80,9 @@ struct StreamPublishEngine::Impl {
std::unique_ptr<QVideoSink> sink;
std::unique_ptr<QCamera> camera;
std::unique_ptr<QScreenCapture> screen;
#ifdef UTUN_STREAM_PORTAL
std::unique_ptr<StreamPortalCapture> portal;
#endif
std::unique_ptr<QTimer> screenGrabTimer;
#ifdef UTUN_STREAM_X11_CURSOR
std::unique_ptr<StreamScreenCursor> cursor;
@ -148,6 +154,9 @@ QVariant StreamPublishEngine::previewFrame() const {
}
QList<int> StreamPublishEngine::codecs() const { std::lock_guard<std::mutex> guard(m->lock); return m->codecs; }
bool StreamPublishEngine::cursorSupported(const StreamVideoSource& source) {
#ifdef UTUN_STREAM_PORTAL
if (source.kind == StreamVideoSource::Screen && source.id == "portal") return true;
#endif
#ifdef UTUN_STREAM_X11_CURSOR
return source.kind == StreamVideoSource::Screen && source.screen && source.id != "portal" && QGuiApplication::platformName() == "xcb";
#else
@ -267,6 +276,14 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) {
if (screen == config.source.screen && screenId(screen) == config.source.id) { selected = screen; break; }
if (!selected) { DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop screen disappeared"); return false; }
}
#ifdef UTUN_STREAM_PORTAL
if (config.source.id == "portal") {
m->portal = std::make_unique<StreamPortalCapture>();
connect(m->portal.get(), &StreamPortalCapture::frameReady, m->sink.get(), &QVideoSink::setVideoFrame);
connect(m->portal.get(), &StreamPortalCapture::errorOccurred, this, failed, Qt::QueuedConnection);
m->portal->start(config.showCursor);
} else
#endif
// Qt X11 screen capture ищет root по имени и путает мониторы; QScreen захватывает именно выбранный экран.
if (selected && QGuiApplication::platformName() == "xcb") {
#ifdef UTUN_STREAM_X11_CURSOR
@ -340,6 +357,9 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) {
void StreamPublishEngine::closeSource() {
#ifdef HAVE_STREAM_CAPTURE
m->screenGrabTimer.reset();
#ifdef UTUN_STREAM_PORTAL
m->portal.reset();
#endif
#ifdef UTUN_STREAM_X11_CURSOR
m->cursor.reset();
#endif
@ -388,6 +408,10 @@ bool StreamPublishEngine::start(uint64_t group, const StreamPublishConfig& confi
bool StreamPublishEngine::reconfigure(const StreamPublishConfig& config) {
if (!m->running) return false;
StreamPublishConfig previous = this->config();
if (previous.source.id == "portal" && config.source.sameSource(previous.source) && config.showCursor != previous.showCursor) {
DEBUG_WARN(DEBUG_CATEGORY_VIDEO, "Wayland capture cursor mode cannot change during a portal session");
emit errorOccurred(text("Change cursor visibility before starting screen sharing")); return false;
}
if (config.audio != previous.audio || config.microphone != previous.microphone) {
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "desktop microphone selection changed during live publication");
emit errorOccurred(text("Change the microphone before starting the stream")); return false;

4
tools/chatgui/src/stream_publish_window.cpp

@ -302,5 +302,7 @@ void StreamPublishWindow::synchronize() {
m_cursor->setChecked(config.showCursor);
}
m_cursor->setVisible(StreamPublishEngine::cursorSupported(selection().source));
m_cursor->setEnabled(!active || m_engine->running());
bool portal = selection().source.id == "portal";
m_cursor->setEnabled(!active || (m_engine->running() && !portal));
m_cursor->setToolTip(portal ? text("Change cursor visibility before starting screen sharing") : QString());
}

Loading…
Cancel
Save