From 1e49d2554cd1d0729a5546f5a7f17af94e9145b7 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 20 Oct 2026 02:29:46 +0200 Subject: [PATCH] Limit desktop and Android stream bitrate menus to 12 Mbit/s --- doc/tasks.md | 8 ++++++++ .../main/java/com/utun/chat/ui/screens/StreamScreen.kt | 8 ++++---- tools/chatgui/src/stream_publish_window.cpp | 8 +++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/doc/tasks.md b/doc/tasks.md index 6184d474..d58059f4 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -4,6 +4,14 @@ ## Текущие задачи +[+] **Выбор битрейта трансляции до 12 Мбит/с** — 20.10.2026: + Desktop и Android: верхний ручной пункт 12М, прежние сохранённые значения выше приводятся к лимиту. + Android пересекает выбор с диапазоном encoder и сохраняет лимит при смене режима/камеры; + если ручного диапазона нет, используется автоматический выбор. Автоматический расчёт битрейта не менялся. + C/desktop/Android APK собраны, Android unit и Qt captureSettingsSurviveReopening PASS. + Логи: /tmp/stream-bitrate12-android-final.log, /tmp/stream-bitrate12-desktop-build.log, + /tmp/stream-bitrate12-settings-test.log. Готовые сборки в этой правке не устанавливались. + [+] **Desktop/Android: codec probes при запуске вместо задержки каждого звонка** — 20.10.2026: Звонок e55c56204f7bf159, локальный Linux: ACTIVE 01:01:17.892, decoder probes до 01:01:26.255, encoder probes до 01:01:28.284. Samsung уже опубликовал RX CAPS за 4мс; первый input через 10459мс, diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt index b2c87d09..e2457119 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt @@ -234,7 +234,7 @@ private fun StreamCaptureToolbar(cameras: List, config: StreamCapt val modes = allModes.filter { it.videoCodec == mode?.videoCodec } var menu by remember { mutableStateOf(null) } LaunchedEffect(enabled) { if (!enabled) menu = null } - LaunchedEffect(menu) { LogManager.addLog("DEBUG", "stream", "toolbar menu=$menu enabled=$enabled") } + LaunchedEffect(menu) { LogManager.addLog("DEBUG", "stream", "toolbar menu=$menu enabled=$enabled manualBitrateRange=${mode?.manualBitrateRange}") } val locale = LocalConfiguration.current.locales[0] val shortBitrate = config?.let { val mega = it.bitrate >= 1_000_000 @@ -299,9 +299,9 @@ private fun StreamCaptureToolbar(cameras: List, config: StreamCapt CaptureOptionItem(stringResource(R.string.stream_bitrate_auto), config?.videoBitrate == null, onClick = { menu = null; config?.let { onChange(it.copy(videoBitrate = null)) } }) - mode?.let { m -> - listOf(256000, 512000, 1000000, 2000000, 4000000, 6000000, 8000000, 12000000, 16000000, 24000000, 32000000, 48000000, 64000000) - .map { it.coerceIn(m.minimumBitrate, m.maximumBitrate) }.distinct().forEach { value -> + mode?.takeUnless { it.manualBitrateRange.isEmpty() }?.let { m -> + listOf(256000, 512000, 1000000, 2000000, 4000000, 6000000, 8000000, 12000000) + .map { it.coerceIn(m.manualBitrateRange) }.distinct().forEach { value -> CaptureOptionItem(stringResource(R.string.stream_bitrate_value, value / 1_000_000.0), config?.videoBitrate == value, onClick = { menu = null; config?.let { onChange(it.copy(videoBitrate = value)) } diff --git a/tools/chatgui/src/stream_publish_window.cpp b/tools/chatgui/src/stream_publish_window.cpp index 7d89060c..e37da2a0 100644 --- a/tools/chatgui/src/stream_publish_window.cpp +++ b/tools/chatgui/src/stream_publish_window.cpp @@ -24,6 +24,7 @@ #endif namespace { +constexpr int MaximumManualBitrate = 12000000; QString text(const char* value) { return QCoreApplication::translate("ChatGui", value); } QString bytes(uint64_t value) { return QString::number(value / 1024.0, 'f', 1) + " KiB"; } } @@ -64,8 +65,9 @@ StreamPublishWindow::StreamPublishWindow(StreamPublishEngine* engine, uint64_t g form->addRow(text("Video mode"), m_mode); m_codec = new QComboBox(settings); form->addRow(text("Video codec"), m_codec); m_bitrate = new QComboBox(settings); m_bitrate->addItem(text("Automatic"), 0); - for (int bitrate : {250000, 500000, 1000000, 2000000, 4000000, 8000000, 16000000}) + for (int bitrate : {250000, 500000, 1000000, 2000000, 4000000, 8000000, MaximumManualBitrate}) m_bitrate->addItem(QStringLiteral("%1 Mbit/s").arg(bitrate / 1000000.0, 0, 'f', 2), bitrate); + DEBUG_DEBUG(DEBUG_CATEGORY_STREAM, "desktop manual stream bitrate selection maximum_bps=%d", MaximumManualBitrate); form->addRow(text("Video bitrate"), m_bitrate); m_rotation = new QButtonGroup(this); auto* rotationRow = new QWidget(settings); auto* angles = new QHBoxLayout(rotationRow); angles->setContentsMargins(0, 0, 0, 0); @@ -188,6 +190,10 @@ void StreamPublishWindow::restoreSettings() { restored.video.fps = m_settings.value("fps").toInt(30); restored.nativeSize = m_settings.value("native_size").toBool(); refreshModes(restored, sourceIndex < 0 && restored.source.kind == StreamVideoSource::Screen); int bitrate = m_settings.value("bitrate").toInt(); + if (bitrate > MaximumManualBitrate) { + DEBUG_WARN(DEBUG_CATEGORY_STREAM, "desktop saved stream bitrate adjusted old_bps=%d maximum_bps=%d", bitrate, MaximumManualBitrate); + bitrate = MaximumManualBitrate; + } if (bitrate > 0 && m_bitrate->findData(bitrate) < 0) m_bitrate->addItem(QStringLiteral("%1 Mbit/s").arg(bitrate / 1000000.0, 0, 'f', 2), bitrate); select(m_bitrate, bitrate, "bitrate");