# VIDEO-003: видеокодек и радиоформат, программная проверка 16 сентября 2026 года. Worktree `SDR_Rover_Video`, ветка `video-development`, исходный HEAD `af7c05f`. Передача через эфир и обращения к SDR не выполнялись. Число 600 кбит/с здесь служит инженерной целью, а не условием зачёта работы. ## Что проверено Результаты разделены по происхождению: | Уровень | Смысл в этом отчёте | |---|---| | `CALCULATED MAXIMUM` | Арифметика формата PHY, кода, преамбулы, защитных интервалов и паузы при нулевых потерях. | | `IMPLEMENTED` | Действующий генератор Lab045 формирует пакет с нагрузкой `protocol.packet` ровно 256 байт, BPSK 500 ксимв/с, FEC 1/2. VIDEO-003 его не меняет. | | `OFFLINE VERIFIED` | Новый отдельный приёмник декодировал программный сигнал: поиск известной преамбулы, оценка фазы/частоты, PHY-заголовок, FEC и CRC. Это не проверка производственного передатчика или приёмника. | Исходник H.264 тот же, что в VIDEO-001/002: `data/raw/video001/udacity_project_video.mp4`, SHA-256 `651949922042c223375d40bf8929def97dbb62c6ade651d1f5b08eea47127d5f`. Сравнивались два шестисекундных окна. Размеры кадров режима `CURRENT` побайтно совпали с сохранёнными результатами VIDEO-001 во всех шести проверенных сочетаниях окна и разрешения. ## Предел PHY и полезная нагрузка Длина полного пакета в PHY Lab045 ограничена 1024 байтами. Внутри него `protocol.packet` занимает 8 байт заголовка и 4 байта CRC-32. Максимальная нагрузка этого пакета равна `1024 − 8 − 4 = 1012` байтам. Формат VIDEO-002 содержит 17-байтный видеозаголовок, поэтому максимум данных видео в одном фрагменте равен **995 байтам**. Это граница формата; генератор Lab045 пока принимает только 256 байт нагрузки, что оставило бы 239 байт видео в формате VIDEO-002. Производственный TX/RX с фрагментом 995 байт не проверялся. Видеозаголовок VIDEO-002 состоит из флагов версии/типа кадра (1 байт), `stream_id` (4), `frame_id` (4), индекса (2), числа фрагментов (2), возраста кадра (2) и длины данных (2). Поток и номер кадра нужны для разделения потоков и отказа от старых кадров; индекс и число фрагментов нужны при перестановке и потере; тип кадра нужен декодеру; возраст нужен каждому фрагменту для ограничения срока доставки. Длина уже выводится из CRC-проверенного внешнего пакета. Отдельная пробная версия укладывает индекс и `count−1` в байт каждый и убирает повтор длины, сохраняя 32-битные `stream_id` и `frame_id`: 13 байт, экономия 4 байта, или 23,5% заголовка. Она даёт 999 байт видео на пакет и увеличивает верхнюю скорость лишь с 574,149 до 576,457 кбит/с. Это не основной способ увеличить пропускную способность; формат VIDEO-002 остался исходным. ## Радиобюджет Расчёт использует 1280 BPSK-символов преамбулы, 144 символа защищённого PHY-заголовка и 42 символьных интервала защитных областей/RRC. В тело FEC входят все биты полного пакета и шесть хвостовых битов свёрточного кода. Прокалывание применяется к существующему коду R=1/2; фактическое число передаваемых битов посчитано по маске, включая неполный последний период. В QPSK тело несёт два кодовых бита на символ, преамбула и PHY-заголовок остаются BPSK. Оценка занятой полосы `Rs × (1 + 0,35)` учитывает скругление RRC и не является измеренной полосой излучения. Для размеров нагрузки PHY 256, 512, 768 и 1012 байт и пауз 5 / 2 / 1 / 0,5 / 0 мс сохранено 140 строк в `data/processed/video003/design_space.json`. В таблице ниже приведён максимум каждой группы: 1012 байт нагрузки, 0 мс, нулевые потери. | Модуляция, ксимв/с | FEC | Сырая скорость, кбит/с | Эфирное время пакета, мс | Видео, кбит/с | Расчётная полоса, кГц | |---|---:|---:|---:|---:|---:| | BPSK 500 | 1/2 | 500 | 35,724 | 222,819 | 675 | | QPSK 250 | 1/2 | 500 | 38,656 | 205,919 | 337,5 | | QPSK 250 | 2/3 | 500 | 30,460 | 261,326 | 337,5 | | QPSK 250 | 3/4 | 500 | 27,728 | 287,074 | 337,5 | | QPSK 500 | 1/2 | 1000 | 19,328 | 411,838 | 675 | | QPSK 500 | 2/3 | 1000 | 15,230 | 522,653 | 675 | | QPSK 500 | 3/4 | 1000 | 13,864 | **574,149** | 675 | Символ длится 4 мкс при 250 ксимв/с и 2 мкс при 500 ксимв/с. При частоте дискретизации 8 Мвыб/с это 32 и 16 выборок на символ. Для кандидата QPSK 500, FEC 2/3, нагрузка 1012 байт изменение паузы даёт: | Пауза, мс | Эфирное время, мс | Доля времени передачи | Видео, кбит/с | Накладная доля | |---:|---:|---:|---:|---:| | 5 | 15,230 | 75,28% | 393,475 | 60,65% | | 2 | 15,230 | 88,39% | 461,985 | 53,80% | | 1 | 15,230 | 93,84% | 490,450 | 50,96% | | 0,5 | 15,230 | 96,82% | 506,039 | 49,40% | | 0 | 15,230 | 100% | 522,653 | 47,73% | Здесь накладная доля равна `1 − видео-биты / (сырая скорость × период пакета)`; она включает FEC, преамбулу, заголовки и паузу. Нулевой интервал проверен только программно. Передача пакетов без паузы через SDR не разрешена этим опытом. Даже при нулевой паузе, полном пакете и FEC 3/4 максимум **574,149 кбит/с**. Без видеозаголовка получилось бы 583,958 кбит/с. Для перехода за 600 кбит/с при сохранении остальных параметров нужна символьная скорость не ниже **522 513 символов/с**. При неизменных 8 Мвыб/с ближайшее большее целое отношение выборок к символу — 15, то есть 533 333 символа/с; арифметическая скорость тогда составила бы 612,425 кбит/с. Это минимальное изменение одного параметра в расчёте, а не готовая настройка RF: потребуются новый тактовый режим PHY, проверка полосы, синхронизации и скорости обработки. Другие одиночные расчётные варианты: полный пакет не меньше 1248 байт при 500 ксимв/с и FEC 3/4 либо сокращение фиксированной части кадра минимум на 299 символов. Оба требуют изменения PHY и отдельной проверки. ## QPSK и FEC: автономный приём Отображение Gray зафиксировано как `00=(-1−j)/√2`, `01=(-1+j)/√2`, `11=(1+j)/√2`, `10=(1−j)/√2`; энергия каждого QPSK-символа равна единице. Приёмник ищет PRBS7-преамбулу, оценивает частотный сдвиг и начальную фазу только по известным символам, проверяет повторённый PHY-заголовок, затем декодирует тело и CRC. Второе уточнение фазы использует уже проверенный PHY-заголовок. Исходные биты полезной нагрузки передаются только измерителю ошибок после завершения приёма. Проверены поворот на 90°, случайная фаза, сдвиг 73 Гц, шум и поиск после 11 начальных шумовых символов. Отдельный контроль RRC при 250 и 500 ксимв/с прошёл с 32/16 выборками на символ при идеальной тактовой синхронизации; он не доказывает захват тактов из IQ. Прокалывание штатного кода K=7: для 2/3 повторяется маска `1110`, для 3/4 — `111001`, для 1/2 сохраняются все биты. Удалённые биты возвращаются в декодер Витерби как нулевые мягкие метрики. Эталонные векторы, длины кода, включая хвост, декодирование без ошибок и отказ при неверной длине проверены тестами. Код R=1/2 не заменён. AWGN-контроль содержит 32 реализации на каждую точку 0/3/6/9 dB `Eb/N0`, семь сочетаний модуляции/скорости/FEC, всего 896 прогонов, затравка `20260916`. `Es=1`, `Eb=Es × число символов тела / число информационных битов`; учтён и добавочный бит при нечётной длине QPSK-тела. Фиксированные расходы кадра учтены отдельно в радиобюджете. Это сравнение при одинаковом `Eb/N0`, а не при одинаковой мощности или `Es/N0`. BER до FEC считается только для достигнутых тел пакета, BER после FEC — для выданных декодером пакетов; оба знаменателя записаны в JSON. Успех полного пакета и прохождение CRC учитываются отдельно. | QPSK 500 ксимв/с | CRC при 3 dB | CRC при 6 dB | CRC при 9 dB | |---|---:|---:|---:| | FEC 1/2 | 26/32 | 32/32 | 32/32 | | FEC 2/3 | 13/32 | 32/32 | 32/32 | | FEC 3/4 | 3/32 | 32/32 | 32/32 | Нулевая частота ошибок в 32 реализациях не доказывает малую вероятность потери на длинном потоке. Ставка 3/4 повышает расчётную скорость, но на 3 dB в этом опыте уступила 2/3 по прохождению CRC. Дополнительно переданы **32 последовательных максимальных пакета** без межпакетной паузы через программный канал с 42 переходными символами на пакет. При `Eb/N0=9 dB` и сдвиге 73 Гц QPSK 500 с FEC 2/3 и 3/4 получили по 32/32 CRC и по 32/32 правильно разобранных видеозаголовка. Приёмник выводил длину очередного пакета из принятого PHY-заголовка и не получал границы или payload от генератора. Полезные скорости коротких потоков: **522,653** и **574,149 кбит/с** за 0,487 и 0,444 с сигнального времени. Время программной обработки оказалось в **5,57** и **6,20** раза больше длительности сигнала. Поэтому проверен короткий автономный поток, а обработка в реальном времени и длительная устойчивая доставка — **NOT_RUN**. Исходной IQ-записи Lab066 в данном worktree нет. Частотная неравномерность по её сводным JSON не воспроизводится однозначно; отдельная модель по Lab066 не строилась. AWGN не объявляется эквивалентом OTA-канала. ## H.264 через PyAV Использован **PyAV 16.0.1** с библиотеками FFmpeg: `libavcodec 62.11.100`, `libavformat 62.3.100`, `libavutil 60.8.100`. FFmpeg CLI не вызывался. Для каждого из 60 прогонов рядом с размерами кадров сохранены имя кодека, разрешение, частота кадров, формат пикселей, целевой и предельный потоки, размер VBV, GOP, число B-кадров, `preset`, `tune`, фактический профиль, `intra-refresh`, `time_base` и точные `x264-params`. Профиль всех проверенных потоков декодер определил как `High`; B-кадров нет. `CURRENT` повторил VIDEO-001 с GOP 1 с и VBV 1 с. `CURRENT_VBV`, `SHORT_GOP` и `INTRA_REFRESH` проверены при 300/400/500 кбит/с и VBV 0,2 с. Короткий GOP равен 5 кадрам при 10 кадрах/с и 3 кадрам при 5 кадрах/с. Запрошенный intra refresh уменьшил отдельные пики, но в испытании с потерей кадра восстанавливал точное изображение позже короткого GOP. В таблице приведено худшее из двух окон для потока и размера кадра, худшее время восстановления после удаления одного кадра и меньшее среднее PSNR из двух окон. Пик за 100 мс отражает один крупный кадр, его нельзя подменять средним потоком. | Режим | H.264 | Средний, кбит/с | Пик 100 мс | Пик 1 с | Макс. кадр, байт | P95 кадра, байт | Восстановление, мс | PSNR, dB | |---|---|---:|---:|---:|---:|---:|---:|---:| | NORMAL | CURRENT | 354,0 | 1116,1 | 375,8 | 13951 | 12784 | 900 | 33,8 | | NORMAL | SHORT_GOP 400k | 361,4 | 740,2 | 408,8 | 9252 | 9114 | 400 | 33,3 | | HIGH QUALITY | CURRENT | 357,2 | 1034,6 | 455,6 | 12933 | 7892 | 900 | 33,2 | | HIGH QUALITY | SHORT_GOP 400k | 391,8 | 751,7 | 427,1 | 9396 | 9080 | 400 | 33,1 | | 720p/5 | CURRENT | 345,5 | 1164,0 | 440,6 | 14550 | 11653 | 800 | 33,0 | | 720p/5 | SHORT_GOP 400k | 340,2 | 736,6 | 345,5 | 9208 | 9122 | 600 | 32,1 | Порог 300 кбит/с снижал размер пиков сильнее, но ухудшал PSNR. Порог 500 кбит/с повышал пиковый поток и требовал большего радиобюджета. Вариант `SHORT_GOP 400k` выбран для совместного расчёта по размеру кадров и сроку восстановления, без утверждения о проверенном операторском качестве. Контрольных сцен с мелкими препятствиями и оценки оператором не было. ## Сопоставление видео и радио Измерения VIDEO-001/002 и требуемые запасы: | Видео | Средний, кбит/с | Пик 1 с, кбит/с | Нужно +20%, кбит/с | Нужно +50%, кбит/с | |---|---:|---:|---:|---:| | ROBUST 320×240/5 | 117,2 | 171,7 | 206,0 | 257,5 | | NORMAL 640×360/10 | 354,0 | 375,8 | 451,0 | 563,7 | | HIGH QUALITY 854×480/10 | 357,2 | 455,6 | 546,7 | 683,3 | | 720p/5 | 345,5 | 440,6 | 528,8 | 661,0 | Для расчётного QPSK 500, FEC 2/3, пакет 1024 байта, пауза 0 мс исходные пики дают запас `522,653/peak`: NORMAL 1,391, HIGH QUALITY 1,147, 720p/5 1,186. После `SHORT_GOP 400k` пики 408,8 / 427,1 / 345,5 кбит/с дают запас **1,278 / 1,224 / 1,512**. По одному лишь расчётному фильтру все три превышают 1,2; при исходном кодировании HIGH QUALITY и 720p/5 порог 1,2 не проходили. Эти числа не учитывают ошибки PHY, занятость процессора и серийные потери пакетов. Модель VIDEO-002 повторена на настоящих H.264 пакетах с рассчитанным временем передачи каждого полного пакета. Очередь ограничена двумя кадрами, срок — 300 мс, потери 0/1/2/5/10% независимы по передаваемому пакету, фиксированная затравка `20260916`. Отдельно сохранены серии из 2/5/10 потерянных пакетов; их нельзя трактовать как независимую вероятность. Ниже для `SHORT_GOP 400k + QPSK 500 / FEC 2/3 / 1012 байт / 0 мс` показано число отображённых кадров в окнах «белая / чёрная машина»: | Потеря пакетов | NORMAL, из 60 | HIGH QUALITY, из 60 | 720p/5, из 30 | |---:|---:|---:|---:| | 0% | 60 / 60 | 60 / 60 | 30 / 30 | | 1% | 54 / 55 | 56 / 55 | 27 / 25 | | 2% | 45 / 42 | 47 / 46 | 23 / 20 | | 5% | 27 / 22 | 28 / 25 | 11 / 12 | | 10% | 16 / 16 | 16 / 13 | 5 / 5 | Без потерь максимальные и P95 возрасты показанных кадров в этих прогонах не превысили 152,3 мс; сбросов по устареванию не было. При потере пакетов возраст остаётся ограниченным, но неполные кадры не показываются. При 5% потерь до оператора доходит меньше половины кадров NORMAL и HIGH QUALITY в одном или обоих окнах. Время восстановления после первой потерянной части записано отдельно для каждого прогона в JSON; например, при 1% потерь диапазон для этих трёх режимов составил 252–752 мс. Это конкретные короткие реализации, а не оценка вероятности для длительного канала. ## Статус и ограничения | Поле | Результат | |---|---| | `VIDEO-003 STATUS` | **PARTIAL**: программный PHY и видео проверены по отдельности и в модели доставки; производственный TX/RX, real-time и OTA не проверены. | | `MAX PHY PACKET SIZE` | 1024 байта полного пакета. | | `CURRENT IMPLEMENTED PAYLOAD LIMIT` | Ровно 256 байт нагрузки `protocol.packet` у генератора Lab045; видео в производственный TX/RX не встроено. | | `MAX CALCULATED VIDEO PAYLOAD` | 995 байт при текущем 17-байтном заголовке. | | `BEST H264 PROFILE` | `SHORT_GOP 400k`, GOP 0,5 с при 10 кадрах/с, VBV 0,2 с; операторское качество не проверялось. | | `BEST BPSK CONFIGURATION` | 500 ксимв/с, FEC 1/2, PHY payload 1012 байт, 0 мс: 222,819 кбит/с **только расчёт**; действующий размер 256 байт и пауза 5 мс дают 115,654 кбит/с при нулевых потерях. | | `BEST QPSK 250K CONFIGURATION` | FEC 3/4, payload 1012 байт, 0 мс: 287,074 кбит/с **только расчёт**. | | `BEST QPSK 500K CONFIGURATION` | По скорости FEC 3/4, payload 1012 байт, 0 мс: 574,149 кбит/с; по балансу с ошибками и `SHORT_GOP 400k` кандидат FEC 2/3: 522,653 кбит/с. Оба только программные. | | `BEST FEC RATE` | **2/3 как следующий диагностический кандидат**; при 3 dB получил 13/32 CRC против 3/32 у 3/4, а расчётный поток после смены GOP даёт запас более 1,2 для трёх видеорежимов. | | `BEST CALCULATED USEFUL RATE` | 574,149 кбит/с при нулевых потерях. | | `BEST OFFLINE-VERIFIED USEFUL RATE` | 574,149 кбит/с на коротком 32-пакетном синтетическом потоке при 9 dB, 32/32 CRC; CPU/signal = 6,20, поэтому это **не real-time goodput**. | | `600 KBIT/S TARGET WITH CURRENT PHY` | `NOT_REACHABLE` в проверенной матрице при пакете до 1024 байт, скоростях до 500 ксимв/с и FEC до 3/4. | | `MINIMUM ARCHITECTURAL CHANGE REQUIRED` | Для арифметического превышения 600 кбит/с при FEC 3/4 поднять скорость минимум до 522 513 символов/с; при Fs=8 Мвыб/с и целых выборках на символ следующий вариант 533 333 символа/с (15 выборок/символ). Требуются новые PHY/RX и тесты. | | `NORMAL VIDEO FITS WITH 20% HEADROOM` | `YES` только в расчёте для `SHORT_GOP 400k + QPSK 500/FEC 2/3/1012/0`: запас 1,278. | | `HIGH QUALITY VIDEO FITS WITH 20% HEADROOM` | `YES` только в том же расчёте: 1,224; исходный режим VIDEO-001 давал 1,147. | | `720P5 FITS WITH 20% HEADROOM` | `YES` только в том же расчёте: 1,512; исходный режим давал 1,186. | | `BEST NEXT RF CANDIDATE` | Предмет **отдельной разработки и будущего разрешённого опыта**: QPSK 500 ксимв/с, FEC 2/3, полный пакет 1024 байта, пауза 0 мс, `SHORT_GOP 400k`. Сейчас real-time декодирование и устойчивость к потерям не подтверждены. | | `WHY` | 2/3 заметно лучше 3/4 в AWGN-контроле 3 dB; расчёт 522,653 кбит/с покрывает пики нового H.264 с запасом ≥1,2. В модели при 0% потерь показаны все кадры; при 5% большая доля кадров теряется. | | `ENCODER API` | PyAV 16.0.1; версии библиотек и точные параметры каждого прогона — в `codec_results.json`. | | `FFMPEG CLI USED` | `NO`. | | `VIDEO-SPECIFIC GATE` | `PASS`: 123 целевых теста, сверка результатов, импортов и отсутствия аппаратных импортов в проверяемых модулях. | | `RF TX` | `0`. | | `COMMIT` / `PUSH` | `NOT PERFORMED` / `NOT PERFORMED`. | ## Файлы и повторение - `protocol/punctured_fec.py`, `protocol/video003_modem.py`: автономный кодер и приёмник; производственный BPSK и SDR receiver не изменены. - `protocol/video003_compact_header.py`: отдельная проба 13-байтного заголовка, версия VIDEO-002 остаётся исходной. - `tools/video003_design.py`: `design_space.json` и точный расчёт. - `tools/video003_synthetic.py`: `synthetic_phy.json`, 896 реализаций AWGN. - `tools/video003_stream.py`: `continuous_stream.json`, короткий непрерывный поток. - `tools/video003_codec.py`: `codec_results.json`, 60 прогонов PyAV. - `tools/video003_transport.py`: `transport_results.json`, 784 прогона доставки. - `tools/video_gate.py`: целевой шлюз проверки без исторических RF-данных. Запуск из корня worktree после установки `requirements-video.txt`: ```powershell python -B -X utf8 -m tools.video003_design python -B -X utf8 -m tools.video003_synthetic python -B -X utf8 -m tools.video003_stream python -B -X utf8 -m tools.video003_codec python -B -X utf8 -m tools.video003_transport python -B -X utf8 -m tools.video_gate ``` Последние две программы читают результаты предыдущих. `video_gate` проверяет только файлы VIDEO-001/002/003 и используемые модули `protocol`, запускает тесты без аппаратных entry point. Статический запрет аппаратных импортов в этих модулях и отсутствие аппаратного запуска в перечисленных командах не служат доказательством качества радиоканала. Следующий опыт с RF требует отдельного прямого разрешения и новой подготовки PHY. При независимой проверке общий `python tools/quick_gate.py` завершился с ошибкой: 1059 тестов прошли, один тест Lab065 и его функциональная проверка не нашли исторический `data/raw/lab064/tx_metadata.json` в VIDEO worktree. Этот файл не создавался для VIDEO-003. Целевой `video_gate` прошёл отдельно: 123 теста и сверка сохранённых результатов.