Browse Source

Document demand driven playback and delayed decoder lifecycle

master
evgeny 4 days ago
parent
commit
7b4dfc062a
  1. 15
      doc/service_lifecycle.md
  2. 36
      doc/stream.txt

15
doc/service_lifecycle.md

@ -104,6 +104,21 @@ Live media хранится в RS-кольце с общим индексом PT
destroy отсоединённого cursor не обращается к store. Frontend прекращает audio callback
и worker до освобождения своего DSP; borrowed handle/RS pointers между потоками не передаются.
Чтение video cursor запрашивает следующий кадр по готовности decoder, независимо от
PTS показа; audio cursor сохраняет временной lookahead. Bridges готовят один ответ
на незавершённый запрос и не читают следующий кадр после получения ответа автоматически.
Android worker держит один рабочий input и один готовый output MediaCodec; свободный
input buffer получает лишь для уже готовых данных и сразу возвращает codec.
Первый decoded frame разрешает движение clock/audio. Будущий output ждёт PTS и
приостанавливает новые video requests, сохраняя независимую обработку audio/control.
PTS поданных кадров служат диагностике/проверке запаздывания, а не лимиту заполнения codec.
Смена revision заменяет только video decoder и его измеренный защитный guard;
GAP/EXPIRED начинают новую точку KEY. Нехватка сети сохраняет decoder references.
Desktop FFmpeg держит один рабочий AVPacket и два готовых изображения; EAGAIN оставляет
packet до следующего прохода. FIN подаёт EOS и дренирует выход до decoder EOF;
конец GUI требует также показа оставшихся изображений и завершения audio tail.
Отсутствие прогресса decoder при наличии работы имеет отдельную диагностику и срок 10s.
ACK-история принадлежит ядру и обновляется только при первом найденном подтверждении
пакета. REINIT/close соединения не стирает уже подтверждённые за последнюю секунду байты.
Общий `stream_publisher` Android/desktop владеет отдельным 100ms таймером TX-снимков;

36
doc/stream.txt

