From 242d0f549371f711ccf0bfe7a33629c2327f5f50 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 18 Oct 2026 22:24:55 +0200 Subject: [PATCH] Verify the QP ceiling constrains real HEVC output under bitrate pressure --- tools/chatgui/tests/test_stream_publish.cpp | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tools/chatgui/tests/test_stream_publish.cpp b/tools/chatgui/tests/test_stream_publish.cpp index d879bc92..1ed39f5c 100644 --- a/tools/chatgui/tests/test_stream_publish.cpp +++ b/tools/chatgui/tests/test_stream_publish.cpp @@ -309,6 +309,41 @@ private slots: qp.reset(24, 4000000, true, 10000000); QCOMPARE(qp.update(1000, 11000000), 24); QCOMPARE(qp.bitrate(), uint64_t(0)); } + void maximumQpConstrainsEncodedHevc() { +#ifdef HAVE_FFMPEG + auto previousDebug = g_debug_config.category_levels[DEBUG_CATEGORY_DEBUG]; + auto cleanup = qScopeGuard([&] { + debug_set_log_hook(nullptr); debug_set_category_level(DEBUG_CATEGORY_DEBUG, previousDebug); + ffmpegDiagnosticMessages.clear(); + }); + debug_set_log_hook(captureFfmpegDiagnostic); debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_TRACE); + QImage image(320, 192, QImage::Format_RGB32); + uint32_t random = 1; + for (int y = 0; y < image.height(); ++y) { + auto* row = reinterpret_cast(image.scanLine(y)); + for (int x = 0; x < image.width(); ++x) { random = random * 1664525 + 1013904223; row[x] = 0xff000000 | (random & 0xffffff); } + } + int previousQp = -1, previousBytes = 0; + for (int ceiling : {18, 35}) { + LiveVideoConfig config; config.codec = STREAM_MEDIA_H265; config.width = 320; config.height = 192; + config.bitrate = 64000; config.maxQp = ceiling; + LiveVideoEncoder encoder; + QVERIFY2(encoder.open(config, LiveVideoEncoder::Backend::SoftwareOnly), qPrintable(encoder.error())); + ffmpegDiagnosticMessages.clear(); QList output; + QVERIFY(encoder.encode(image, 100000, true, output)); QCOMPARE(output.size(), 1); QVERIFY(output.front().key); + int initial = 0, actual = -1; + for (const auto& line : ffmpegDiagnosticMessages) { + if (line.contains("init_qp_minus26")) initial = line.section('=', -1).trimmed().toInt(); + if (line.contains("slice_qp_delta")) actual = 26 + initial + line.section('=', -1).trimmed().toInt(); + } + QVERIFY(actual >= 0); QVERIFY2(actual <= ceiling, qPrintable(QStringLiteral("QP %1 > %2").arg(actual).arg(ceiling))); + if (previousQp >= 0) { QVERIFY(actual > previousQp); QVERIFY(output.front().data.size() < previousBytes); } + previousQp = actual; previousBytes = output.front().data.size(); + } +#else + QSKIP("FFmpeg unavailable"); +#endif + } void proportionalScreenModes_data() { QTest::addColumn("source"); QTest::addColumn("maximum"); QTest::addColumn("reduced"); QTest::newRow("full-hd") << QSize(1920, 1080) << QSize(1920, 1080) << QSize(1280, 720);