Files
SDR-Rover/docs/video/VIDEO_002.md

19 KiB
Raw Blame History

VIDEO-002: транспорт H.264 и расчёт радиоканала

16 сентября 2026 года. Ветка video-development. Выполнен только программный прогон: RF TX = 0. Модуляция, FEC, PHY-заголовок, RRC и рабочий приёмник SDR не менялись. Коммит и отправка в удалённый репозиторий не выполнялись.

Исходные данные и предел проверки

Тот же ролик и те же окна движения, что в VIDEO-001: data/raw/video001/udacity_project_video.mp4, SHA-256 651949922042c223375d40bf8929def97dbb62c6ade651d1f5b08eea47127d5f; белая машина на 7–13 с и чёрная на 33–39 с. Кодировщик PyAV/libx264 повторно создал пакеты H.264 с настройками VIDEO-001. Размер каждого кадра сверен с comparison_traffic_160k.json или comparison_traffic_320k.json. Исходные окна имеют по 6 с: 30 кадров ROBUST и 60 кадров NORMAL/HIGH QUALITY. Сырые видеоданные в Git не включены. Результат 198 прогонов находится в data/processed/video002/results.json; запуск:

python -m tools.video002_simulation
python -m pytest tests/test_video002_transport.py tests/test_video002_codec.py -q -p no:cacheprovider

Прогон моделирует длительность пакета и паузу, подаёт фрагменты на сборщик и декодирует полные кадры настоящим декодером H.264. Он не моделирует ошибки синхронизации, шум, вероятность CRC-успеха, работу независимого SDR-приёмника и время CPU для FEC. Контрольная программная линия SOFTWARE_2MBPS передаёт нагрузку 1024 байта за 4,096 мс без RF и нужна для отдельной проверки потерь.

Формат и правило свежести

protocol/video_stream_transport.py добавляет 17-байтный заголовок внутри полезной нагрузки проверенного пакета. Он не заменяет штатные 8 байт заголовка protocol.packet и 4 байта CRC:

Поле Байты Назначение
Версия и тип кадра 1 Старшие 4 бита — версия 1; младшие — KEYFRAME=1 или DELTA_FRAME=2
stream_id 4 Выбор сеанса сборщика
frame_id 4 Номер с последовательным сравнением и переходом через 2³²
fragment_index, fragment_count 2 + 2 Порядок и общее число, максимум 256
age_ms 2 Возраст кадра на расчётном конце передачи пакета
payload_length 2 Проверяемая длина части H.264

При нагрузке PHY 256 байт остаётся 239 байт изображения; при 512 — 495, при 1024 — 1007. На стороне передатчика очередь ограничена двумя кадрами и 300 мс: старый кадр сбрасывается даже после частичной отправки, если к округлённому моменту конца следующего пакета он станет просроченным. Сборщик держит максимум два незавершённых кадра, принимает части в произвольном порядке, проверяет длины и противоречивые дубликаты, не выдаёт неполный кадр и по истечении срока освобождает место. Потеря одного фрагмента не останавливает приём следующих кадров. Сборщик получает данные только после внешнего решения PHY/FEC/CRC; stream_id сам по себе не аутентифицирует отправителя. Номер последнего принятого к сборке кадра не позволяет старому пакету снова стать новым даже после вытеснения 1024 номеров из журнала закрытых кадров. После перезапуска нужен новый контекст сборщика/сеанса.

Декодер показывает кадр только один раз. После пропуска номера он ждёт полный опорный кадр и открывает новый контекст H.264. Это осторожное правило: некоторые P-кадры кодек мог бы восстановить и раньше, но подменять потерянные данные или показывать повреждённую картинку оператору здесь не разрешено. Показанные опорные кадры побайтно совпали по SHA-256 с чистым декодированием соответствующего окна, включая случаи восстановления после потери.

Чистый прогон при возрасте не более 300 мс

