bridge читает ближайшие кадры по запросу worker с текущим PTS и отдельными audio/video lookahead.
За проход подаётся до 8 видео-кадров, выход декодера обслуживается до 16 раз.
Kotlin держит до четырёх входных кадров, до трёх поданных decoder PTS и один ожидающий выход.
Нельзя выбросить reference P-кадр и продолжить с зависимыми: переполнение сбрасывает декодер до KEY.
За проход подаётся до четырёх кадров, выход декодера обслуживается до восьми раз.
При обычной нехватке данных decoder references сохраняются; GAP/вытеснение требуют нового KEY.
Просроченный кадр при нормальной последовательности декодируется без показа.
Просроченный кадр при нормальной последовательности декодируется без показа.
- После prebuffer 150ms AudioTrack clock определяет время показа видео; видео без аудио использует
- Фиксированного prebuffer нет. AudioTrack задаёт время показа видео по реально услышанному PCM;
монотонные часы. Короткие audio gaps заполняются Opus PLC, большой разрыв сбрасывает timeline.
без аудио используются монотонные часы с остановкой на границе готовых кадров.
Короткие audio gaps заполняются Opus PLC, большой разрыв сбрасывает timeline.
Локальный preview использует обычную подписку на собственный источник с отключённым воспроизведением
Локальный preview использует обычную подписку на собственный источник с отключённым воспроизведением
своего микрофона, чтобы исключить акустическую обратную связь. Локальный preview ориентируется по сенсору своей камеры
своего микрофона, чтобы исключить акустическую обратную связь. Локальный preview ориентируется по сенсору своей камеры
и текущему положению экрана; верх картинки зрителей отмечается красной гранью на кнопках поворота.
и текущему положению экрана; верх картинки зрителей отмечается красной гранью на кнопках поворота.
@ -839,7 +841,8 @@ Android:
Каждая запись JNI pull имеет header 24 bytes: kind:1, flags:1, width:2, height:2, rotation:2, PTS_us:8, length:4, revision:4.
Каждая запись JNI pull имеет header 24 bytes: kind:1, flags:1, width:2, height:2, rotation:2, PTS_us:8, length:4, revision:4.
Kotlin и desktop viewer пересоздают только видеодекодер при смене revision; audio clock не сбрасывается.
Kotlin и desktop viewer пересоздают только видеодекодер при смене revision; audio clock не сбрасывается.
- Stop сначала закрывает capture producers и encoder, затем FIN.
- Stop сначала закрывает capture producers и encoder, затем FIN.
Publisher сохраняет конечный буфер ещё 2s для сетевой выдачи, затем закрывается.
Publisher сохраняет конечный буфер ещё 2s для сетевой выдачи, затем снимает своё владение.
При наличии локального reader завершённый источник и кольцо живут до его close, позволяя дочитать FIN.
Это ограниченный drain, не подтверждение воспроизведения всеми viewers. Abort/core restart очищает очередь сразу.
Это ограниченный drain, не подтверждение воспроизведения всеми viewers. Abort/core restart очищает очередь сразу.
Поздние команды старого session ID не меняют новый запуск.
Поздние команды старого session ID не меняют новый запуск.
- Звонок, рация и voice recording не начинают новый capture во время трансляции;
- Звонок, рация и voice recording не начинают новый capture во время трансляции;
@ -870,29 +873,60 @@ Desktop:
ответы предыдущего канала не меняют текущую шапку. Личные беседы снимают наблюдение.
ответы предыдущего канала не меняют текущую шапку. Личные беседы снимают наблюдение.
- Один StreamPlayerWindow на процесс. Он содержит имя источника, состояние подключения, громкость,
- Один StreamPlayerWindow на процесс. Он содержит имя источника, состояние подключения, громкость,
полноэкранный режим и закрытие. Выбор нового источника закрывает предыдущего reader.
полноэкранный режим и закрытие. Выбор нового источника закрывает предыдущего reader.
- transport/stream_bridge владеет одним viewer и ограничивает RX 4MiB/256 записей.
- transport/stream_bridge владеет одним viewer, готовит до двух media records и ограничивает RX 4MiB/16 записей.
Attach/detach выполняются в uasync; команды и копирование медиаданных защищены mutex.
Attach/detach выполняются в uasync; команды и копирование медиаданных защищены mutex.
Post отменяется до destroy ядра; GUI/decoder не хранят заимствованные instance/handle pointers.
Post отменяется до destroy ядра; GUI/decoder не хранят заимствованные instance/handle pointers.
- stream_media_receiver собирает H.264 access units и выдаёт Opus 48kHz mono/stereo/20ms.
- stream_media_cursor собирает ближайший H.264 access unit и выдаёт Opus 48kHz mono/stereo/20ms из RS-кольца.
Android AudioTrack и desktop output работают в stereo; mono-пакеты upmix выполняет libopus.
Android AudioTrack и desktop output работают в stereo; mono-пакеты upmix выполняет libopus.
FFmpeg/Opus декодируются отдельным worker; Qt-очередь не накапливает кадры.
FFmpeg/Opus декодируются отдельным worker; Qt-очередь не накапливает кадры.
Очередь декодированного видео ограничена 128 кадрами и 256MiB, аудио — 25 пакетами (500ms).
Worker запрашивает видео при наличии менее двух готовых изображений; защитный предел — четыре.
Кадры сохраняются до достижения их PTS аудиочасами. При пределе видео отбрасывается новый
Дальние кадры и звук не копируются из кольца. SoundTouch и устройство держат только рабочую порцию PCM.
уже декодированный кадр; ближайшие к показу остаются в очереди, codec refs не меняются.
Кадры сохраняются до достижения их PTS аудиочасами; при задержке GUI общий clock останавливается.
Видео декодируется без задержки frame-threading. При GAP сбрасываются decoder refs и timeline до KEY.
Видео декодируется без задержки frame-threading. При GAP сбрасываются decoder refs и timeline до KEY.
- При начальном подключении desktop/Android прогревают Opus до первого KEY в ограниченной очереди.
- При начальном подключении desktop/Android прогревают Opus из кольца до первого KEY (до 500ms истории).
Старый звук обрезается по PTS видео, включая начало stereo PCM-пакета; декодер не сбрасывается из-за preroll.
Старый звук обрезается по PTS видео, включая начало stereo PCM-пакета; декодер не сбрасывается из-за preroll.
Prebuffer 150ms начинается после выбора первого KEY, затем показ следует физическим audio callback timestamps;
Фиксированного prebuffer нет: показ следует физическим audio callback timestamps;
без звука — монотонным часам. END до KEY освобождает preroll, не оставляя незавершённую очередь.
без звука — монотонным часам с ограничением готовым PTS. END до KEY завершает пустой reader.
Короткие пропуски аудио заполняются Opus PLC; большой разрыв/pressure сбрасывает timeline.
Короткие пропуски аудио заполняются Opus PLC; большой разрыв/pressure сбрасывает timeline.
Закрытие окна снимает только reader, собственная публикация сохраняется.
Закрытие окна снимает только reader, собственная публикация сохраняется.
Удаление канала сообщает STREAM_CLOSE_GROUP; остановка ядра снимает media и catalogue owners.
Удаление канала сообщает STREAM_CLOSE_GROUP; остановка ядра снимает media и catalogue owners.
- Без FFmpeg окно сообщает, что декодирование недоступно. Нужна desktop-сборка с HAVE_FFMPEG.
- Без FFmpeg окно сообщает, что декодирование недоступно. Нужна desktop-сборка с HAVE_FFMPEG.
Проверки: test_stream_view — настоящее ядро, старые эпохи/cancel, RX pressure, H.264 с поворотом и сменой revision без новой эпохи,
Проверки: test_stream_view — настоящее ядро, старые эпохи/cancel, задержанное чтение без роста RX, H.264 с поворотом и сменой revision без новой эпохи,
Opus/громкость на настоящем null audio backend, непрерывные 30fps при физической audio latency 200ms,
Opus/громкость на настоящем null audio backend, непрерывные 30fps при физической audio latency 200ms,
закрытие канала и полный баланс tracked allocations. Раз в секунду desktop viewer логирует decode/show FPS,
закрытие канала и полный баланс tracked allocations. Раз в секунду desktop viewer логирует decode/show FPS,
late/pressure drops, число и байты кадров, PTS границ очереди относительно часов и audio callback timing.
late/pressure drops, число и байты кадров, PTS границ очереди относительно часов и audio callback timing.
test_stream_service также проверяет общий каталог двух независимых источников одного канала.
test_stream_service также проверяет общий каталог двух независимых источников одного канала,
шестисекундную паузу readers при живом сетевом приёме без restart и полное локальное/удалённое дочитывание FIN.
Общий запас и адаптация воспроизведения:
- Кодированный поток хранится один раз, в stream_buffer (RS-кольцо 32MiB по умолчанию).
stream_media_store хранит только диапазоны seq, PTS готового видео/аудио и позиции KEY.
Индекс ограничен геометрией кольца и 4MiB метаданных; cursor принадлежит отдельному handle.
Live ingest cursor и оптимизатор выдач продолжают продвигаться, независимо от паузы player.
Рабочая память reader — один H.264 кадр до 2MiB, один Opus-пакет и два scratch медиаблока.
- Подпись пачки проверяется при первом восстановлении. Индексы использованных RS-частей фиксируются;
повторное чтение использует тот же неизменяемый набор, поэтому поздние части не меняют проверенные данные.
Reader не закрепляет старые части против вытеснения. После выхода за окно кольца он начинает с нового KEY.
- AVAILABLE сообщает готовность индекса, DATA/GAP/END callbacks описывают live ingest.
media_read выдаёт END после обоих треков конкретного reader. MORE продолжает ограниченную сборку
отдельным callback без ожидания новых пакетов; WAIT ожидает новые данные или изменение позиции.