# VIDEO-001: программный предел видеотракта 16 сентября 2026 года. Ветка `video-development`, исходный HEAD `af7c05f`. `RF TX = 0`. SDR, камеры и экран не запускались. Основной `main`, старые результаты и исходные IQ не менялись. Таблицы ниже относятся к этому компьютеру и одному ролику; они не доказывают работу живого видео через радио. ## Что уже работает | Узел | Файл и назначение | Зависимости и измеренное состояние | |---|---|---| | Подготовка JPEG | `experiments/lab047_jpeg_object_transport.py`, `experiments/lab050_video_stream.py`: уменьшение, RGB, JPEG | Pillow; Lab047: 320×240 q35, 8724 байта. Lab050: 128×96 q25, 1740–1893 байта на искусственных сдвигах фотографии. | | Кодирование видео | `experiments/lab026_video_bitrate_benchmark.py` и `protocol/video_packet.py`: исследование сжатия и отдельный формат BASE/ROI | Это не подключённый к Lab045/Lab053 H.264 видеотракт. В VIDEO-001 добавлен автономный измеритель `tools/video_compare.py`, PyAV/libx264. | | Фрагменты объекта | `experiments/lab046_bpsk_object_transport.py`, `protocol/image_fragments.py` | 12 байт метаданных и 244 байта JPEG на пакет. Сборка требует все фрагменты; отдельного замера CPU только для фрагментации нет. | | Сигнал | `experiments/lab045_hackrf_bpsk_fec.py`, `experiments/lab049_bpsk_symbol_rate.py` | BPSK, свёрточный код 1/2, RRC; один пакет при 500 ксимв/с занимает 11,532 мс до паузы. Видео с H.264 в генератор не подаётся. | | Приём потока | `experiments/lab053_streaming_receiver.py`, `experiments/lab053_pipeline.py` | NumPy, SciPy, Numba. Lab053: программный источник 6,044416 с, 240/240 CRC-пакетов, 30/30 JPEG, 5 свежих изображений/с в стенде. Камеры и экрана там нет. | | Сборка и показ | `ImageSink` в `experiments/lab051_receiver_performance.py`; модель показа в `lab050_video_stream.py` | В Lab053 на 30 изображений сборка заняла 5,967 мс, JPEG decode 5,977 мс суммарно. Физический экран не реализован и не измерен. | **MEASURED:** Lab047 передала по эфиру один JPEG 8724 байта за 10,3788 с на 20 ксимв/с. Первоначальный независимый приём остановился по вычислительному пределу; повторный анализ той же RX-записи после сеанса восстановил 36/36 фрагментов и точный JPEG. Lab050–052 сначала не достигали реального времени: например, Lab050 обработала 0,323745 с IQ за 55,157553 с при 500 ксимв/с. Lab053 ускорила только программный конвейер: измеренные 5 кадров/с относятся к заданному файлу IQ, не к аппаратному видео. Ориентир 5 кадров/с для полной системы остаётся непроверенным. **MEASURED:** Lab066 выполнила один аппаратно валидный сеанс 500 ксимв/с с 16 пакетами по 256 байт и 5 мс между ними. Строгие legacy и T2 получили 10/16 точных пакетов, шесть остановились на PHY-заголовке. Lab067 связала эти отказы с локальным качеством принятого сигнала и не нашла основания для малой правки приёмника. 10/16 не считается постоянной вероятностью доставки. ## Радиобюджет **CALCULATED по генератору Lab045/Lab066:** 256 байт нагрузки содержат 12 байт заголовка фрагмента и 244 байта изображения. Пакет протокола имеет ещё 8 байт заголовка и 4 байта CRC, всего 268 байт. Код 1/2 с шестью хвостовыми битами даёт `(268×8+6)×2 = 4300` кодированных бит. Преамбула PRBS7 занимает 1280 символов, троекратный PHY-заголовок 144, вместе с кодированным телом это 5724 BPSK-символа. Две защитные области и хвост RRC добавляют 42 интервала: 5766 интервалов, 92 256 IQ-отсчётов и 11,532 мс на пакет при 500 ксимв/с. | Условие | Полезная скорость JPEG, бит/с | Смысл | |---|---:|---| | Без потерь и пауз | 169 268 | `244×8 / 0,011532`; верхняя граница формата. | | Без потерь, с паузой 5 мс после пакета | 118 074 | `244×8 / 0,016532`; около 60,49 пакета/с. | | Один сеанс Lab066, 10 принятых пакетов, с двумя 100-мс защитными интервалами | 42 480 | `10×244×8 / 0,459512`; видеоэквивалент, потому что Lab066 передавала не JPEG. Не измерение длительной видеодоставки. | При 5/10/15 кадрах/с без потерь и с паузой помещаются соответственно не более 12/6/4 целых пакетов за период кадра: 2928/1464/976 байт изображения. Это только длительность эфира; опорный H.264 кадр и потери могут заполнить очередь. Текущий формат и сборщик понимают JPEG, поэтому H.264 требует отдельного видеотранспорта. Его оценка в таблицах учитывает `ceil(размер/244)` пакетов на кадр, но не означает готовую передачу H.264. **MEASURED, сохранённый IQ Lab053:** 386 842 624 байта complex64 равны 6,044416 с при 8 Мвыб/с. Новый `tools/video_iq_replay.py` читает их блоками, вызывает штатный независимый PHY/FEC/CRC-приёмник и сборщик, без графиков, истории по блокам и сверки с TX во время замера. Первый проход: JIT-разогрев 0,496044 с, затем 4,099045 с обработки, или 1,475 с IQ/с обработки. Повторный проход: разогрев 0,000135 с, обработка 4,238388 с, или 1,426. Оба дали 240/240 пакетов и 30/30 точных JPEG. Первый и повторный проходы не образуют статистической гарантии для другого ноутбука, а профиль всё ещё содержит внутренние счётчики приёмника. ## Программное сравнение кодеков **MEASURED:** один исходный файл `data/raw/video001/udacity_project_video.mp4`, взятый из [открытого проекта Udacity по обнаружению автомобилей](https://github.com/udacity/CarND-Vehicle-Detection/blob/master/project_video.mp4). Размер 25 268 015 байт, SHA-256 `651949922042c223375d40bf8929def97dbb62c6ade651d1f5b08eea47127d5f`; 1280×720, 25 кадров/с, 50,4 с. Это реальная съёмка с движущегося автомобиля. В окне 7–13 с белая машина проходит справа, в окне 33–39 с появляются и меняют положение чёрная и белая машины. В обоих окнах исходные выбранные кадры различались. При изменении разрешения пропорции сохранены чёрными полями. Предыдущая проба на пустой дороге сохранена отдельно в `data/processed/video001/camera_only/` и не входит в таблицу ниже. JPEG повторяет профиль проекта: q35, 4:2:0, независимые кадры. H.264 использует PyAV 16.0.1 и доступный `libx264` из FFmpeg: `preset=veryfast`, `tune=zerolatency`, без B-кадров и lookahead, один поток кодировщика, закрытый GOP с опорным кадром раз в секунду, `crf=28`, VBV maxrate/buffer 160 или 320 кбит/с. Есть отдельные пробы с 40 кбит/с. Настройка maxrate не считается фактическим битрейтом: ниже приведены размеры полученных пакетов. Время кодирования и декодирования не включает чтение MP4. Отдельный `end_to_end_file_pipeline_latency_s` измерен прямым проходом: чтение очередного кадра MP4 с пропуском промежуточных, изменение размера, кодирование, декодирование и получение RGB. Открытие файла, эфир, очередь показа и экран в него не входят. Пик за 1 с рассчитан скользящим окном из `fps` кадров. В таблице для каждого режима взято большее из двух окон значение среднего и пикового потока, а также большее среднее время обработки кадра. Единицы: кбит/с и мс/кадр. `FITS` сопоставляет пакетную пиковую нагрузку с 21,76 принятого пакета/с в одном сеансе Lab066. Для всех строк это `НЕТ`; длительный рабочий предел радио остаётся **NOT_RUN**. По контрольным кадрам оценены различимость машин и полос, направление и потеря деталей. Мелких препятствий в этих двух участках нет; проверка с оператором ровера **NOT_RUN**. | Разрешение | FPS | Кодек | Средний поток | Пик 1 с | Кодирование | Декодирование | Качество для оператора | FITS CURRENT RADIO BUDGET | |---|---:|---|---:|---:|---:|---:|---|---| | 320×240 | 5 | JPEG q35 | 245 | 280 | 0,6 | 0,5 | Ближние машины и полоса видны; дальние предметы мелки | НЕТ | | 320×240 | 5 | H.264 160k | 117 | 172 | 1,2 | 0,3 | Ближние машины и направление видны; мелкие детали ограничены | НЕТ | | 320×240 | 5 | H.264 320k | 117 | 172 | 1,2 | 0,3 | Почти тот же вид, что при 160k | НЕТ | | 320×240 | 10 | JPEG q35 | 491 | 563 | 0,3 | 0,4 | Ближние машины и полоса видны; дальние предметы мелки | НЕТ | | 320×240 | 10 | H.264 160k | 140 | 213 | 1,0 | 0,2 | Ближние машины и направление видны; мелкие детали ограничены | НЕТ | | 320×240 | 10 | H.264 320k | 140 | 213 | 1,0 | 0,2 | Почти тот же вид, что при 160k | НЕТ | | 320×240 | 15 | JPEG q35 | 738 | 850 | 0,2 | 0,3 | Ближние машины и полоса видны; дальние предметы мелки | НЕТ | | 320×240 | 15 | H.264 160k | 151 | 238 | 0,9 | 0,2 | Ближние машины и направление видны; мелкие детали ограничены | НЕТ | | 320×240 | 15 | H.264 320k | 151 | 238 | 0,9 | 0,2 | Почти тот же вид, что при 160k | НЕТ | | 640×360 | 5 | JPEG q35 | 580 | 726 | 0,8 | 1,7 | Машины и разметка видны; крупный поток | НЕТ | | 640×360 | 5 | H.264 160k | 174 | 230 | 3,2 | 0,7 | Машины видны; текстура дороги размыта при движении | НЕТ | | 640×360 | 5 | H.264 320k | 342 | 437 | 3,8 | 1,0 | Машины, полоса и направление различимы | НЕТ | | 640×360 | 10 | JPEG q35 | 1165 | 1470 | 0,6 | 0,8 | Машины и разметка видны; крупный поток | НЕТ | | 640×360 | 10 | H.264 160k | 178 | 250 | 2,5 | 0,5 | Машины видны; текстура дороги размыта при движении | НЕТ | | 640×360 | 10 | H.264 320k | 354 | 376 | 3,0 | 0,7 | Машины, полоса и направление различимы | НЕТ | | 640×360 | 15 | JPEG q35 | 1752 | 2226 | 0,6 | 1,3 | Машины и разметка видны; крупный поток | НЕТ | | 640×360 | 15 | H.264 160k | 180 | 250 | 2,3 | 0,4 | Машины видны; текстура дороги размыта при движении | НЕТ | | 640×360 | 15 | H.264 320k | 355 | 375 | 2,6 | 0,5 | Машины, полоса и направление различимы | НЕТ | | 640×480 | 5 | JPEG q35 | 699 | 841 | 1,3 | 1,4 | Машины видны; чёрные поля 60 пикселей | НЕТ | | 640×480 | 5 | H.264 160k | 171 | 221 | 3,7 | 0,7 | Машины видны; поля и размытие деталей | НЕТ | | 640×480 | 5 | H.264 320k | 347 | 412 | 4,1 | 1,0 | Машины видны; полезная область как 640×360 | НЕТ | | 640×480 | 10 | JPEG q35 | 1402 | 1701 | 1,0 | 1,4 | Машины видны; чёрные поля 60 пикселей | НЕТ | | 640×480 | 10 | H.264 160k | 178 | 252 | 2,9 | 0,5 | Машины видны; поля и размытие деталей | НЕТ | | 640×480 | 10 | H.264 320k | 355 | 381 | 3,3 | 0,7 | Машины видны; полезная область как 640×360 | НЕТ | | 854×480 | 5 | JPEG q35 | 911 | 1142 | 1,3 | 2,1 | Машины и разметка чётче; крупный поток | НЕТ | | 854×480 | 5 | H.264 160k | 172 | 223 | 5,2 | 0,8 | Ближние машины видны; дальние детали размыты | НЕТ | | 854×480 | 5 | H.264 320k | 347 | 378 | 6,3 | 1,3 | Машины, полосы и направление хорошо различимы | НЕТ | | 854×480 | 10 | JPEG q35 | 1828 | 2318 | 1,4 | 2,2 | Машины и разметка чётче; крупный поток | НЕТ | | 854×480 | 10 | H.264 160k | 179 | 265 | 4,3 | 0,6 | Ближние машины видны; дальние детали размыты | НЕТ | | 854×480 | 10 | H.264 320k | 357 | 456 | 5,1 | 0,8 | Машины, полосы и направление хорошо различимы | НЕТ | | 1280×720 | 5 | JPEG q35 | 1745 | 2247 | 2,7 | 4,9 | Машины и разметка подробны; поток велик | НЕТ | | 1280×720 | 5 | H.264 160k | 173 | 217 | 9,8 | 1,2 | Машины видны; разрешение не даёт ожидаемой детализации | НЕТ | | 1280×720 | 5 | H.264 320k | 346 | 441 | 11,5 | 1,7 | Машины и разметка видны; дальние надписи не проверены | НЕТ | Полные размеры каждого кадра, включая опорные, фактическая скорость кодирования, оба замера задержки, RSS всего процесса, PSNR и число уникальных кадров сохранены в `data/processed/video001/comparison_traffic_160k.json` и `comparison_traffic_320k.json`. RSS в общем процессе достиг 240,9 МиБ в первом наборе и 241,7 МиБ во втором; это наблюдаемый пик при двух проходах на случай, не отдельная память кодека. В сценарии заранее загружены все выбранные кадры, поэтому RSS завышает память будущего поштучного видеотракта. У программных кандидатов максимальная задержка прямого файлового прохода составила 26,0 мс для HIGH QUALITY, 10,2 мс для NORMAL и 11,5 мс для ROBUST на этом ПК. Все 88 проходов этих двух наборов дали столько же уникальных декодированных кадров, сколько входных. Повторного кадра под новым номером не было в файловом декодировании; поведение экрана не проверено. Полученная частота кодирования выше заданной FPS на этом ПК, но это не частота доставки через радио. **MEASURED, проверка малого потока:** при настройке 40 кбит/с фактический H.264 поток на `320×240 / 5` достигал 43,0 кбит/с в среднем и 56,0 кбит/с в худшую секунду; опорный кадр до 2709 байт. Ближние автомобили узнаваемы, но их края и дорожная текстура сильно размываются. На `640×360 / 10` получено 44,8/67,6 кбит/с. Проверены все 11 сочетаний при 40 кбит/с, оба участка; во всех 44 проходах JPEG и H.264 число уникальных кадров равно входному. Даже наименьший пик среди всех этих проходов составил 29 пакетных мест за секунду, больше 21,76 принятого пакета/с в измеренном сеансе Lab066. Подробности: `comparison_traffic_40k.json`; пик RSS этого набора — 240,5 МиБ. **MEASURED, потеря данных в файле:** в каждом H.264 проходе удаляли первый опорный пакет и, отдельно, первый промежуточный пакет. Точное совпадение с неповреждённым декодированием возвращалось на следующем опорном кадре через 1 секунду исходного времени. Промежуточные изображения до него могут быть испорчены или отсутствовать. У независимого JPEG потеря одного изображения не мешает декодировать следующее. Это программная проба потери пакета кодека, а не проверка нашего радиопротокола или реального показа без зависаний. ## Выбор режимов и граница вывода Три **кандидата для следующей программной работы**, выбранные после замеров: | Назначение | Режим | Причина | Радио сейчас | |---|---|---|---| | HIGH QUALITY | 854×480, 10 кадров/с, H.264 320k | Машины и полосы различимы; 357 кбит/с средний, 456 кбит/с пик, кодирование 5,1 мс/кадр | НЕТ | | NORMAL | 640×360, 10 кадров/с, H.264 320k | Машины и направление различимы; 354/376 кбит/с, кодирование 3,0 мс/кадр | НЕТ | | ROBUST | 320×240, 5 кадров/с, H.264 160k | Ближние машины видны при меньшей нагрузке; 117/172 кбит/с, кодирование 1,2 мс/кадр | НЕТ | Названия описывают исследуемые программные профили, а не пригодность для управления ровером. Вариант 40 кбит/с не выбран даже как ROBUST: потеря мелких деталей и всплеск пакетов слишком велики. Для будущего видеотранспорта нужны номер изображения, номер фрагмента, время создания и срок актуальности; ожидающая очередь не больше одного нового изображения, сброс просроченного, сброс зависимого H.264 потока после потери опорных данных до следующего IDR. Имеющиеся PHY, FEC, CRC, заголовки и модуляция не менялись. Для `1280×720 / 5` H.264 320k потребовал 346 кбит/с в среднем, 441 кбит/с в худшую секунду и до 228 пакетных мест за секунду. Кодирование заняло в среднем до 11,5 мс/кадр, декодирование до 1,7 мс/кадр, прямой файловый путь до 32,0 мс для отдельного кадра; фактически кодировалось около 87 кадров/с. Текущие 5-мс паузы ограничивают эфир примерно 60,49 пакета/с без потерь. Крупнейший опорный кадр 12 593 байта требует 52 фрагмента и 0,860 с их сериализации; наибольший кадр вообще — 14 550 байт, 60 фрагментов и 0,992 с. Чтобы передать этот кадр в период 0,2 с, потребовалось бы не менее 300 пакетов/с без учёта управления, ошибок и защитного запаса. JPEG q35 при том же режиме дал 1745/2247 кбит/с. Для 720p нужны иной радиобюджет или существенно меньшие кадры, а также ограничение пиков, потерь и срока актуальности; одной скорости кодировщика недостаточно. ## Очереди и наблюдаемые ограничения В Lab053 очереди ограничены: 8 IQ-блоков, 4 строгих кандидата и 16 выходных пакетов. В программном стенде переполнений не было. У экспериментального `lab053_pipeline.py` растут списки истории блоков, пакетов и кадров: они нужны для отчёта, но не должны попадать в рабочий процесс ноутбука. Новый повтор IQ не собирает эту историю и не строит графики. Штатный приёмник всё же сохраняет внутренние счётчики и двойное IQ-кольцо; в Lab053 выделение кольца составило 6 797 824 байта. Это измеренная стоимость текущей реализации, а не основание менять PHY в VIDEO-001. `ImageSink` держит один собираемый JPEG. Недостающие фрагменты старого изображения задерживают его завершение до появления следующего ID; в текущем формате нет времени создания и срока годности. Отдельной H.264 очереди ещё нет. В автономном сравнении создан один экземпляр libx264 на весь участок, не новый процесс на каждый кадр. Основные измеренные ограничения для 10/15 кадров/с: пакетная и пиковая битовая нагрузка, потери Lab066, крупные опорные изображения и отсутствие транспорта с правилами свежести и восстановления. Одной достаточной скорости CPU-кодирования для решения этих вопросов мало. **NOT_RUN:** независимые генераторы, передача H.264 или непрерывного видео по эфиру, живой USB-приём, камера, экран, операторская проверка препятствий, ноутбук и длительное подтверждение полезной скорости радиоканала. Следующая практическая задача: сделать программный видеотранспорт с ограничением очереди, дедлайном изображения и восстановлением по IDR, затем проверить его на сохранённом IQ без доступа к SDR. **Проверки:** `video_validate_results.py` сверил 132 прохода в трёх наборах: матрицу режимов, SHA исходника, размеры кадров, поток, пакетные места, уникальность и восстановление. Целевые тесты VIDEO-001: 4 пройдены. Общие тесты: 1022 пройдены, один исторический тест исключён, поскольку в отдельном рабочем дереве нет исходного `data/raw/lab064/tx_metadata.json`. Полный `quick_gate.py` в этом дереве не завершён. На радио тесты не запускались. ## Воспроизведение Из ветки `video-development` после установки `requirements-video.txt`. Исходный ролик берётся по ссылке выше и сверяется с указанным SHA-256. Окна по умолчанию: 7–13 и 33–39 с; для другого ролика доступны повторяемые параметры `--window`. ```powershell New-Item -ItemType Directory -Force data\raw\video001 Invoke-WebRequest https://raw.githubusercontent.com/udacity/CarND-Vehicle-Detection/master/project_video.mp4 -OutFile data\raw\video001\udacity_project_video.mp4 (Get-FileHash -Algorithm SHA256 data\raw\video001\udacity_project_video.mp4).Hash python -B tools/video_compare.py --source data\raw\video001\udacity_project_video.mp4 --output data\processed\video001\comparison_traffic_160k.json --h264-maxrate-bps 160000 python -B tools/video_compare.py --source data\raw\video001\udacity_project_video.mp4 --output data\processed\video001\comparison_traffic_320k.json --h264-maxrate-bps 320000 python -B tools/video_compare.py --source data\raw\video001\udacity_project_video.mp4 --output data\processed\video001\comparison_traffic_40k.json --h264-maxrate-bps 40000 python -B tools/video_validate_results.py --source data\raw\video001\udacity_project_video.mp4 data\processed\video001\comparison_traffic_160k.json data\processed\video001\comparison_traffic_320k.json data\processed\video001\comparison_traffic_40k.json python -B tools/video_report_table.py --comparison-160k data\processed\video001\comparison_traffic_160k.json --comparison-320k data\processed\video001\comparison_traffic_320k.json --report docs\video\VIDEO_001.md python -B -m pytest tests\test_video_001_compare.py -q -p no:cacheprovider --basetemp data\processed\video001\pytest_temp_target ``` Повтор IQ описан в `SECOND_COMPUTER_SETUP.md`; он требует сохранённый файл и исходную ведомость SHA только для послерезультатной сверки.