diff --git a/doc/call_video.txt b/doc/call_video.txt index 3701759f..b27001c6 100644 --- a/doc/call_video.txt +++ b/doc/call_video.txt @@ -688,7 +688,7 @@ Samsung удерживает кадр/следующие encoded frames до н test_call_video_clock exit=0, test_call_video_encoder 13/13 PASS. Диагностика установлена на Samsung, ChatGUI пересобран и перезапущен. Поведение кодеков, очередей, аудиосинхронизации не изменено. -Независимое расписание показа, 15.10.2026 +Независимое расписание показа, 15.10.2026 (история; заменено восстановлением без пропусков ниже) Общий C-модуль call_video_playout принадлежит RX worker, не владеет изображениями/decoder. Последовательные сроки: D[i] = D[i-1] + (PTS[i]-PTS[i-1])*25/26. Локальная received_us ставится на входе RX port в CLOCK_MONOTONIC до ожидания worker; @@ -872,7 +872,7 @@ test_call_video проверяет сочетания PPS flags/extra header bit Новое требование: сохранять последовательность encoded кадров, быстро декодировать пришедший burst и плавно догонять показом. Короткая пауза не должна вызывать пропуск входного P-кадра, ожидание следующего KEY или перескок на более свежее изображение. -Текущая реализация этому требованию не соответствует; в этой итерации добавлена диагностика, +На момент аудита реализация этому требованию не соответствовала; сначала добавлена диагностика, алгоритм буферизации/показа и действующие ограничения не изменены. 1. Router сохраняет порядок, при заполнении RX port приостанавливает доставку/ACK и возобновляет @@ -920,3 +920,56 @@ Windows-диагностика: AudioDiag теперь работает чере время исполнения/интервалы; video RX worker показывает decode и опоздание пробуждения. video late drop содержит точные PTS/AV/возраст первого позднего кадра за окно, playout — диапазоны всех late кадров. Измерения не корректируют Windows callback-estimate аудиочасы. + +Восстановление без пропусков, 19.10.2026 — действующее поведение +Encoded-кадр после принятия сохраняет ID/PTS и владельца до передачи дальше. TX port +удерживает непринятый хвост пачки и повторяет его при уведомлении writable. Новая пачка +не принимается во время обработки старой. Busy=0 не меняет references и не запрашивает KEY; +ошибка цепочки/формата/отказ decoder возвращает -1 и диагностируется отдельно. +Admission ограничивает новые raw-входы encoder, но не запрещает передачу уже готовых кадров. +Router send_q будит flush через отменяемый waiter; audio progress, CAPS ACK и timer — другие источники wake. + +Mailbox: до восьми кадров, каждый <=2MiB; максимальная пачка <=16MiB без предварительного выделения. +Transport сохраняет прежние пределы 32 кадра/500мс PTS/2MiB; RX — 8 кадров/4MiB. +Это верхние границы ёмкости, заполнение не является условием начала передачи/показа. +Полный RX FIFO удерживает BUSY до разгрузки, создавая паузу production для устранения долга. +Обычный поток не проходит этот hysteresis. Длительная перегрузка/обрыв ограничены deadline головы TX 2с: +после него цепочка явно сбрасывается с причиной deadline и запросом KEY, память не растёт бесконечно. + +GPU/MediaCodec отдают готовые выходы независимо от новых кадров камеры. При backpressure +подача raw останавливается до encode; уже принятые GPU-входы продолжают drain в ограниченную очередь. +При смене bitrate сначала полностью забираются выходы старого encoder, затем запускается новый KEY. +Фоновая подготовка desktop сохраняется. Некорректный первый KEY — настоящая ошибка encoder, +а не busy; выводится ошибка и отключается подача вместо бесконечного повторения неисправного режима. +Явные stop/смена режима/отсоединение Surface отменяют соответствующие старые очереди. + +Decoder получает кадры строго последовательно, без искусственных интервалов 30fps между decode. +Готовые изображения остаются ограничены двумя; Android inputs+outputs — восемью. +Основной backlog хранится encoded, а не большим RGB FIFO или удержанием всех аппаратных outputs. + +Playout больше не содержит DROP_LATE/DROP_SCHEDULE. Invalid/order остаётся диагностируемой ошибкой. +CallTimeline публикует rate_ppm из фактического SourceSpan SoundTouch -> PCM на текущей позиции устройства. +База темпа видео max(1x, audio rate), коррекция 2 * max(0, audioPTS-framePTS) ppm, предел 1.6x. +После показа следующий интервал равен deltaPTS/speed; после опоздания отсчитывается от фактической +выдачи, поэтому очередь не выдаётся мгновенной пачкой. После отсутствия готовых кадров привязка снимается: +прошедшее ожидание данных не добавляется второй раз. Дополнительный стартовый резерв не создаётся. +Видео может временно отставать от звука более 50мс, затем догоняет; опережение ограничено 40мс. +Невалидные аудиочасы приостанавливают показ, сохраняют decoder и порядок кадров. + +Desktop сохраняет один queued кадр до paintEvent acknowledgement; serial защищает stop/restart. +Скрытое/свёрнутое окно принимает поток без ожидания paint, физический показ там не обещается. +Android выпускает следующий кадр только после чтения соответствующего SurfaceTexture timestamp +после RenderThread commit (API29+); на API26–28 проверка выполняется через postOnAnimation. +Проверяется Surface identity; detach/stop отменяет ожидание. Commit/paint не измеряют scanout панели. + +Диагностика call=debug: playout speed_ppm/AV/cadence, RX decode/wake, GUI notification/paint wait, +Android awaitingSurfacePts/surfaceWaitMs. TX paused/resumed и RX full/drained показывают границы давления. +Windows WASAPI padding/latency остаются наблюдениями; аппаратная привязка аудио Windows не изменялась. +Для проверки реального Windows тракта нужны обновлённая сборка и новый звонок с call=debug. + +Проверки: test_call_video_playout сохраняет 480/480 кадров при паузах сети/CPU 50/100/200/500мс, +аудиодогоне и недостоверных часах; отдельно моделируется poll с шагом 15.625мс (не замер Windows). +test_call_video_port проверяет частично принятую пачку, повторный busy, отсутствие KEY/spin и RX drain. +test_call_video_flush проверяет bounded burst, событие send_ready, аудиогейт и отмену callbacks. +Qt clock требует 90/90 при RX/GUI-паузах; GPU-тест проверяет каждый исходный PTS через смену bitrate +и равенство decoded + pending входам, без настоящего Windows драйвера. diff --git a/tools/chatgui/tests/test_call_timeline.cpp b/tools/chatgui/tests/test_call_timeline.cpp index 4a5302c6..53528b54 100644 --- a/tools/chatgui/tests/test_call_timeline.cpp +++ b/tools/chatgui/tests/test_call_timeline.cpp @@ -20,8 +20,10 @@ static void test_boundaries() { map.progress(1, 960, 20000, 20000, true); auto clock = map.clock(20000); CHECK(clock.valid && clock.pts_us == 1010000 && clock.written_samples == 1920); + CHECK(clock.rate_ppm == 1000000); map.progress(1, 1200, 25000, 25000, true); CHECK(map.clock(25000).pts_us == 1010000); // Локальная тишина. + CHECK(map.clock(25000).rate_ppm == 0); map.progress(1, 1920, 40000, 30000, true); clock = map.clock(35000); CHECK(clock.valid && clock.pts_us == 1015000 && clock.played_samples == 1680);