Document per-track completion and Android batch wakeups

This commit is contained in:
evgeny committed 2026-10-21 00:13:01 +02:00
1 parent a342316e7a
commit b2efab9806
2 files changed
+24 -6

No files matched your search

+5 -1
View File
@@ -138,10 +138,14 @@ destroy отсоединённого cursor не обращается к store.
Чтение video cursor запрашивает следующий кадр по готовности decoder, независимо от
PTS показа; audio cursor сохраняет временной lookahead. Viewers готовят ограниченный батч
на запрос: отдельно задаются число видеокадров, audio lookahead и число всех записей.
Desktop принимает до 16 записей и обрабатывает треки по их готовности; Android запрашивает одну запись.
Desktop и Android принимают до 16 записей и обрабатывают треки по их готовности.
VIDEO_END/AUDIO_END следуют за последними пакетами своего трека, не ожидая другого трека;
общий END завершает вход, а окно ждёт опустошения обоих выходов. GAP/CLOSED отменяют старый батч.
Получение батча погашает запрос, включая повторные обращения до pull; скрытого чтения следующего батча нет.
Callback готовности только будит desktop worker и не вызывает API ядра/bridge. Stop снимает callback
под mutex viewer до освобождения его контекста; detach будит ожидающие workers до уничтожения manager.
На Android signal принадлежит worker и живёт до stream_stop и close mixer input; ядро только уведомляет его.
В wait не удерживаются mutex bridge/ядра. Расход PCM будит тот же signal, уведомления сливаются без потери пробуждения.
GUI и audio callback будят worker при движении часов/освобождении места; сна между готовыми пакетами нет.
Android worker держит один рабочий input и один готовый output MediaCodec; свободный
input buffer получает лишь для уже готовых данных и сразу возвращает codec.
+19 -5
View File
@@ -829,7 +829,7 @@ Android:
При video pressure отбрасываются целые ожидающие кадры, P-кадры запрещены до нового KEY.
Кодировщик получает отказ admission и запрашивает KEY с ограничением частоты 500ms.
- RX: stream_viewers держит отдельный handle/cursor, demand, status и ограниченный owned батч на session ID.
Android задаёт бюджет в одну запись, соответствующий одному рабочему input StreamDecodePump.
Android принимает до 16 записей: максимум один новый видеокадр и звук в пределах собственного lookahead.
Общей RX FIFO нет: остановка/отставание одного reader не задерживает остальных.
Получение ответа и сетевые AVAILABLE не запускают автоматическое чтение следующего кадра.
Запас остаётся в RS-кольце. want_video запрашивает следующий полный видеокадр независимо от часов показа;
@@ -839,7 +839,11 @@ Android:
Перед каждым входом проверяется выход; свободный input buffer берётся только для уже готового рабочего кадра.
Будущий output ждёт своего PTS и приостанавливает новые video requests; уже запрошенный ответ помещается в рабочий input.
Низкая задержка запрашивается через KEY_LOW_LATENCY при заявленной поддержке, но корректность не зависит от этого режима.
За проход обслуживаются до четырёх media replies, до восьми output buffers за один вызов pump.
За проход обрабатываются до 32 готовых записей, до восьми output buffers за один вызов pump.
Готовый батч и расход PCM будят worker через отдельную condition variable, без JVM callbacks из ядра.
Ожидание имеет deadline 5ms при незавершённой работе синхронного MediaCodec, иначе 50ms;
уведомление прерывает ожидание сразу. Между готовыми записями sleep нет.
Worker владеет signal до stream_stop и отсоединения своего mixer input; detach ядра будит signal, не освобождая его.
При обычной нехватке данных decoder references сохраняются; GAP/вытеснение требуют нового KEY.
Просроченный кадр при нормальной последовательности декодируется без показа.
- Фиксированного prebuffer нет. Начало clock/audio output разрешено после первого декодированного кадра.
@@ -1041,13 +1045,20 @@ Desktop:
Worker держит один рабочий AVPacket и не более двух готовых изображений. Следующий video request не ограничен часами показа.
Бюджет нового видео учитывает AVPacket, готовые изображения и оставшиеся кодированные кадры батча.
Записи аудио/видео расходуются независимо по готовности потребителя; заполненное видео не блокирует запрос звука.
GAP/FIN/CLOSED обрабатываются после предыдущих записей батча. Между готовыми пакетами нет sleep или нового round trip к ядру.
VIDEO_END/AUDIO_END следуют за последними пакетами своего трека и не ждут расходования другого трека.
END подтверждает выдачу обоих треков. Нулевые бюджеты media также разрешают получение управляющих событий.
GAP/CLOSED отменяют прежний батч и сбрасывают frontend сразу; старые media перед ними не доигрываются.
Между готовыми пакетами нет 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.
FIN отправляет decoder EOS; выход дренируется теми же ограниченными проходами до EOF, GUI продолжает показ хвоста.
VIDEO_END отправляет decoder EOS, AUDIO_END дренирует SoundTouch независимо от видеодекодера.
Общий END не управляет сбросом отдельных декодеров: иначе заполненный PCM, ожидание первой картинки и decoder EOS образуют цикл.
Выход дренируется теми же ограниченными проходами до EOF, GUI продолжает показ хвоста.
После физического воспроизведения последнего PCM оставшееся видео использует монотонные часы;
после EOF видеодекодера оставшийся звук больше не удерживается ожиданием картинки.
Ожидающий кадр не теряется при заполненной очереди изображений. Отсутствие прогресса при наличии работы логируется как ошибка.
- При начальном подключении desktop/Android прогревают Opus из кольца до первого KEY (до 500ms истории).
Старый звук обрезается по PTS видео, включая начало stereo PCM-пакета; декодер не сбрасывается из-за preroll.
@@ -1113,7 +1124,10 @@ StreamDecodePumpTest проверяет конвейеры 4/8 кадров пр
test_stream_playback проверяет восемь будущих кадров из кольца без video lookahead; test_android_stream — один ответ
при повторных запросах, отсутствие скрытого prefetch и возобновление с прежней позиции.
test_stream_view дополнительно задерживает четыре настоящих FFmpeg decoded frames: запуск требует кадра после 80ms,
а короткий поток из трёх кадров получает все изображения после FIN, без потери decoder tail.
а короткий поток из трёх кадров получает все изображения после FIN, в том числе при заполненном аудиобуфере.
Проверяются также 8 кадров, отсутствие звука и аудиотрек короче/длиннее видео; завершение ждёт оба выходных хвоста.
StreamReadQueueTest проверяет независимые EOF, отмену старых записей по GAP/CLOSED и границы записей батча.
test_android_stream проверяет батч из 3 video + 3 audio, уведомления без потерь и пробуждение ожидающего worker при stop.
Батчевый сценарий проверяет накопленный поток, раздельные бюджеты треков, независимые readers, уведомления и остановку:
28 video + 50 audio записей проходят через 16 батчей без пропусков/повторов, END следует за последними данными.
Диагностика debug: viewer buffer выводит число/максимальный размер батчей и prepare/handoff (среднее/максимум);