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

295 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 теста и сверка сохранённых результатов.