Document independent audio preparation and live stream catchup
This commit is contained in:
1 parent
4e5530aca0
commit
e8ee608ba9
3 files changed
+50
-29
No files matched your search
@@ -144,10 +144,16 @@ VIDEO_END/AUDIO_END следуют за последними пакетами с
|
||||
Получение батча погашает запрос, включая повторные обращения до pull; скрытого чтения следующего батча нет.
|
||||
Callback готовности только будит desktop worker и не вызывает API ядра/bridge. Stop снимает callback
|
||||
под mutex viewer до освобождения его контекста; detach будит ожидающие workers до уничтожения manager.
|
||||
На Android signal принадлежит worker и живёт до stream_stop и close mixer input; ядро только уведомляет его.
|
||||
На Android signal принадлежит audio worker и живёт до stream_stop, join video worker и close mixer input;
|
||||
ядро только уведомляет его. Surface освобождается после join video worker.
|
||||
В wait не удерживаются mutex bridge/ядра. Расход PCM будит тот же signal, уведомления сливаются без потери пробуждения.
|
||||
GUI и audio callback будят worker при движении часов/освобождении места; сна между готовыми пакетами нет.
|
||||
Android worker держит один рабочий input и один готовый output MediaCodec; свободный
|
||||
Каждый reader имеет отдельные audio/control и video workers. Audio worker читает батчи и готовит
|
||||
до 250ms PCM через Opus/SoundTouch, не удерживая блокировку consumer. Запас пополняется при наличии
|
||||
данных без обязательного prefill. SPSC передаёт PCM вместе с отображением исходных PTS; mixer/audio
|
||||
callback только копирует и смешивает. Короткая блокировка защищает output map/clock и lifetime,
|
||||
в ней нет декодирования, time-stretch или MediaCodec/FFmpeg. EOF продолжает prepare до опустошения DSP.
|
||||
Android video worker получает ограниченный mailbox (два кадра) и держит один рабочий input и один готовый output MediaCodec; свободный
|
||||
input buffer получает лишь для уже готовых данных и сразу возвращает codec.
|
||||
Первый decoded frame разрешает движение clock/audio. Будущий output ждёт PTS и
|
||||
приостанавливает новые video requests, сохраняя независимую обработку audio/control.
|
||||
@@ -155,8 +161,11 @@ input buffer получает лишь для уже готовых данных
|
||||
первого аудиопакета, сохраняя это основание неизменным. Opus/SoundTouch получает PCM до
|
||||
запуска audio clock; неподвижные часы не разрешают читать дальше этого ограниченного окна.
|
||||
PTS поданных кадров служат диагностике/проверке запаздывания, а не лимиту заполнения codec.
|
||||
Смена revision заменяет только video decoder и его измеренный защитный guard;
|
||||
Смена revision заменяет только video decoder и его диагностические измерения;
|
||||
GAP/EXPIRED начинают новую точку KEY. Нехватка сети сохраняет decoder references.
|
||||
Reset увеличивает video generation; результаты прежнего поколения не публикуются. Video worker
|
||||
после EOF остаётся доступен для reset до явного stop. Audio clock после старта не ждёт видео:
|
||||
просроченные изображения декодируются для сохранения references, но не показываются.
|
||||
Desktop FFmpeg держит один рабочий AVPacket и два готовых изображения; EAGAIN оставляет
|
||||
packet до следующего прохода. FIN подаёт EOS и дренирует выход до decoder EOF;
|
||||
конец GUI требует также показа оставшихся изображений и завершения audio tail.
|
||||
|
||||
+36
-24
@@ -816,8 +816,9 @@ Android:
|
||||
lookback=200ms, lookahead=0, release=rise*5, target=0.25. История и gain принадлежат только audio worker
|
||||
трансляции; оба канала используют общий gain, сохраняющий стереобаланс. Изменения настроек рации применяются на следующем PCM-кадре, без перезапуска микрофона,
|
||||
Opus или source_epoch; compressor не добавляет задержку и не меняет capture PTS.
|
||||
- Camera/codec callbacks — HandlerThread, Opus encoder — audio capture thread, decoder — отдельный viewer worker,
|
||||
общий AudioTrack — worker StreamAudioMixer. Перекладка плиток сохраняет TextureView/decoder.
|
||||
- Camera/codec callbacks — HandlerThread, Opus encoder — audio capture thread. Каждый viewer имеет
|
||||
audio/control worker и независимый video worker; общий AudioTrack — worker StreamAudioMixer.
|
||||
Перекладка плиток сохраняет TextureView/decoder.
|
||||
- Native bridge использует общий stream_publisher для TX и stream_viewers для RX.
|
||||
stream_publisher держит pthread mutex, ограниченные очереди и один pending post либо media timer;
|
||||
статистика обслуживается отдельным таймером 100ms. Тот же модуль используется desktop.
|
||||
@@ -834,6 +835,7 @@ Android:
|
||||
Получение ответа и сетевые AVAILABLE не запускают автоматическое чтение следующего кадра.
|
||||
Запас остаётся в RS-кольце. want_video запрашивает следующий полный видеокадр независимо от часов показа;
|
||||
audio_ahead ограничивает только звук относительно PTS потребителя. Управление/звук обслуживаются независимо от video pressure.
|
||||
StreamVideoPlayback владеет MediaCodec и принимает mailbox до двух кадров от audio/control worker.
|
||||
StreamDecodePump держит один рабочий кодированный кадр и один ожидающий output MediaCodec.
|
||||
Decoder заполняет свой внутренний конвейер до первого выхода без ограничений по числу поданных кадров или video lookahead.
|
||||
Перед каждым входом проверяется выход; свободный input buffer берётся только для уже готового рабочего кадра.
|
||||
@@ -841,9 +843,10 @@ Android:
|
||||
Низкая задержка запрашивается через KEY_LOW_LATENCY при заявленной поддержке, но корректность не зависит от этого режима.
|
||||
За проход обрабатываются до 32 готовых записей, до восьми output buffers за один вызов pump.
|
||||
Готовый батч и расход PCM будят worker через отдельную condition variable, без JVM callbacks из ядра.
|
||||
Ожидание имеет deadline 5ms при незавершённой работе синхронного MediaCodec, иначе 50ms;
|
||||
уведомление прерывает ожидание сразу. Между готовыми записями sleep нет.
|
||||
Worker владеет signal до stream_stop и отсоединения своего mixer input; detach ядра будит signal, не освобождая его.
|
||||
Video worker проверяет MediaCodec каждые 5ms при незавершённой работе, иначе ждёт до 50ms;
|
||||
audio worker будят media, расход PCM и изменение video state. Без звука его wall clock обновляется каждые 5ms.
|
||||
Между готовыми записями sleep нет. Audio worker владеет signal до stream_stop, join video worker
|
||||
и отсоединения своего mixer input; detach ядра будит signal, не освобождая его.
|
||||
При обычной нехватке данных decoder references сохраняются; GAP/вытеснение требуют нового KEY.
|
||||
Просроченный кадр при нормальной последовательности декодируется без показа.
|
||||
- Фиксированного prebuffer нет. Начало clock/audio output разрешено после первого декодированного кадра.
|
||||
@@ -856,13 +859,13 @@ Android:
|
||||
Заполнение поддерживается до фактического bufferSizeInFrames устройства; API>=31 задаёт start threshold=1.
|
||||
При EOF недописанный PCM передаётся полностью; mixer выдаёт тишину после последнего кадра источника
|
||||
до его физического воспроизведения. END одного input не закрывает AudioTrack остальных.
|
||||
Hold/starvation одного источника добавляет silence span только в его native timeline, не двигая его PTS.
|
||||
Starvation одного источника добавляет silence span только в его native timeline, не двигая его PTS.
|
||||
Видео не удерживает звук после старта; накопившийся из-за тишины избыток погашается ускорением.
|
||||
GAP создаёт новый input/origin, сохраняя общее устройство и часы остальных трансляций.
|
||||
Watchdog 2s проверяет отсутствие движения hardware head только при достаточном заполнении либо заблокированной записи;
|
||||
намеренная пауза и ожидание данных до порога запуска не считаются зависанием. Ошибка содержит состояние и счётчики устройства.
|
||||
Защитный guard минутного контроллера учитывает audio device lead и наблюдённое опережение decoder
|
||||
(максимум last_input_PTS-output_PTS текущей revision плюс период кадра). Drain не обнуляет этот guard;
|
||||
новый decoder начинает измерение заново. Отдельного контроллера задержки декодера нет.
|
||||
Защитный guard аудиоконтроллера — максимум 40ms и audio device lead + 20ms.
|
||||
Наблюдённое опережение decoder остаётся диагностикой и не увеличивает задержку звука.
|
||||
Отсутствие output progress 10s при наличии работы даёт ERROR; сетевые паузы и ожидание PTS допустимы.
|
||||
Состояния ожидания KEY и decoder разделены; логи показывают inputs/decoded/shown, рабочие slots, inflight и decoderLeadUs.
|
||||
Короткие audio gaps заполняются Opus PLC, большой разрыв сбрасывает timeline.
|
||||
@@ -1041,8 +1044,9 @@ Desktop:
|
||||
Stop снимает callback до уничтожения worker; detach будит ожидание перед освобождением manager.
|
||||
- stream_media_cursor собирает ближайший access unit выбранного кодека и выдаёт Opus 48kHz mono/stereo/20ms из RS-кольца.
|
||||
Android AudioTrack и desktop output работают в stereo; mono-пакеты upmix выполняет libopus.
|
||||
FFmpeg/Opus декодируются отдельным worker; Qt-очередь не накапливает кадры.
|
||||
Worker держит один рабочий AVPacket и не более двух готовых изображений. Следующий video request не ограничен часами показа.
|
||||
Opus/SoundTouch и FFmpeg декодируются разными workers каждого player; Qt-очередь не накапливает кадры.
|
||||
Video worker держит один рабочий AVPacket и не более двух готовых изображений; audio worker передаёт ему
|
||||
ближайшие кодированные кадры через ограниченную очередь. Следующий video request не ограничен часами показа.
|
||||
Бюджет нового видео учитывает AVPacket, готовые изображения и оставшиеся кодированные кадры батча.
|
||||
Записи аудио/видео расходуются независимо по готовности потребителя; заполненное видео не блокирует запрос звука.
|
||||
VIDEO_END/AUDIO_END следуют за последними пакетами своего трека и не ждут расходования другого трека.
|
||||
@@ -1051,14 +1055,15 @@ Desktop:
|
||||
Между готовыми пакетами нет sleep или нового round trip к ядру.
|
||||
FFmpeg output обслуживается перед input; EAGAIN сохраняет рабочий packet и означает backpressure, не GAP.
|
||||
Дальние кадры и звук не копируются из кольца. SoundTouch и устройство держат только рабочую порцию PCM.
|
||||
Кадры сохраняются до достижения их PTS аудиочасами; задержка показа удерживает clock только этого player.
|
||||
Видео декодируется без задержки frame-threading. При GAP сбрасываются decoder refs и timeline до KEY.
|
||||
- Первый decoded frame разрешает движение clock/audio, защитный guard учитывает наблюдённый decoder lead.
|
||||
Кадры сохраняются до достижения их PTS аудиочасами; опоздавшие более чем на 100ms отбрасываются до RGB conversion.
|
||||
FFmpeg использует четыре slice threads без frame-threading. При GAP сбрасываются decoder refs и timeline до KEY;
|
||||
поколение video worker исключает публикацию результатов прежнего decoder.
|
||||
- Первый decoded frame разрешает движение clock/audio; затем позднее видео не удерживает звук.
|
||||
VIDEO_END отправляет decoder EOS, AUDIO_END дренирует SoundTouch независимо от видеодекодера.
|
||||
Общий END не управляет сбросом отдельных декодеров: иначе заполненный PCM, ожидание первой картинки и decoder EOS образуют цикл.
|
||||
Выход дренируется теми же ограниченными проходами до EOF, GUI продолжает показ хвоста.
|
||||
После физического воспроизведения последнего PCM оставшееся видео использует монотонные часы;
|
||||
после EOF видеодекодера оставшийся звук больше не удерживается ожиданием картинки.
|
||||
EOF видеодекодера не влияет на независимое воспроизведение оставшегося звука.
|
||||
Ожидающий кадр не теряется при заполненной очереди изображений. Отсутствие прогресса при наличии работы логируется как ошибка.
|
||||
- При начальном подключении desktop/Android прогревают Opus из кольца до первого KEY (до 500ms истории).
|
||||
Старый звук обрезается по PTS видео, включая начало stereo PCM-пакета; декодер не сбрасывается из-за preroll.
|
||||
@@ -1175,23 +1180,30 @@ test_stream_publish проверяет реальные encoder/decoder H.264/H.
|
||||
- AVAILABLE сообщает готовность индекса, DATA/GAP/END callbacks описывают live ingest.
|
||||
media_read выдаёт END после обоих треков конкретного reader. MORE продолжает ограниченную сборку
|
||||
отдельным callback без ожидания новых пакетов; WAIT ожидает новые данные или изменение позиции.
|
||||
- Общий C-контроллер хранит 60 секундных минимумов запаса: ready_PTS - playback_PTS.
|
||||
ready_PTS — меньшая из границ полного видео и звука, для preview без звука — граница видео.
|
||||
Каждое обновление учитывается в минимуме текущей секунды, включая короткий простой.
|
||||
- Декодированный PCM пополняется до 250ms при наличии данных; фиксированного ожидания перед стартом нет.
|
||||
Это запас отдельного audio worker, размер аппаратного буфера не увеличивается. Audio lookahead — device lead + 500ms,
|
||||
достаточный для 250ms PCM даже при x1.6. SPSC имеет 128 слотов по 960 stereo frames с собственными PTS spans.
|
||||
Mixer/callback не вызывает Opus/SoundTouch; Android переиспользует PCM-массив каждого источника.
|
||||
- Общий C-контроллер хранит четыре минимума за интервалы по 50ms: ready_PTS - playback_PTS.
|
||||
ready_PTS — граница готового звука, пока аудиотрек активен; без звука/после AUDIO_END — максимум границ треков.
|
||||
Каждое обновление учитывается в минимуме текущего интервала, включая короткий простой.
|
||||
История нормализована через correction += wall_elapsed - actually_played_media_elapsed.
|
||||
Старые минимумы автоматически увеличиваются на длительность паузы и уменьшаются на реальный расход при догоне.
|
||||
Измерения опираются на PTS фактически услышанного PCM, включая аппаратную очередь и периоды тишины.
|
||||
- После полной здоровой минуты темп плавно повышается до x1.1; SoundTouch сохраняет тон и стерео.
|
||||
Ускорение расходует только минимальный запас за минуту сверх безопасной границы (не менее 33ms,
|
||||
с учётом аппаратной задержки), уже поставленного ускоренного звука и плавного торможения.
|
||||
- После 200ms без фактической нехватки темп плавно повышается до x1.6; SoundTouch сохраняет тон и стерео.
|
||||
Темп пропорционален избытку (масштаб 2s), изменение ограничено x0.6 за 500ms.
|
||||
Ускорение расходует только минимальный запас сверх защитной границы, уже подготовленного/поставленного
|
||||
ускоренного звука и плавного торможения. Каждый источник имеет собственный controller и отображение PTS.
|
||||
При нехватке данных темп возвращается к x1.0, часы ждут, сетевой приём продолжает накапливать запас.
|
||||
После возобновления отсчёт здоровой минуты начинается заново. Разрыв/GAP/новая эпоха сбрасывают историю.
|
||||
После возобновления начинается новое окно 200ms. Разрыв/GAP/новая эпоха сбрасывают историю.
|
||||
- Диагностика stream: PTS, ready, текущий/минимальный запас, correction, healthy interval, tempo,
|
||||
pending gain, wait/resume, generation, причины resync и размеры рабочих очередей. DEBUG — раз в секунду.
|
||||
test_stream_playback проверяет историю, плавный догон с отложенной аппаратной очередью,
|
||||
независимые readers, позднюю повреждённую RS-часть, вытеснение, GAP, FIN и большой многопачечный кадр.
|
||||
test_stream_audio проверяет настоящий стерео Opus/SoundTouch x1.1, сохранение тона/баланса,
|
||||
отображение аппаратного frame counter в исходный PTS и остановку PTS на тишине.
|
||||
test_stream_audio проверяет настоящий стерео Opus/SoundTouch x1.1/x1.6, сохранение тона/баланса,
|
||||
конкурентные producer/consumer, запас 250ms, аппаратный frame counter и остановку PTS на тишине.
|
||||
test_stream_playback моделирует паузы 200ms/4s с отложенным выходом 350ms и проверяет возврат к guard без перерасхода.
|
||||
test_stream_view задерживает видеодекодер на 500ms и проверяет непрерывность аудио.
|
||||
|
||||
21. Суперузлы: помощь в раздаче по запросу
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* feed/prepare/set_tempo/finish — один producer; pull/silence — один consumer.
|
||||
* position/pending_gain сериализуют с consumer короткой внешней блокировкой; pending_gain вызывает producer.
|
||||
* Producer не держит эту блокировку при feed/prepare/finish: callback не ждёт Opus/SoundTouch.
|
||||
* feed прогревает Opus перед start_pts, затем подаёт PCM с темпом 1.0..1.1 без изменения высоты звука.
|
||||
* feed прогревает Opus перед start_pts, затем подаёт PCM с темпом 1.0..1.6 без изменения высоты звука.
|
||||
* pull записывает соответствие кадров устройства исходному PTS; silence продлевает hardware time, но не media time.
|
||||
* position/pending_gain используют реально проигранный frame counter, поэтому уже поставленный PCM сохраняет свой темп.
|
||||
* Последний Opus-пакет/EOF не теряется: finish выталкивает остаток SoundTouch. */
|
||||
@@ -28,7 +28,7 @@ int stream_playback_audio_prepare(struct stream_playback_audio *audio);
|
||||
unsigned stream_playback_audio_buffered(const struct stream_playback_audio *audio);
|
||||
void stream_playback_audio_set_tempo(struct stream_playback_audio *audio, int tempo_milli);
|
||||
int stream_playback_audio_needs_input(const struct stream_playback_audio *audio);
|
||||
/* frames <=8192; limit_pts_us ограничивает продвижение исходного материала до готовой границы видео/аудио.
|
||||
/* frames <=8192; limit_pts_us ограничивает исходный PTS, INT64_MAX разрешает весь подготовленный звук.
|
||||
* Возвращает число stereo frames; оставшиеся места backend заполняет тишиной и вызывает silence. */
|
||||
int stream_playback_audio_pull(struct stream_playback_audio *audio, int16_t *pcm, unsigned frames, int64_t limit_pts_us);
|
||||
void stream_playback_audio_silence(struct stream_playback_audio *audio, unsigned frames);
|
||||
|
||||
Reference in new issue
Block a user