188 lines
18 KiB
Markdown
188 lines
18 KiB
Markdown
# 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 не начата.
|