Finalize shared frame rate selection and deterministic call control verification

This commit is contained in:
evgeny committed 2026-10-28 14:10:53 +01:00
1 parent bb0fa13c8b
commit 264a13705f
3 files changed
+7 -12

No files matched your search

+4 -8
View File
@@ -15,10 +15,7 @@
#include <QActionGroup>
#include <QWidgetAction>
#include <QToolButton>
#include <QProxyStyle>
#include <QStyleOptionMenuItem>
#include <QPainter>
#include <QPainterPath>
#include <QSignalBlocker>
#include <QJsonDocument>
#include <QScopedValueRollback>
@@ -189,7 +186,9 @@ StreamPublishWindow::StreamPublishWindow(StreamPublishEngine* engine, uint64_t g
refreshModes(previous, previous.source.kind == StreamVideoSource::Screen); apply();
if (!m_engine->active()) synchronize();
});
connect(m_resolution, &QMenu::triggered, this, [this] { refreshFrameRates(value(m_fps).toInt()); apply(); });
connect(m_resolution, &QMenu::triggered, this, [this] {
populateFrameRates(m_fps, m_modes, value(m_resolution).toSize(), value(m_fps).toInt()); apply();
});
for (auto* menu : {m_fps, m_codec, m_bitrate, m_maxQp, m_rotation, m_microphone})
connect(menu, &QMenu::triggered, this, &StreamPublishWindow::apply);
for (auto* menu : {m_codec, m_maxQp}) connect(menu, &QMenu::triggered, this, [this] { if (!m_updating) synchronize(); });
@@ -368,7 +367,7 @@ void StreamPublishWindow::refreshModes(const StreamPublishConfig& previous, bool
m_resolution->menuAction()->setToolTip(text("No supported video modes")); return;
}
const auto& mode = m_modes[selected];
select(m_resolution, mode.size); refreshFrameRates(mode.fps);
select(m_resolution, mode.size); populateFrameRates(m_fps, m_modes, mode.size, mode.fps);
if (!maximum && wanted != mode) DEBUG_WARN(DEBUG_CATEGORY_VIDEO,
"desktop video mode adjusted source=%s requested=%dx%d/%d selected=%dx%d/%d",
qPrintable(source.name), wanted.size.width(), wanted.size.height(), wanted.fps, mode.size.width(), mode.size.height(), mode.fps);
@@ -377,9 +376,6 @@ void StreamPublishWindow::refreshModes(const StreamPublishConfig& previous, bool
source.kind == StreamVideoSource::Screen && mode.size == m_modes.front().size);
}
void StreamPublishWindow::refreshFrameRates(int previous) {
populateFrameRates(m_fps, m_modes, value(m_resolution).toSize(), previous);
}
void StreamPublishWindow::refreshCodecs() {
QScopedValueRollback<bool> updating(m_updating, true);
int previous = selected(m_codec) ? value(m_codec).toInt() : m_settings.value("codec").toInt();
@@ -49,7 +49,6 @@ private:
void refreshSources(); // Сохраняет выбранный handle; пропавший active-source не подменяется другим, до start возможен первый доступный.
// Режимы camera/screen; выбирает близкий previous либо native screen.
void refreshModes(const StreamPublishConfig& previous, bool maximum = false);
void refreshFrameRates(int previous); // Все стандартные и аппаратные FPS; недоступные для выбранного размера видимы и отключены.
void updateMenuButtons(); // Обновляет иконки со значениями и подсказки верхнего ряда после выбора/синхронизации.
void refreshCodecs(); // Перечитывает engine.codecs(), сохраняет текущий/saved codec, недоступный заменяет первым.
void synchronize(); // Читает engine config/state без apply; настраивает controls и ограничения изменения audio/cursor/QP.
+3 -3
View File
@@ -162,14 +162,13 @@ private slots:
void videoSettingsMenus() {
CallWindow window; window.setCallId(77); window.setPeerName(QStringLiteral("Video call")); window.setState(CallWindow::Active);
auto* engine = window.findChild<CallVideoEngine*>(); QVERIFY(engine);
auto* capture = engine->findChild<CallCameraCapture*>(); QVERIFY(capture);
QObject::disconnect(capture, nullptr, engine, nullptr); // Детерминированные режимы, без открытия камеры/звонка.
CallCameraDevice first{QStringLiteral("Main camera"), QByteArray("main"), {}};
stream_video_add_camera_modes(first.modes, QSize(1920, 1080), 29.97, 29.97);
stream_video_add_camera_modes(first.modes, QSize(1280, 720), 15, 60);
CallCameraDevice second{QStringLiteral("Secondary camera"), QByteArray("secondary"), {}};
stream_video_add_camera_modes(second.modes, QSize(640, 480), 7, 7);
emit engine->camerasChanged({first, second});
QSignalBlocker blocked(engine); // Аппаратные события не меняют тестовые режимы; камера/звонок не открываются.
auto getMenu = [&window](const char* name) { return window.findChild<QMenu*>(name); };
auto chosen = [](QMenu* menu) { auto* action = menu->findChild<QActionGroup*>()->checkedAction(); return action ? action->data() : QVariant(); };
auto choose = [](QMenu* menu, const QVariant& value) {
@@ -185,7 +184,8 @@ private slots:
for (auto* action : fps->actions()) if (action->isCheckable())
QCOMPARE(action->isEnabled(), action->data().toInt() <= 30);
choose(camera, second.id); QCOMPARE(chosen(resolution).toSize(), QSize(640, 480)); QCOMPARE(chosen(fps).toInt(), 7);
emit engine->camerasChanged({second, first}); QCOMPARE(chosen(camera).toByteArray(), second.id); QCOMPARE(chosen(fps).toInt(), 7);
blocked.unblock(); emit engine->camerasChanged({second, first}); blocked.reblock();
QCOMPARE(chosen(camera).toByteArray(), second.id); QCOMPARE(chosen(fps).toInt(), 7);
choose(camera, first.id); choose(resolution, QSize(1920, 1080)); choose(getMenu("callVideoCodec"), 1);
auto* minimum = window.findChild<QSpinBox*>("callVideoMinimumBitrate"); QVERIFY(minimum);
auto* maximum = window.findChild<QSpinBox*>("callVideoMaximumBitrate"); QVERIFY(maximum);