Browse Source

Document microphone watchdogs and pending stream diagnostics

master
evgeny 2 days ago
parent
commit
38eae06161
  1. 10
      doc/service_lifecycle.md
  2. 24
      doc/tasks.md
  3. 6
      src/stream/stream_media_buffer.c

10
doc/service_lifecycle.md

@ -165,6 +165,16 @@ Fatal ошибка audio worker передаётся в GUI с session ID и з
откат видеоконфигурации применяется только к video/capture. Поздний отказ старого publisher
не завершает новую сессию. Причина ошибки сохраняется в окне после окончания drain.
Desktop-звонок и рация проверяют поступление корректного PCM, включая первый callback.
Секунда без данных отключает TX и фиксирует понятную ошибку в GUI; цифровая тишина является данными.
RX продолжает работать, рация снимает PTT, автоматического переоткрытия неисправного входа нет.
Выбор другого микрофона или новая сессия снимают ошибку. Неисправное устройство закрывается
в отдельном потоке; stop не присоединяет уже запущенный close worker. Новый захват ждёт его завершения.
В звонке microphone lease удерживается до конца закрытия даже после stop. Общий AudioCapture
рации сначала отсоединяет callback потребителя; последний владелец освобождает backend в worker.
Сброс контекста и уничтожение владельца дожидаются worker до освобождения miniaudio-контекста.
Штатное закрытие исправного устройства сохраняет синхронный порядок.
В desktop-видеозвонке Windows/Linux камера живёт в отдельном процессе того же
`vibechat --call-camera-worker`. Служебный вход выполняется до конфига, БД и
single-instance lock. Перечисление устройств, Qt/V4L2, преобразование и освобождение

24
doc/tasks.md

@ -4,6 +4,30 @@
## Текущие задачи
[+] **Проверять поступление PCM микрофона в desktop-звонках и рации** — 16.10.2026:
Секунда без первого/очередного корректного PCM отключает захват с понятным сообщением GUI.
Цифровая тишина допустима; отсутствие callbacks, nullptr и frames=0 проверяются отдельно.
RX сохраняется, PTT снимается и блокируется до выбора другого входа или новой сессии.
Неисправный backend закрывается асинхронно; stop во время закрытия не блокирует GUI,
новый захват ждёт завершения прежнего. Контекст и callback живут до завершения worker.
Тест с uninit=700мс проверяет heartbeat GUI, stop<300мс, удержание lease звонка и отсутствие повторных открытий.
GUI собран; audio_recovery, microphone_watchdog, radio_panel, call_video_encoder, call_video_clock: 5/5 PASS.
Захват экрана 3440×1440 под Xvfb: H.264/H.265 продолжают выдавать кадры, stop=7/59мс.
check.sh: 156/156, proxy 9/9, burst/load PASS. Логи: /tmp/mic-stream-final-tests.log,
/tmp/mic-stream-core-check-unrestricted.log, /tmp/stream-h265-progress.log.
[ ] **Устранить неподвижный кадр Windows-трансляции на Android и зависание stop** — 16.10.2026:
Новые 4.log/6.log: Realtek PCM поступает; после согласия на CPU открывается libx265 3440×1440.
В 4.log остановка заканчивается сообщением закрытия микрофона, завершение video worker не видно.
Добавлены стадии video worker, счётчики преобразования/кодирования/публикации и этапы stop/join.
Соответствующий Samsung-лог: epoch=3fdca693c4ec22b6, KEY PTS=19237089, следующий output=19876744.
Декодированы два кадра, показан один; written=played=0, аудиоустройство закрыто, clock стоит на KEY,
сетевой запас растёт более 46с. Причина отсутствия первого PCM пока не установлена.
Добавлены первая/ожидающая аудиометка cursor и audioInputs/audioPts/needsAudio в Android-сводке.
Диагностический APK собран, unit-тесты прошли, установлен на Samsung RZ8R72MG64B.
Повторное открытие невозможно: источник уже отсутствует в канале «ннн»; запрошен новый запуск/stop Windows.
Логи: /tmp/stream-viewer-sm.log, /tmp/stream-viewer-diagnostic.log. Исправление этих двух зависаний ещё не подтверждено.
[+] **Проверять микрофон и спрашивать перед переходом трансляции на CPU** — 16.10.2026:
По 4.log/6.log: GPU-кодировщики недоступны, WASAPI-микрофон камеры выдаёт frames=0,
повторное закрытие устройства блокировало GUI примерно на 4 с. Список кодеков больше не запускает пробное кодирование.

6
src/stream/stream_media_buffer.c

@ -445,11 +445,11 @@ int stream_media_cursor_read(struct stream_media_cursor *c, int64_t position, in
return STREAM_OK;
}
if (video_allowed) return cursor_video(c, packet);
if (ar == STREAM_OK && audio_ahead >= 0 && audio_pts > audio_limit && c->audio_blocked_pts != audio_pts) {
if (!c->audio_started && ar == STREAM_OK && audio_ahead >= 0 && audio_pts > audio_limit && c->audio_blocked_pts != audio_pts) {
c->audio_blocked_pts = audio_pts;
DEBUG_DEBUG(DEBUG_CATEGORY_STREAM, "media cursor audio waits source=%llx seq=%llu pts=%lld position=%lld limit=%lld first=%d video_requested=%d",
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "media cursor first audio waits source=%llx seq=%llu pts=%lld position=%lld limit=%lld video_requested=%d",
(unsigned long long)c->store->descriptor.source_node_id, (unsigned long long)c->audio.seq,
(long long)audio_pts, (long long)position, (long long)audio_limit, !c->audio_started, want_video);
(long long)audio_pts, (long long)position, (long long)audio_limit, want_video);
}
return ar == STREAM_MORE || vr == STREAM_MORE ? STREAM_MORE : STREAM_WAIT;
}

Loading…
Cancel
Save