diff --git a/doc/call_video.txt b/doc/call_video.txt index 36798808..a48c51b8 100644 --- a/doc/call_video.txt +++ b/doc/call_video.txt @@ -63,11 +63,14 @@ Worker хранит pending-команду и применяет её перед команда завершается отказом; нельзя бесконечно продлевать её таймаут. Ограничитель очереди работает и во время ожидания. Если новый IDR не принят, producer запрашивает следующий IDR по существующему контракту send_frame. -Desktop сохраняет старый encoder до готовности кандидата. Android переоткрывает -encoder последовательно (аппаратный ресурс может быть единственным), при отказе -восстанавливает прежнюю конфигурацию и подтверждает фактически восстановленный bitrate. -Допустима пауза картинки; аудио и capture timeline продолжаются. Реальные затраты переключения и -пиковый объём IDR нужно проверить для каждого доступного режима/backend. +Desktop готовит кандидата в отдельном потоке, продолжая кодирование старым encoder. +Готовый кандидат применяется только на IDR; при незавершённой подготовке текущий +GOP продолжается. Android сначала меняет bitrate через MediaCodec.setParameters +без остановки; подтверждает только проверенный KEY с PTS не раньше команды. +При отказе runtime API Android переоткрывает encoder последовательно (аппаратный +ресурс может быть единственным), при ошибке восстанавливает прежнюю конфигурацию +и подтверждает фактически восстановленный bitrate. В этой резервной ветке возможна +пауза картинки; аудио и capture timeline продолжаются. Порядок реализации [+] История первых ACK 500мс/50мс и снимок payload send_q/inflight отдельного сервиса. @@ -344,10 +347,11 @@ pixel format, отсутствие B-кадров и размер. Провер эту проверку bitstream. Automatic-профили трансляций сохраняют прежний выбор GPU/SW. Опции encoder сверены с https://ffmpeg.org/ffmpeg-codecs.html#libx265 и разделом libx264. -CallVideoEncoder принадлежит будущему video worker. Он хранит единственную pending +CallVideoEncoder принадлежит video worker. Он хранит единственную pending команду generation/request/bitrate, отклоняет replay, чужой generation и выход за -согласованный maximumBitrate. На ближайшем IDR по capture PTS создаётся кандидат; -старый encoder сохраняется до получения полного KEY с точным исходным PTS. +согласованный maximumBitrate. После команды кандидат открывается в фоне; +на ближайшем IDR после готовности проверяется полный KEY с точным исходным PTS. +Старый encoder сохраняется до успешной проверки; stop ждёт завершения подготовки. При отказе кандидата возвращается completion с bitrate=0 и используется прежний контекст. Неизменный target также подтверждается на KEY без пересоздания. Completion отделён от отправки кадра: даже при закрытом admission его нужно @@ -525,11 +529,30 @@ ChatGUI пересобран; test_call_video_encoder — 10/10 PASS в кажд Логи: /tmp/call-camera-locale-test-c.log, /tmp/call-camera-locale-test-ru.log. Работающий GUI автоматически не перезапускался; проверка полного звонка после исправления остаётся. -Desktop UI: принимаемый кадр раскрывает окно на весь экран с сохранением пропорций. -Своя камера отображается миниатюрой поверх изображения собеседника; при отсутствии -входящего видео — миниатюрой в обычном окне. Без кадров видеоплощадка не занимает места. -Esc/F11, кнопка и двойной щелчок переключают полноэкранный режим; геометрия окна сохраняется. -Настройки камеры/кодека/битрейта/звука и диагностика свёрнуты под «Настройки звонка». -Preview берётся из того же QVideoFrame, отдельная камера не открывается; обновление до 10 fps. -После 5 секунд без новых показанных RX кадров изображение скрывается: отдельного VIDEO_OFF -в протоколе пока нет. Возобновление видео снова открывает полный экран. +UI и периодические фризы (15.10.2026) +Android: принимаемое видео занимает весь экран, своя камера — миниатюрой поверх него. +Без RX локальная камера видна только миниатюрой на экране аудиозвонка; без кадров +место под видео не резервируется. Касание показывает кнопки, через 5с они скрываются. +Имя/статус/диагностика не рисуются поверх видео; параметры вынесены в «Настройки звонка». +TextureView и Surface сохраняются при показе кнопок; decoder освобождает старый Surface +до его release. Запоздалый detach предыдущего Surface не отключает новый. +Preview берётся из того же Camera2 YUV кадра (до 5 fps), без второй камеры. +Desktop: первый RX кадр увеличивает обычное изменяемое окно, без автоматического fullscreen. +Видео сохраняет пропорции, своя миниатюра находится внутри видеоплощадки, панель — под ней. +Esc/F11, кнопка и двойной щелчок переключают fullscreen вручную; геометрия восстанавливается. +Preview берётся из того же QVideoFrame (до 10 fps). Без RX остаётся лишь своя миниатюра; +без обоих видео — обычное окно аудиозвонка. После 5с без показанных кадров RX скрывается: +отдельного VIDEO_OFF в протоколе пока нет. + +Подтверждённая причина фризов раз в 1–2с: коррекция capture timestamp меняла audio source_epoch, +а обе платформы сбрасывали video decoder и ждали KEY. Теперь source_epoch обновляет +аудиопривязку без потери video references, готовых кадров и последнего показанного PTS. +Отдельный production RX тест: 90/90 кадров, 32 смены аудиоэпохи, 0 дополнительных KEY, +0 decoder rejection (/tmp/call-video-clock-final.log). +Android больше не отбрасывает кадр из-за интервала чуть меньше 33333мкс: Camera2 уже +ограничивает FPS; повторная фильтрация превращала дрожание timestamps в падение до 15fps. +Desktop rate test: 10/10 PASS, непрерывные H.264/H.265 4M -> 300k -> 4M, оба decoder. +H.264 commit 5–7мс; H.265 51–76мс включая кодирование первого кадра, подготовка — в фоне. +Измерение /tmp/call-video-background-test.log; для H.265 стоимость кодирования остаётся существенной. +Android assembleDebug и 81 unit-тест проходят. Полный звонок с камерами после этих правок +требует ручной приёмки; автоматические проверки не подтверждают его целиком. diff --git a/doc/tasks.md b/doc/tasks.md index 869f47a4..7620f525 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -46,7 +46,7 @@ Аппаратные блокеры устранены: общий C validator, AVC Baseline/CB, нормативный DPB, независимые encoder/decoder probes, фактические profile/level, VBV убран из wire. Decoder сообщает acceptance/rejection; Auto делает fallback, отдельный KEY request восстанавливает references. - Android последовательно заменяет encoder на IDR с восстановлением предыдущего режима при отказе. + Android меняет bitrate без остановки MediaCodec на IDR; при отказе API последовательно заменяет encoder с восстановлением. Unisoc кодирует HEVC и AVC; Samsung кодирует AVC и независимо принимает HEVC. Проверены аппаратные 4M -> 300k -> 4M, HEVC Unisoc -> Samsung, AVC Samsung -> Unisoc, все три потока -> production decoder ChatGUI. AVC Unisoc -> Samsung пока вернул 3/4 @@ -55,6 +55,11 @@ 15.10.2026: USB-камера ChatGUI отдаёт кадры; обнаружен и исправлен отказ обоих TX codecs из-за LC_NUMERIC=ru_RU: дробный level 3.1 заменён целочисленным параметром 31. ChatGUI пересобран; Qt codecs 10/10 PASS в C и ru_RU.UTF-8, включая 720p и смену bitrate. + UI исправлен: Android fullscreen RX + своя миниатюра, управление и диагностика отделены; + desktop — большое изменяемое окно с панелью под видео. Без кадров пустая видеоплощадка скрыта. + Фризы: обе платформы сохраняют decoder при коррекции audio epoch; production RX 90/90 кадров, + 32 коррекции часов, 0 KEY requests/rejections. Android Camera2 больше не теряет кадры на пороге 33333мкс. + Desktop готовит encoder при смене bitrate в фоне, применяет на IDR; Qt codecs 10/10 PASS. Осталась ручная приёмка полного звонка с камерами, Surface, A/V и переключениями после исправления. Аппаратные probes используют синтетические кадры. Контракты, этапы и проверки: `doc/call_video.txt`.