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

28 KiB
Raw Blame History

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 по обнаружению автомобилей. Размер 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.

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 только для послерезультатной сверки.