Include the cursor in X11 stream frames by default
This commit is contained in:
1 parent
e24ab45725
commit
5753177f29
3 files changed
+32
-2
No files matched your search
@@ -31,6 +31,9 @@ extern "C" {
|
||||
#include <QWindowCapture>
|
||||
#include <QVideoFrame>
|
||||
#endif
|
||||
#ifdef UTUN_STREAM_X11_CURSOR
|
||||
#include "stream_screen_cursor.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
int64_t monotonicUs() { return std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
@@ -75,6 +78,9 @@ struct StreamPublishEngine::Impl {
|
||||
std::unique_ptr<QCamera> camera;
|
||||
std::unique_ptr<QScreenCapture> screen;
|
||||
std::unique_ptr<QTimer> screenGrabTimer;
|
||||
#ifdef UTUN_STREAM_X11_CURSOR
|
||||
std::unique_ptr<StreamScreenCursor> cursor;
|
||||
#endif
|
||||
std::unique_ptr<QWindowCapture> window;
|
||||
QVideoFrame frame;
|
||||
QVideoFrame previewFrame;
|
||||
@@ -141,6 +147,13 @@ QVariant StreamPublishEngine::previewFrame() const {
|
||||
#endif
|
||||
}
|
||||
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_X11_CURSOR
|
||||
return source.kind == StreamVideoSource::Screen && source.screen && source.id != "portal" && QGuiApplication::platformName() == "xcb";
|
||||
#else
|
||||
Q_UNUSED(source); return false;
|
||||
#endif
|
||||
}
|
||||
bool StreamPublishEngine::muted() const { return m->muted.load(); }
|
||||
void StreamPublishEngine::setMuted(bool muted) {
|
||||
if (!m->running || !config().audio) {
|
||||
@@ -256,6 +269,9 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) {
|
||||
}
|
||||
// Qt X11 screen capture ищет root по имени и путает мониторы; QScreen захватывает именно выбранный экран.
|
||||
if (selected && QGuiApplication::platformName() == "xcb") {
|
||||
#ifdef UTUN_STREAM_X11_CURSOR
|
||||
m->cursor = std::make_unique<StreamScreenCursor>(selected);
|
||||
#endif
|
||||
m->screenGrabTimer = std::make_unique<QTimer>(); m->screenGrabTimer->setTimerType(Qt::PreciseTimer);
|
||||
connect(m->screenGrabTimer.get(), &QTimer::timeout, this, [this, generation, screen = QPointer<QScreen>(selected), failed] {
|
||||
if (generation != m->sourceGeneration || !m->running) return;
|
||||
@@ -266,6 +282,12 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) {
|
||||
m->screenGrabTimer->stop();
|
||||
QMetaObject::invokeMethod(this, [failed] { failed(text("Video capture stopped")); }); return;
|
||||
}
|
||||
#ifdef UTUN_STREAM_X11_CURSOR
|
||||
if (this->config().showCursor && !m->cursor->draw(image)) {
|
||||
m->screenGrabTimer->stop();
|
||||
QMetaObject::invokeMethod(this, [failed] { failed(text("Could not capture the mouse cursor")); }); return;
|
||||
}
|
||||
#endif
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||
QVideoFrame frame(image);
|
||||
#else
|
||||
@@ -284,8 +306,8 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) {
|
||||
frame.setStartTime(captured); m->sink->setVideoFrame(frame);
|
||||
});
|
||||
m->screenGrabTimer->start(std::max(1, 1000 / std::clamp(config.video.fps, 1, 60)));
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "desktop X11 screen grab started source=%s interval_ms=%d",
|
||||
qPrintable(config.source.name), m->screenGrabTimer->interval());
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "desktop X11 screen grab started source=%s interval_ms=%d cursor=%d supported=%d",
|
||||
qPrintable(config.source.name), m->screenGrabTimer->interval(), config.showCursor, cursorSupported(config.source));
|
||||
} else {
|
||||
m->screen = std::make_unique<QScreenCapture>();
|
||||
m->screen->setScreen(selected);
|
||||
@@ -318,6 +340,9 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) {
|
||||
void StreamPublishEngine::closeSource() {
|
||||
#ifdef HAVE_STREAM_CAPTURE
|
||||
m->screenGrabTimer.reset();
|
||||
#ifdef UTUN_STREAM_X11_CURSOR
|
||||
m->cursor.reset();
|
||||
#endif
|
||||
emit previewVideoChanged(QVariant());
|
||||
if (m->sink) disconnect(m->sink.get(), nullptr, this, nullptr);
|
||||
if (m->camera) { disconnect(m->camera.get(), nullptr, this, nullptr); m->camera->stop(); }
|
||||
@@ -367,6 +392,8 @@ bool StreamPublishEngine::reconfigure(const StreamPublishConfig& config) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "desktop microphone selection changed during live publication");
|
||||
emit errorOccurred(text("Change the microphone before starting the stream")); return false;
|
||||
}
|
||||
if (config.showCursor != previous.showCursor)
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "desktop cursor selected enabled=%d supported=%d", config.showCursor, cursorSupported(config.source));
|
||||
bool sourceChange = !config.source.sameSource(previous.source) || (config.source.kind == StreamVideoSource::Camera
|
||||
&& (config.video.width != previous.video.width || config.video.height != previous.video.height || config.video.fps != previous.video.fps));
|
||||
{ std::lock_guard<std::mutex> guard(m->lock); m->wanted = config; m->generation++; m->started = monotonicUs();
|
||||
|
||||
Reference in new issue
Block a user