Показаны результаты окон «белая / чёрная машина». Возраст — от захвата исходного кадра до завершения последнего пакета, без времени кодирования, декодирования и экрана. drop — сброс отправителем по возрасту / по переполнению. Все эти строки имеют 0% искусственных потерь пакетов.

Режим Канал модели Показано кадров Возраст, среднее, мс Макс. очередь drop
ROBUST 320×240/5 BPSK 256/5 мс 0/30 · 0/30 — 2 6/0 · 9/0
NORMAL 640×360/10 BPSK 256/5 мс 0/60 · 0/60 — 2 2/58 · 2/57
HIGH QUALITY 854×480/10 BPSK 256/5 мс 0/60 · 0/60 — 2 2/58 · 2/58
ROBUST QPSK 500k, 1024/0 мс, расчёт 30/30 · 30/30 53,4 · 65,7 1 0/0 · 0/0
NORMAL QPSK 500k, 1024/0 мс, расчёт 0/60 · 20/60 — · 115,8 2 0/6 · 0/4
HIGH QUALITY QPSK 500k, 1024/0 мс, расчёт 40/60 · 40/60 96,0 · 98,7 2 0/4 · 0/4
ROBUST Программные 2 Мбит/с 30/30 · 30/30 11,2 · 13,8 1 0/0 · 0/0
NORMAL Программные 2 Мбит/с 60/60 · 60/60 19,2 · 20,0 1 0/0 · 0/0
HIGH QUALITY Программные 2 Мбит/с 60/60 · 60/60 19,7 · 20,2 1 0/0 · 0/0

При нынешнем BPSK крупнейшие опорные кадры ROBUST занимают 397 и 479 мс (ceil(размер/239) × (11,532+5)), NORMAL — 926 и 975 мс, HIGH QUALITY — 909 и 893 мс. Поэтому чистая модель с пределом 300 мс не декодирует их. Отказ NORMAL на расчётной QPSK в одном окне также показывает, что запас по среднему потоку нельзя считать гарантией прохождения опорных кадров.

Потери пакетов и восстановление

Затравка генератора 20260916; вероятность относится к передаваемому пакету. Ниже число показанных кадров на контрольной программной линии в окнах «белая / чёрная машина» из 30 или 60 исходных. burst удаляет первые 2/5/10 пакетов потока. JSON содержит каждую из 198 комбинаций, в том числе те же потери на двух расчётных радиопрофилях, номера показанных кадров, потери кадров, время восстановления, возраст, глубину очереди и сбросы.

Потеря ROBUST NORMAL HIGH QUALITY
Случайная 0% 30/30 · 30/30 60/60 · 60/60 60/60 · 60/60
Случайная 1% 30/30 · 30/30 55/60 · 51/60 48/60 · 47/60
Случайная 2% 26/30 · 25/30 39/60 · 33/60 39/60 · 38/60
Случайная 5% 21/30 · 19/30 6/60 · 5/60 18/60 · 27/60
Случайная 10% 15/30 · 19/30 5/60 · 5/60 12/60 · 11/60
Случайная 20% 0/30 · 0/30 0/60 · 0/60 0/60 · 0/60
burst 2/5/10 пакетов 25/30 · 25/30 50/60 · 50/60 50/60 · 50/60

Отдельные сценарии с потерей первого фрагмента опорного кадра №5/10 и P-кадра №6/11 подтвердили восстановление на следующем полном опорном кадре №10/20. На программной линии после потери опорного кадра это заняло от 1025 до 1057 мс, после потери P-кадра — от 825 до 957 мс. Значения включают ожидание следующего GOP длиной 1 с и доставку его первого кадра. При случайной потере 20% ни один полный опорный кадр в этих коротких окнах не прошёл: время восстановления не определено. Скрытых повторов старого frame_id нет; число разных изображений и их SHA-256 записаны в результате.

Расчёт радиопакета

