Complete VIDEO-001 through VIDEO-004 software video studies
This commit is contained in:
209
docs/video/VIDEO_002.md
Normal file
209
docs/video/VIDEO_002.md
Normal file
@@ -0,0 +1,209 @@
|
||||
# VIDEO-002: транспорт H.264 и расчёт радиоканала
|
||||
|
||||
16 сентября 2026 года. Ветка `video-development`. Выполнен только программный прогон:
|
||||
`RF TX = 0`. Модуляция, FEC, PHY-заголовок, RRC и рабочий приёмник SDR не менялись.
|
||||
Коммит и отправка в удалённый репозиторий не выполнялись.
|
||||
|
||||
## Исходные данные и предел проверки
|
||||
|
||||
Тот же ролик и те же окна движения, что в [VIDEO-001](VIDEO_001.md):
|
||||
`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`; запуск:
|
||||
|
||||
```powershell
|
||||
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.
|
||||
Reference in New Issue
Block a user