Files
SDR-Rover/docs/video/VIDEO_005.md
2026-09-17 13:34:58 +03:00

188 lines
18 KiB
Markdown
Raw Permalink 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-005 — приём IQ и проверка видеотракта
17 сентября 2026 года. Статус: **PARTIAL**. Это программный эксперимент в
`video-development`, без доступа к SDR и без передачи в эфир. Исходная точка —
`95f6640`; история Git сохранена. Измерения и SHA записаны в
`data/processed/video005/benchmark.json` (seed `20260917`).
## Рабочая цепочка
Приёмник `receive_iq_stream()` получает одномерный complex IQ и выбранный режим
радиоканала. Он не получает границы пакета, момент выборки, истинный CFO/фазу,
payload или CRC. Цепочка: цифровое смещение несущей → согласованный RRC → поиск
известной преамбулы по всему потоку → дробное уточнение момента → оценка CFO и
фазы по преамбуле → разрешение квадранта QPSK → блочное слежение за фазой тела
по решениям QPSK → PHY/внутренний FEC 2/3/CRC → фрагменты → внешний FEC 8+1
с усилением опорного блока → сборка H.264 → декодированные кадры. Эталонные
пакеты и пиксели используются после обработки только для подсчёта ошибок.
Использованы прежние QPSK mapping, RRC, FEC, Viterbi, CRC и видеотранспорт.
Новые поиск преамбулы, восстановление такта и несущей находятся в отдельных
модулях. Порог корреляции 0,5 отсекает наблюдавшиеся боковые пики PRBS7 около
0,4. Формат преамбулы не менялся. `CURRENT PREAMBLE INSUFFICIENT = NO` **только
для проверенной сетки**; это не доказательство устойчивости в эфире.
## Проверки сигнала
На одном полном пакете и в комбинированных трёхпакетных потоках проверены
дробные сдвиги `0`, `±0,1`, `±0,25`, `±0,4` символа; CFO `0`, `±1`, `±5`,
`±20`, `±100` Гц; начальная фаза `0`, `±15`, `±45`, `90`, `180` градусов.
Синтетическое фазовое отклонение тела от 0 до 0,35 рад уменьшалось решающим
QPSK-трекером. Все заявленные строгие проверки восстановили исходный пакет.
Дрейф частоты дискретизации не вводился: `SAMPLE CLOCK OFFSET = NOT MODELED IN
VIDEO-005`.
AWGN, 16 полных пакетов на точку, фиксированная затравка: при `Eb/N0` 0, 3, 6,
9 дБ получено соответственно **0/16, 1/16, 16/16, 16/16** точных CRC-пакетов;
неверных принятых пакетов — 0. Это наблюдение для выбранного потока, не кривая
ошибок или оценка вероятности для любого канала.
`LAB066-LIKE DIAGNOSTIC CHANNEL MODEL`: медиана измеренной неравномерности
полосы 2,870 дБ и средний показатель matched/residual 5,546 дБ. Суррогат
содержит двухотводный FIR с задержкой 8 отсчётов и вторым коэффициентом
0,176194, а также белый остаток. Он дал **30/32** точных CRC-пакетов, неверных
принятых — 0. Фильтр согласован по одному сводному показателю; модель не
воспроизводит распределение помех, меняющийся канал, аппаратные искажения или
саму запись Lab066. Это не измерение RF-приёма.
## Скорость и профиль
Канонический сигнал: 32 полных пакета, 3 886 112 комплексных отсчётов,
8 Мвыб/с, длительность **0,485764 с**, SHA-256 IQ
`d34c4fbba04708180f60ed759cef8bfa9f67827a57ea5ff201d94701bf32afd2`.
Передача 500 ксимв/с, QPSK, inner FEC 2/3. Первый запуск с JIT занял
**1,203 с**. Три прогретых замера `perf_counter()` — 0,281 / 0,299 / 0,268 с;
медиана **0,281 с**, фактор **0,578**, скорость **1,729×** реального времени.
Получено 32/32 пакета с точным SHA и CRC; целевой фактор ≤0,67 выполнен,
предпочтительный ≤0,50 — нет. Эти числа зависят от нагрузки данного ПК.
В таблице времена этапов взяты из последнего прогретого запуска (0,268 с),
проценты относятся к нему. Числа вызовов взяты из отдельного `cProfile`;
его времена не складываются с таблицей. Копии/буферы перечислены по коду,
точное число выделений NumPy не измерялось.
| Этап | Время, мс | Доля | Вызовы | Основные выделения/копии |
|---|---:|---:|---:|---|
| Смещение несущей | 15,3 | 5,7% | 1 | Периодический осциллятор и complex64 baseband, по 3,89 млн отсчётов |
| Согласованный RRC | 61,5 | 22,9% | 1 | Выход свёртки; внутренние FFT-буферы SciPy |
| Поиск преамбулы | 49,2 | 18,4% | 1 | Две корреляции/массивы энергии на прореженных фазах |
| Восстановление такта | 9,2 | 3,4% | 32 | Индексы и один complex64-массив символов на кандидат |
| Оценка CFO/фазы/квадранта | 12,5 | 4,7% | 32 | Корректор и исправленные символы на пакет |
| Проверка PHY-заголовка | 0,6 | 0,2% | 32 | Малый массив заголовка |
| Слежение за фазой QPSK | 49,9 | 18,6% | 32 | Одна копия символов пакета и векторы блоков по 64 |
| Строгий PHY/FEC/CRC | 53,0 | 19,8% | 32 | Мягкие решения, depuncturing и рабочие массивы Viterbi |
В `cProfile` (полный профилированный вызов 0,282 с): слежение QPSK 74,4 мс,
RRC 54,6 мс, поиск 46,6 мс, Viterbi `decode_soft` 28,6 мс, depuncturing
1,41 мс, QPSK soft decisions 0,48 мс и `parse_packet`/CRC 0,36 мс. На чистом
двухсекундном видео внешний FEC занял 1,10 мс, сборка фрагментов 0,86 мс,
декодирование H.264 15,7 мс. Диагностическая сверка пикселей заняла ещё
11,3 мс и исключена из времени рабочего пути. Доли мелких функций из
`cProfile` относятся к 0,282 с; вложенные функции нельзя суммировать.
## Видео 640×360/10
Первые 20 кадров исходного клипа (SHA-256
`651949922042c223375d40bf8929def97dbb62c6ade651d1f5b08eea47127d5f`)
закодированы PyAV/libx264 в H.264 SHORT_GOP 400k. Создано 117 PHY-пакетов;
длительность IQ 1,991 с. Потери и повреждение вносятся в **IQ-интервалы**, до
приёмника. Возраст отсчитывается от захвата кадра до завершения радиопакета.
| Сценарий | CRC-пакеты | Кадры/FPS | Потеря кадров | P50/P95/max, мс | Просрочено | Восстановлено FEC | Опорный кадр |
|---|---:|---:|---:|---:|---:|---:|---:|
| Без потерь | 117 | 20/20; 10,0 | 0% | 101/167/167 | 0 | 0 | — |
| 1% IQ-потерь (факт 1/117) | 116 | 20/20; 10,0 | 0% | 101/167/167 | 0 | 1 | — |
| 5% IQ-потерь (факт 6/117) | 111 | 17/20; 8,5 | 15% | 119/167/167 | 1 | 3 | — |
| Два фрагмента опорного кадра | 115 | 20/20; 10,0 | 0% | 101/167/167 | 0 | 2 | 0 мс |
| Три фрагмента опорного кадра | 114 | 15/20; 7,5 | 25% | 89/167/167 | 1 | 0 | 667 мс до следующего |
| Один испорченный IQ-пакет | 116 | 20/20; 10,0 | 0% | 101/167/167 | 0 | 1 | 0 мс |
Во всех сценариях нет неверного CRC-пакета, неверно собранного или декодированного
кадра и повторного показа старого кадра. После невосстановленной потери
опорного кадра H.264 ждёт следующий опорный кадр. Чистый путь **IQ →
декодированные кадры** имеет фактор **0,576**. Полный офлайн-прогон от чтения
и кодирования источника через формирование IQ и расчёт синтетического канала
до показа имеет фактор **2,153**; его нельзя представлять как скорость одного
приёмника. В этом прогоне 0,317 с заняли чтение/кодирование, 0,597 с — внешний
FEC и PHY передатчика, 0,923 с — формирование IQ, около 1,3 с — канал и около
1,1 с — радиоприём. Сверка эталона в оба фактора не входит.
## CODE QUALITY AUDIT
**BEFORE:** рабочие модули `video003_modem`, `video004_viterbi`,
`video004_erasure` и четыре новых модуля `video005_*` — около 968 строк и
34 функции после реализации; радиофактор до короткой чистки в одном прогоне
0,513. Главные затраты: RRC, поиск преамбулы, слежение за фазой и FEC.
| Проверка или подозрительное место | Где | Почему и категория | Решение |
|---|---|---|---|
| Длина IQ, конечность, параметры режима, границы интерполяции | `video005_receiver.py`, `video005_timing.py` | A: повреждённый вход и выход за буфер | KEEP |
| PHY-заголовок, CRC, возраст, индексы внешнего FEC | `video005_receiver.py`, старые модули | A: обязательные барьеры до видео | KEEP |
| Равенство длин строк матрицы и векторов внешнего FEC | `packet_erasure_fec.py` | A: обрезка `zip()` могла скрыть невозможное состояние | REWRITE с `strict=True` |
| Предварительный PHY-заголовок и повторная проверка в строгом декодере | `video005_receiver.py` | D: длина тела нужна до FEC, строгий разбор обязателен | KEEP |
| Проверка фазовых решений внутри тела | `video005_carrier.py` | E: решения QPSK нужны для слежения | KEEP, блоками по 64 символа |
| Эталонные SHA пакетов и пикселей | `video005_benchmark.py`, `video005_video.py` | C: диагностика не должна решать судьбу кадра | MOVE_TO_DIAGNOSTICS после обработки |
| `complex128` после интерполяции/фазовой коррекции | `video005_timing.py`, `video005_carrier.py` | Лишний объём временных векторов | REWRITE в `complex64` |
| Повторный H.264 decode эталона | `video005_video.py` | C: нужен для точной пиксельной сверки, не для показа | KEEP вне измеряемого пути |
| `LAB066-LIKE`, `cProfile`, графики и подробный JSON | `tools/` | C: офлайн-диагностика | KEEP вне receiver |
| Периодический осциллятор, RRC/FFT-буферы | `video005_receiver.py` | Выделения велики, но RRC быстрее основной цели | KEEP; дальнейшая оптимизация требует отдельного профиля |
**REMOVED / SIMPLIFIED:** временные векторы символов и фазовой коррекции стали
`complex64`; эталон перестал управлять H.264-декодированием; два `zip()`
внешнего FEC теперь проверяют равенство длин. **MOVED TO TESTS /
DIAGNOSTICS:** точные SHA и сверка пикселей остаются в проверочном коде и
выполняются после рабочего прохода. Неиспользуемых импортов Ruff не обнаружил;
декодер и передатчик не содержат Lab066-ветвей или глобального изменяемого
состояния. Кеш коэффициентов RRC неизменяемый. Большие функции сборки видео
остаются в офлайн-инструменте; их разделение сейчас не даст доказанного выигрыша.
**AFTER:** радиофактор 0,578 в финальном запуске; ускорение от изменения dtype
не заявляется из-за разброса времени между прогонами. Строгие пакеты, CRC,
числа кадров и сценарные выходы остались теми же. Прошли 178 тестов,
`ruff`, `pyright` (0 ошибок/предупреждений), `git diff --check` и
`video_gate.py`. Защита от неверных пакетов, индексов и просроченного видео
не удалялась.
Независимый запуск общего `tools/quick_gate.py` дал 1103 пройденных теста,
2 пропуска и один отказ Lab065: в этом worktree отсутствует игнорируемый
исторический вход `data/raw/lab064/tx_metadata.json`. Это ограничение общего
шлюза, а не воспроизведённый отказ VIDEO-005; целевой VIDEO gate прошёл.
## Решение и границы
Предварительная политика без автоматического переключения: GOOD — NORMAL
640×360/10 с 8+1 и усилением опорных блоков; DEGRADED — снизить FPS или
увеличить избыточность; POOR — ROBUST 320×240/5; CRITICAL — отключить видео
или резко снизить поток. Пороги потерь не закреплены: один короткий сценарий
5% дал 17/20 кадров, а суррогат Lab066 не заменяет эфир.
| Итоговое поле | Результат |
|---|---|
| VIDEO-005 STATUS | **PARTIAL**: радиопуть проходит цель, офлайн-генерация медленнее реального времени, есть потери кадров при 5% |
| RAW IQ RECEIVER | **PASS**: 32/32 точных пакета; фактор 0,578 ≤0,67 |
| PREAMBLE ACQUISITION | **PASS** в проверенных потоках |
| TIMING RECOVERY | **PASS** для 0 и ±0,1/0,25/0,4 символа |
| CARRIER FREQUENCY RECOVERY | **PASS** для 0 и ±1/5/20/100 Гц |
| CARRIER PHASE TRACKING | **PASS** в синтетическом тесте изменения фазы |
| QPSK QUADRANT RESOLUTION | **PASS** для 90°/180° и проверенных фаз |
| FEC 2/3 | **PASS**, битовые/пакетные выходы точны |
| OUTER ERASURE FEC | **PASS** при одном и двух стираниях; три не восстановлены |
| 640x360 / 10 FPS END-TO-END | **PARTIAL**: чисто 20/20, при 5% — 17/20; полный офлайн-фактор 2,153 |
| INPUT VIDEO FPS / DISPLAYED FPS / FRAME LOSS RATE | 10 / 10 / 0% чисто; 10 / 8,5 / 15% при 5% IQ-потерь |
| P50 / P95 / MAX FRAME AGE | 101 / 167 / 167 мс чисто; 119 / 167 / 167 мс при 5% |
| RADIO RECEIVER REALTIME FACTOR | 0,578; IQ → декодированные кадры 0,576 в отдельном видеопрогоне |
| END-TO-END VIDEO REALTIME FACTOR | 2,153 от источника через офлайн-канал до кадра |
| RAW IQ DURATION / JIT FIRST RUN TIME / WARM PROCESSING TIME | 0,485764 / 1,203 / медиана 0,281 с |
| MAIN HOT PATH | IQ → RRC → преамбула/такт/несущая → QPSK → FEC/CRC → фрагменты → erasure FEC → H.264 |
| AWGN RESULT | 0/16, 1/16, 16/16, 16/16 точных пакетов при 0/3/6/9 дБ |
| LAB066-LIKE MODEL RESULT | 30/32 точных пакета; диагностический суррогат |
| SAMPLE CLOCK OFFSET | **NOT MODELED IN VIDEO-005** |
| RUFF / PYRIGHT / VIDEO GATE | **PASS / PASS / PASS** |
| BEST NEXT RF CANDIDATE | QPSK 500 ксимв/с, inner 2/3, outer 8+1 с усилением опорного блока, H.264 SHORT_GOP 400k |
| WHY | 20/20 чисто и при одном стирании; нуждается в отдельной проверке устойчивости к 5% и реальным искажениям |
| RF TX / SDR HARDWARE | **0 / NOT ACCESSED** |
| COMMIT / PUSH | **NOT PERFORMED / NOT PERFORMED** |
STOP перед следующим этапом. RF-испытание требует отдельной постановки и
разрешения; VIDEO-006 не начата.