Основа Lab045/VIDEO-001: 1280 символов преамбулы, 144 символа трёхкратного PHY-заголовка, 42 интервала защитных областей и RRC; protocol.packet добавляет 12 байт (заголовок и CRC), свёрточный FEC 1/2 кодирует также 6 хвостовых бит. Для нагрузки PHY P байт тело содержит 2 × ((P+12) × 8 + 6) кодовых бит. BPSK передаёт один бит на символ. Расчётная QPSK оставляет преамбулу и PHY-заголовок двоичными и передаёт тело по два бита на символ; такой смешанный пакет не реализован и не проверен. Все строки считают полный пакет даже для последнего неполного фрагмента, поэтому оценка задержки консервативна. Накладная доля — 1 − полезные биты изображения / (сырая скорость × период пакета с паузой); она включает паузу, служебные поля и FEC.

Модуляция, ксимв/с Сырая скорость, кбит/с Символ, мкс Оценка ширины при RRC 0,35, кГц
BPSK 500 500 2 675
QPSK 250 500 4 337,5
QPSK 500 1000 2 675

В каждой ячейке ниже: эфирное время пакета, мс / полезная скорость видео, кбит/с / накладная доля, %. Пауза в заголовке столбца дана в миллисекундах.

Модуляция PHY, байт 5 мс 2 мс 1 мс 0 мс
BPSK 500 256 11,532 / 115,7 / 76,9 11,532 / 141,3 / 71,7 11,532 / 152,6 / 69,5 11,532 / 165,8 / 66,8
BPSK 500 512 19,724 / 160,2 / 68,0 19,724 / 182,3 / 63,5 19,724 / 191,1 / 61,8 19,724 / 200,8 / 59,8
BPSK 500 1024 36,108 / 196,0 / 60,8 36,108 / 211,4 / 57,7 36,108 / 217,1 / 56,6 36,108 / 223,1 / 55,4
QPSK 250 256 14,464 / 98,2 / 80,4 14,464 / 116,1 / 76,8 14,464 / 123,6 / 75,3 14,464 / 132,2 / 73,6
QPSK 250 512 22,656 / 143,2 / 71,4 22,656 / 160,6 / 67,9 22,656 / 167,4 / 66,5 22,656 / 174,8 / 65,0
QPSK 250 1024 39,040 / 182,9 / 63,4 39,040 / 196,3 / 60,7 39,040 / 201,2 / 59,8 39,040 / 206,4 / 58,7
QPSK 500 256 7,232 / 156,3 / 84,4 7,232 / 207,1 / 79,3 7,232 / 232,3 / 76,8 7,232 / 264,4 / 73,6
QPSK 500 512 11,328 / 242,5 / 75,7 11,328 / 297,1 / 70,3 11,328 / 321,2 / 67,9 11,328 / 349,6 / 65,0
QPSK 500 1024 19,520 / 328,5 / 67,1 19,520 / 374,3 / 62,6 19,520 / 392,6 / 60,7 19,520 / 412,7 / 58,7

Текущая конфигурация — первая ячейка: 115,7 кбит/с видео при 100% доставке. В VIDEO-001 фигурировали 118,1 кбит/с JPEG, поскольку его фрагментный заголовок занимает 12, а новый H.264 — 17 байт. Один сеанс Lab066 доставил 10/16 пакетов; это наблюдение не является постоянной вероятностью доставки и не подставлено в расчёт. Предельный размер всего пакета PHY сейчас 1024 байта: нагрузка 1024 плюс 12 байт protocol.packet его превышает. Lab045 в действующем плане формирует нагрузку ровно 256 байт; строки 512/1024 потребуют разработки и проверки даже при арифметическом соблюдении размера. Уменьшение паузы также не проверялось через радио.

Запас относительно реальных пиков VIDEO-001

Максимум односекундного видеопотока среди двух окон приведён в таблице. Здесь «запас 20%» определён как полезная скорость ≥ пик × 1,2, «запас 50%» — как ≥ пик × 1,5.

