Browse Source

Document reactive stream discovery and desktop playback ownership

master
evgeny 7 days ago
parent
commit
17606c66b8
  1. 35
      doc/stream.txt

35
doc/stream.txt

@ -755,7 +755,7 @@ Android:
- Camera/codec callbacks — HandlerThread, Opus encoder — audio capture thread, decoder/AudioTrack — viewer worker.
- Native bridge держит pthread mutex, ограниченные очереди и один pending post либо timer.
attach/detach выполняются в uasync вне callbacks. detach отменяет post/timer, закрывает handles,
очищает media, snapshots и запрещает producers до уничтожения instance/ua.
очищает media, снимает наблюдение каталога и запрещает producers до уничтожения instance/ua.
UI не сохраняет borrowed inst/ua. Idle без pending data не будит мобильное ядро.
- TX<=2MiB/128 records, не более 250ms ожидания. Actor публикует <=2 пачек за вызов,
неполную пачку объединяет с аудио/видео до 20ms; продолжение работы через timer 5ms.
@ -771,8 +771,16 @@ Android:
своего микрофона, чтобы исключить акустическую обратную связь. Камера при закрытии preview продолжает работать.
Viewer закрывается на Activity ON_STOP и создаётся заново на ON_START; publisher от UI не зависит.
Видимый player удерживает экран включённым. Preview ограничен оставшимся местом, кнопки управления не перекрывает.
- Source list строится в uasync по stream_member_load и stream_member_online, выдаётся UI копией JSON.
Свежий snapshot содержит source ID, epoch, self и экранированное имя. Увиденный источник не создаёт подписку.
- Source list общий для Android/desktop: stream_sources_json в uasync использует stream_member_load
и stream_member_online. stream_watch_sources наблюдает один выбранный канал; group=0 снимает наблюдение.
Начальный snapshot и изменения после Merkle/BGP передаются через CHAT_EVT_STREAM_SOURCES=58:
group_id:8BE, valid:1, JSON с id(decimal string), epoch(hex string), self, name.
События объединяются отложенным callback, одинаковый список повторно не отправляется. Таймера опроса нет.
Обнаружение не создаёт подписку, media-буфер и не удерживает ядро в ACTIVE.
- В шапке канала значок виден при наличии источников; один источник открывается сразу,
несколько выбираются из списка по имени/ID. Пункт меню «Трансляции» также открывает управление публикацией.
Выбранная эпоха проверяется actor до подписки и по фактически открытому handle. Перезапуск источника
требует нового выбора. Ошибка viewer kind=6 передаёт stream_close_reason в flags.
- Stop сначала завершает capture producers и encoder EOS (максимум 1s), затем FIN.
Publisher сохраняет конечный буфер ещё 2s для сетевой выдачи, затем закрывается.
Это ограниченный drain, не подтверждение воспроизведения всеми viewers. Abort/core restart очищает очередь сразу.
@ -785,3 +793,24 @@ Kotlin progress — DEBUG раз в секунду; C packet-level диагно
Проверки: test_stream_media (все пары потерь 6+2, parser/границы/GAP), test_android_stream
(живое ядро, preview, verified snapshots, FIN/cancel, concurrent producer/detach и leak count),
Android H264AnnexBTest (Annex B/length-prefixed NAL, SPS/PPS/IDR и усечённые данные).
Desktop:
- Значок трансляций расположен в шапке MessageList. Источники берутся из того же каталога ядра;
ответы предыдущего канала не меняют текущую шапку. Личные беседы снимают наблюдение.
- Один StreamPlayerWindow на процесс. Он содержит имя источника, состояние подключения, громкость,
полноэкранный режим и закрытие. Выбор нового источника закрывает предыдущего reader.
- transport/stream_bridge владеет одним viewer и ограничивает RX 4MiB/256 записей.
Attach/detach выполняются в uasync; команды и копирование медиаданных защищены mutex.
Post отменяется до destroy ядра; GUI/decoder не хранят заимствованные instance/handle pointers.
- stream_media_receiver собирает H.264 access units и выдаёт Opus 48kHz mono/20ms.
FFmpeg/Opus декодируются отдельным worker; Qt-очередь не накапливает кадры.
Очереди ограничены шестью декодированными видеокадрами и 25 аудиопакетами (500ms).
Видео декодируется без задержки frame-threading. При GAP сбрасываются decoder refs и timeline до KEY.
- После prebuffer 150ms показ следует физическим audio callback timestamps; без звука — монотонным часам.
Короткие пропуски аудио заполняются Opus PLC; большой разрыв/pressure сбрасывает timeline.
Закрытие окна снимает только reader, собственная публикация сохраняется.
Удаление канала сообщает STREAM_CLOSE_GROUP; остановка ядра снимает media и catalogue owners.
- Без FFmpeg окно сообщает, что декодирование недоступно. Нужна desktop-сборка с HAVE_FFMPEG.
Проверки: test_stream_view — настоящее ядро, старые эпохи/cancel, RX pressure, H.264 с поворотом,
Opus/громкость на настоящем null audio backend, закрытие канала и полный баланс tracked allocations.
test_stream_service также проверяет общий каталог двух независимых источников одного канала.

Loading…
Cancel
Save