From f85f45fbd36be407c3b425b0e4ff7528857935a1 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 14 Oct 2026 10:21:40 +0200 Subject: [PATCH] Validate publisher lifecycle in optional codec builds --- tools/chatgui/tests/test_stream_publish.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tools/chatgui/tests/test_stream_publish.cpp b/tools/chatgui/tests/test_stream_publish.cpp index 90fb533f..a2c2e8a0 100644 --- a/tools/chatgui/tests/test_stream_publish.cpp +++ b/tools/chatgui/tests/test_stream_publish.cpp @@ -64,12 +64,17 @@ class StreamPublishTest : public QObject { uint64_t group = 0; size_t allocations = 0; static QByteArray keyframe(int codec, int width = 160, int height = 90, uint64_t pts = 100000) { +#ifndef HAVE_FFMPEG + Q_UNUSED(codec); Q_UNUSED(width); Q_UNUSED(height); Q_UNUSED(pts); + return QByteArray(4, '\0') + "opaque access unit"; +#else StreamVideoEncoder encoder; StreamVideoConfig config; config.width = width; config.height = height; config.codec = codec; if (!encoder.open(config)) return {}; QImage image(width, height, QImage::Format_RGB32); image.fill(QColor(45, 130, 220)); QList output; if (!encoder.encode(image, pts, true, output) || output.isEmpty() || !output.front().key) return {}; return output.front().data; +#endif } bool record(uint64_t id, StreamRecordKind kind, StreamRecord& out) { QElapsedTimer elapsed; elapsed.start(); @@ -110,11 +115,14 @@ private slots: } void encoderRoundTrip_data() { QTest::addColumn("codec"); - for (int codec : StreamVideoEncoder::available()) QTest::newRow(qPrintable(StreamVideoEncoder::codecName(codec))) << codec; + auto codecs = StreamVideoEncoder::available(); + if (codecs.isEmpty()) QTest::newRow("unavailable") << 0; + for (int codec : codecs) QTest::newRow(qPrintable(StreamVideoEncoder::codecName(codec))) << codec; } void encoderRoundTrip() { #ifdef HAVE_FFMPEG - QFETCH(int, codec); auto encoded = keyframe(codec); QVERIFY(!encoded.isEmpty()); + QFETCH(int, codec); if (!codec) QSKIP("No supported encoder"); + auto encoded = keyframe(codec); QVERIFY(!encoded.isEmpty()); const uint8_t *config = nullptr, *frame = nullptr; size_t configLength = 0, frameLength = 0; QCOMPARE(stream_media_key_parse((const uint8_t*)encoded.constData(), encoded.size(), &config, &configLength, &frame, &frameLength), STREAM_OK); const char* names[] = {"", "h264", "hevc", "vp9", "av1", "vvc"}; @@ -180,14 +188,14 @@ private slots: QSignalSpy errors(&engine, &StreamPublishEngine::errorOccurred); QVERIFY(engine.start(group, config)); QTRY_VERIFY_WITH_TIMEOUT(engine.config().video.codec == STREAM_MEDIA_H264, 10000); - char* sources = nullptr; uint64_t epoch = 0; + uint64_t epoch = 0; QElapsedTimer wait; wait.start(); while (!epoch && wait.elapsed() < 5000) { stream_member_state member{}; if (stream_member_load(inst, group, inst->node_id, &member, nullptr) == STREAM_OK && member.published) epoch = member.source.source_epoch; QTest::qWait(1); } - Q_UNUSED(sources); QVERIFY(epoch); QVERIFY(gui_stream_open(202, group, inst->node_id, epoch)); + 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)); 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); @@ -236,7 +244,7 @@ private slots: QVERIFY(!gui_stream_ready()); QVERIFY(gui_stream_attach(inst)); } void cleanupTestCase() { - poll.stop(); gui_stream_detach(inst); uasync_mark_stopped(ua); utun_instance_destroy(inst); uasync_destroy(ua); + poll.stop(); gui_stream_detach(inst); uasync_mark_stopped(ua); utun_instance_destroy(inst); uasync_destroy(ua, 1); QCOMPARE(u_get_allocated_count(), allocations); } };