Режим Пик, кбит/с Нужно при 20%, кбит/с Нужно при 50%, кбит/с Вывод для предела 500 кбит/с
ROBUST 320×240/5 171,7 206,0 257,5 Оба запаса возможны только в ещё не проверенных вариантах
NORMAL 640×360/10 375,8 451,0 563,7 20% да, 50% нет
640×480/10 380,9 457,1 571,4 20% да, 50% нет
HIGH QUALITY 854×480/10 455,6 546,7 683,3 Даже 20% нет
1280×720/5 440,6 528,8 661,0 Даже 20% нет

Из рассчитанных пакетов 20% запаса для ROBUST дают, например, BPSK 500/1024/0 (223,1 кбит/с) или QPSK 500/256/0 (264,4 кбит/с); 50% — только некоторые QPSK 500. Все эти варианты требуют разработки и проверки. Максимум всей таблицы, QPSK 500/1024/0, равен 412,7 кбит/с и не покрывает 20% запас для NORMAL, 640×480, HIGH QUALITY или 1280×720. Сам инженерный диапазон 400–500 кбит/с покрывает 20% лишь для NORMAL и 640×480 в своей верхней части. Расчёт не разрешает называть ни один из режимов прошедшим по текущему радиоканалу.

Итог VIDEO-002

Требуемое поле Результат
VIDEO TRANSPORT PARTIAL: формат, очередь, сборка и H.264 работают в программной модели; на текущем радиобюджете чистый 300-мс прогон не показывает кадров
BOUNDED QUEUE YES, максимум 2 кадра
STALE FRAME DROP YES, срок 300 мс, метрики в JSON
KEYFRAME RECOVERY На контрольной линии после потери IDR кадр №10/20, 1025–1057 мс; SHA-256 совпал с чистым декодированием
LOSS TESTS 0/1/2/5/10/20% и серии 2/5/10 пакетов, фиксированная затравка, два окна, три видеорежима, три канала модели
CURRENT PHY USEFUL RATE 115,7 кбит/с H.264 при 256 байтах, 5 мс, без потерь; измеренной устойчивой скорости H.264 нет
BEST BPSK PACKETIZATION CANDIDATE 1024 байта / 0 мс: расчёт 223,1 кбит/с, но полный пакет 1036 байт превышает действующий предел; среди допустимых по размеру 512/0 даёт 200,8 кбит/с
QPSK 250K CALCULATED RATE Максимум 206,4 кбит/с при 1024/0; пакет сверх действующего предела
QPSK 500K CALCULATED RATE Максимум 412,7 кбит/с при 1024/0; пакет сверх предела, пик NORMAL без 20% запаса
TARGET VIDEO RADIO BUDGET 400–500 кбит/с как инженерная цель, не достигнутый результат; для HIGH QUALITY с 20% требуется ≥546,7 кбит/с, для 1280×720/5 — ≥528,8 кбит/с
NEXT RF DEVELOPMENT CANDIDATE BPSK 500 ксимв/с, нагрузка 512 байт, пауза 0 мс: один конкретный следующий предмет отдельной разработки и последующей проверки независимого приёма. Теоретический предел 200,8 кбит/с, робастный пик с 20% запасом не покрыт. VIDEO-002 не разрешает RF TX
RF TX 0
COMMIT / PUSH NOT PERFORMED / NOT PERFORMED

Проверка после исправлений: 11 целевых тестов VIDEO-002 и 4 теста VIDEO-001 прошли. Независимый проверяющий повторил все 198 симуляций и все 36 расчётных строк; результат совпал с сохранённым JSON. Общий tools/quick_gate.py в этом рабочем дереве не прошёл: у исторических аппаратных лабораторий нет data/raw/lab064/tx_metadata.json и других исходных файлов, а системный временный каталог pytest недоступен для части тестов. Целевые тесты запускались с -p no:cacheprovider; для тестов VIDEO-001 временный каталог pytest был явно направлен в это рабочее дерево. Никакая из этих проверок не запускала RF.