|
|
|
|
@ -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 также проверяет общий каталог двух независимых источников одного канала. |
|
|
|
|
|