@ -813,14 +813,26 @@ Android:
неполную пачку объединяет с аудио/видео до 20ms; продолжение работы через timer 5ms.
При video pressure отбрасываются целые ожидающие кадры, P-кадры запрещены до нового KEY.
Кодировщик получает отказ admission и запрашивает KEY с ограничением частоты 500ms.
- RX<=4MiB/256 records, подготовлено не более двух media records. Запас остаётся в общем RS-кольце;
bridge читает ближайшие кадры по запросу worker с текущим PTS и отдельными audio/video lookahead.
Kotlin держит до четырёх входных кадров, до трёх поданных decoder PTS и один ожидающий выход.
За проход подаётся до четырёх кадров, выход декодера обслуживается до восьми раз.
- RX<=4MiB/256 records, bridge готовит один ответ на незавершённый запрос worker.
Получение ответа и сетевые AVAILABLE не запускают автоматическое чтение следующего кадра.
Запас остаётся в RS-кольце. want_video запрашивает следующий полный видеокадр независимо от часов показа;
audio_ahead ограничивает только звук относительно PTS потребителя. Управление/звук обслуживаются независимо от video pressure.
StreamDecodePump держит один рабочий кодированный кадр и один ожидающий output MediaCodec.
Decoder заполняет свой внутренний конвейер до первого выхода без ограничений по числу поданных кадров или video lookahead.
Перед каждым входом проверяется выход; свободный input buffer берётся только для уже готового рабочего кадра.
Будущий output ждёт своего PTS и приостанавливает новые video requests; уже запрошенный ответ помещается в рабочий input.
Низкая задержка запрашивается через KEY_LOW_LATENCY при заявленной поддержке, но корректность не зависит от этого режима.
За проход обслуживаются до четырёх media replies, до восьми output buffers за один вызов pump.
При обычной нехватке данных decoder references сохраняются; GAP/вытеснение требуют нового KEY.
Просроченный кадр при нормальной последовательности декодируется без показа.
- Фиксированного prebuffer нет. AudioTrack задаёт время показа видео по реально услышанному PCM;
- Фиксированного prebuffer нет. Начало clock/audio output разрешено после первого декодированного кадра.
AudioTrack задаёт время показа видео по реально услышанному PCM;
без аудио используются монотонные часы с остановкой на границе готовых кадров.
Защитный guard минутного контроллера учитывает audio device lead и наблюдённое опережение decoder
(максимум last_input_PTS-output_PTS текущей revision плюс период кадра). Drain не обнуляет этот guard;
новый decoder начинает измерение заново. Отдельного контроллера задержки декодера нет.
Отсутствие output progress 10s при наличии работы даёт ERROR; сетевые паузы и ожидание PTS допустимы.
Состояния ожидания KEY и decoder разделены; логи показывают inputs/decoded/shown, рабочие slots, inflight и decoderLeadUs.
Короткие audio gaps заполняются Opus PLC, большой разрыв сбрасывает timeline.
Локальный preview использует обычную подписку на собственный источник с отключённым воспроизведением
своего микрофона, чтобы исключить акустическую обратную связь. Локальный preview ориентируется по сенсору своей камеры
@ -931,16 +943,20 @@ Desktop:
в uasync. Протокол uAV2 и wire v5 при добавлении desktop publisher не меняются.
- Один StreamPlayerWindow на процесс. Он содержит имя источника, состояние подключения, громкость,
полноэкранный режим и закрытие. Выбор нового источника закрывает предыдущего reader.
- transport/stream_bridge владеет одним viewer, готовит до двух media records и ограничивает RX 4MiB/16 записей.
- transport/stream_bridge владеет одним viewer, готовит один ответ на запрос и ограничивает RX 4MiB/16 записей.
Attach/detach выполняются в uasync; команды и копирование медиаданных защищены mutex.
Post отменяется до destroy ядра; GUI/decoder не хранят заимствованные instance/handle pointers.
- stream_media_cursor собирает ближайший access unit выбранного кодека и выдаёт Opus 48kHz mono/stereo/20ms из RS-кольца.
Android AudioTrack и desktop output работают в stereo; mono-пакеты upmix выполняет libopus.
FFmpeg/Opus декодируются отдельным worker; Qt-очередь не накапливает кадры.
Worker запрашивает видео при наличии менее двух готовых изображений; защитный предел — четыре.
Worker держит один рабочий AVPacket и не более двух готовых изображений. Следующий video request не ограничен часами показа.
FFmpeg output обслуживается перед input; EAGAIN сохраняет рабочий packet и означает backpressure, не GAP.
Дальние кадры и звук не копируются из кольца. SoundTouch и устройство держат только рабочую порцию PCM.
Кадры сохраняются до достижения их PTS аудиочасами; при задержке GUI общий clock останавливается.
Видео декодируется без задержки frame-threading. При GAP сбрасываются decoder refs и timeline до KEY.
- Первый decoded frame разрешает движение clock/audio, защитный guard учитывает наблюдённый decoder lead.
FIN отправляет decoder EOS; выход дренируется теми же ограниченными проходами до EOF, GUI продолжает показ хвоста.
Ожидающий кадр не теряется при заполненной очереди изображений. Отсутствие прогресса при наличии работы логируется как ошибка.
- При начальном подключении desktop/Android прогревают Opus из кольца до первого KEY (до 500ms истории).
Старый звук обрезается по PTS видео, включая начало stereo PCM-пакета; декодер не сбрасывается из-за preroll.
Фиксированного prebuffer нет: показ следует физическим audio callback timestamps;
@ -955,6 +971,12 @@ Opus/громкость на настоящем null audio backend, непрер
late/pressure drops, число и байты кадров, PTS границ очереди относительно часов и audio callback timing.
test_stream_service также проверяет общий каталог двух независимых источников одного канала,
шестисекундную паузу readers при живом сетевом приёме без restart и полное локальное/удалённое дочитывание FIN.
StreamDecodePumpTest проверяет конвейеры 4/8 кадров при неподвижных часах без low-latency, ожидание PTS,
блокировку входа, сетевую паузу, пересечение ответа чтения с будущим output, короткий FIN и сохранение guard.
test_stream_playback проверяет восемь будущих кадров из кольца без video lookahead; test_android_stream — один ответ
при повторных запросах, отсутствие скрытого prefetch и возобновление с прежней позиции.
test_stream_view дополнительно задерживает четыре настоящих FFmpeg decoded frames: запуск требует кадра после 80ms,
а короткий поток из трёх кадров получает все изображения после FIN, без потери decoder tail.
test_stream_publish проверяет реальные encoder/decoder H.264/H.265/VP9/AV1, обновление libx264 bitrate
с прежним decoder, общую публикацию/RS, смену revision, pressure/KEY recovery, FIN и concurrent detach
с балансом tracked allocations. Дополнительный Xvfb/private D-Bus сценарий проверяет реальный экран/окно,

Loading…
Cancel
Save