Show cursor in Windows stream preview

This commit is contained in:
evgeny committed 2026-10-17 01:02:46 +02:00
1 parent bf729502a1
commit 88e3e27145
1 file changed
+26
@@ -57,6 +57,24 @@ QByteArray screenId(QScreen* screen) {
return QJsonDocument(QJsonArray{screen->name(), screen->manufacturer(), screen->model(), screen->serialNumber(), duplicate})
.toJson(QJsonDocument::Compact);
}
#ifdef UTUN_STREAM_WIN_CURSOR
QVideoFrame previewFrameFromImage(const QImage& source) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
return QVideoFrame(source);
#else
QImage image = source.convertToFormat(QImage::Format_RGBA8888);
QVideoFrame frame(QVideoFrameFormat(image.size(), QVideoFrameFormat::Format_RGBA8888));
if (!frame.map(QVideoFrame::WriteOnly)) {
DEBUG_WARN(DEBUG_CATEGORY_VIDEO, "desktop preview frame map failed size=%dx%d", image.width(), image.height());
return {};
}
for (int y = 0; y < image.height(); y++)
std::memcpy(frame.bits(0) + y * frame.bytesPerLine(0), image.constScanLine(y), image.width() * 4);
frame.unmap();
return frame;
#endif
}
#endif
#endif
}
struct StreamPublishEngine::Impl {
@@ -318,7 +336,9 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) {
}
int fps = std::clamp(m->wanted.video.fps, 1, 60);
convert = !m->lastImageCaptureAt || callbackAt - m->lastImageCaptureAt >= 1000000 / fps;
#ifndef UTUN_STREAM_WIN_CURSOR
m->previewFrame = frame;
#endif
if (!convert) { m->wake.notify_all(); return; }
m->lastImageCaptureAt = callbackAt;
if (m->framePts < 0 && m->wanted.source.id == "portal") m->started = monotonicUs();
@@ -510,6 +530,9 @@ void StreamPublishEngine::imageLoop() {
QMetaObject::invokeMethod(this, [this, generation] { sourceFailed(generation, text("Could not capture the mouse cursor")); });
continue;
}
QVideoFrame preview = previewFrameFromImage(image);
if (!preview.isValid()) DEBUG_WARN(DEBUG_CATEGORY_VIDEO, "desktop preview frame unavailable generation=%llu",
(unsigned long long)generation);
#endif
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
if (frame.rotation() != QtVideo::Rotation::None) image = image.transformed(QTransform().rotate(static_cast<int>(frame.rotation())));
@@ -522,6 +545,9 @@ void StreamPublishEngine::imageLoop() {
std::lock_guard<std::mutex> guard(m->lock);
if (m->imageStop) return;
if (!m->running || generation != m->sourceGeneration) continue;
#ifdef UTUN_STREAM_WIN_CURSOR
if (preview.isValid()) m->previewFrame = std::move(preview);
#endif
if (m->framePts < 0 && m->wanted.source.id == "portal") m->started = monotonicUs();
m->latestImage = image; m->frame = std::move(image); m->framePts = pts; m->frameGeneration = m->generation;
if (!m->convertedCaptureFrames++) DEBUG_INFO(DEBUG_CATEGORY_VIDEO,