From e4f9a48c2caf389277f888e8ad5380f90f786e32 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 14 Oct 2026 12:27:50 +0200 Subject: [PATCH] Reuse static screen frames across encoder changes and test rollback --- tools/chatgui/src/stream_publish_engine.cpp | 4 ++-- tools/chatgui/tests/test_stream_publish.cpp | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/tools/chatgui/src/stream_publish_engine.cpp b/tools/chatgui/src/stream_publish_engine.cpp index 7756ba1b..518657bc 100644 --- a/tools/chatgui/src/stream_publish_engine.cpp +++ b/tools/chatgui/src/stream_publish_engine.cpp @@ -133,7 +133,7 @@ bool StreamPublishEngine::openSource(const StreamPublishConfig& config) { uint64_t generation; { std::lock_guard guard(m->lock); generation = ++m->sourceGeneration; m->backendOrigin = m->backendAnchor = -1; m->capturedFrames = 0; } - m->session = std::make_unique(); m->sink = std::make_unique(); + m->session = std::make_unique(); m->sink = std::make_unique(this); m->session->setVideoSink(m->sink.get()); connect(m->sink.get(), &QVideoSink::videoFrameChanged, this, [this, generation](const QVideoFrame& frame) { if (!frame.isValid()) { DEBUG_TRACE(DEBUG_CATEGORY_VIDEO, "desktop capture sink invalid frame generation=%llu", (unsigned long long)generation); return; } @@ -430,7 +430,7 @@ void StreamPublishEngine::videoLoop() { } bool screen = config.source.kind != StreamVideoSource::Camera; if (frame.isValid()) { - if (capture <= lastPts || monotonicUs() - m->origin - capture > 250000) { skipped++; continue; } + if (!screen && (capture <= lastPts || monotonicUs() - m->origin - capture > 250000)) { skipped++; continue; } lastImage = frame.toImage(); if (lastImage.isNull()) { DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop captured frame conversion failed format=%d", frame.pixelFormat()); diff --git a/tools/chatgui/tests/test_stream_publish.cpp b/tools/chatgui/tests/test_stream_publish.cpp index b9bc119b..00cb0f6f 100644 --- a/tools/chatgui/tests/test_stream_publish.cpp +++ b/tools/chatgui/tests/test_stream_publish.cpp @@ -30,6 +30,8 @@ extern "C" { } #ifdef HAVE_STREAM_CAPTURE #include +#include +#include #endif #ifdef TEST_NULL_AUDIO @@ -200,6 +202,12 @@ private slots: } QVERIFY(epoch); QVERIFY(gui_stream_open(202, group, inst->node_id, epoch)); StreamRecord out; QVERIFY(record(202, StreamRecordKind::Opened, out)); QVERIFY(record(202, StreamRecordKind::Video, out)); + auto* sink = engine.findChild(); QVERIFY(sink); + // Неподвижный экран на backend, выдающем кадры только при изменениях: новых raw callbacks нет. + QObject::disconnect(sink, nullptr, &engine, nullptr); + StreamPublishWindow controls(&engine, group); controls.show(); + auto* preview = controls.findChild(); QVERIFY(preview); + QTRY_VERIFY(preview->videoSink()->videoFrame().isValid()); controls.close(); QVERIFY(engine.running()); uint64_t first = out.pts; unsigned audio = 0, video = 0; uint64_t latest = first, left = 0, right = 0; auto* decoder = opus_codec_decoder_create(48000, 2); QVERIFY(decoder); QElapsedTimer elapsed; elapsed.start(); @@ -222,11 +230,21 @@ private slots: QTest::qWait(1); } QVERIFY(revised); QCOMPARE(out.format.rotation, (uint16_t)90); + auto invalid = next; invalid.video.fps = 61; + QVERIFY(engine.reconfigure(invalid)); + QTRY_COMPARE_WITH_TIMEOUT(engine.config().video.fps, 15, 5000); + QTRY_COMPARE(errors.size(), 1); errors.clear(); + bool restored = false; + elapsed.restart(); while (!restored && elapsed.elapsed() < 5000) { + if (gui_stream_pull(202, out, 0, 60000000, 60000000) && out.kind == StreamRecordKind::Video && out.format.revision >= 3) restored = true; + QTest::qWait(1); + } + QVERIFY(restored); #if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0) next.source = {StreamVideoSource::Window, pattern.windowTitle(), {}, QVariant::fromValue(QCapturableWindow(pattern.windowHandle()))}; QVERIFY(engine.reconfigure(next)); bool window = false; elapsed.restart(); while (!window && elapsed.elapsed() < 5000) { - if (gui_stream_pull(202, out, 0, 60000000, 60000000) && out.kind == StreamRecordKind::Video && out.format.revision >= 3) window = true; + if (gui_stream_pull(202, out, 0, 60000000, 60000000) && out.kind == StreamRecordKind::Video && out.format.revision >= 4) window = true; QTest::qWait(1); } QVERIFY(window);