Lab028. Пакетирование синхронного BASE + ROI

Профиль и исходные данные
- Видео: data\raw\lab026_rover_source.mp4
- Источник: 1280x720, 30.000000 fps, 623 кадров, 20.766667 с.
- ROI: x=0.20...0.80, y=0.42...1.00; пиксели x=256...1024, y=302...720.
- Синхронные составные кадры: 63 при 3.000 fps.
- BASE: 240x135, grayscale JPEG Q23; средний размер 2296.016 B, min/max 2122/2476 B.
- ROI: 320x180, grayscale JPEG Q33; средний размер 4204.683 B, min/max 3457/4938 B.
- BASE и ROI формируются из одного source frame и имеют общий composite_frame_id.

Бинарный заголовок
- struct format: !4sBBHIHHHHIII
- Размер: 32 байта; network byte order; padding нет.
- Layout: magic[4] @0, version:u8 @4, object_type:u8 @5, header_size:u16 @6, composite_frame_id:u32 @8, fragment_index:u16 @12, fragment_count:u16 @14, payload_length:u16 @16, flags:u16 @18, jpeg_size:u32 @20, object_crc32:u32 @24, packet_crc32:u32 @28.
- object_type: 1=BASE, 2=ROI; flags зарезервирован и равен 0.

CRC32
- object_crc32 = zlib.crc32(полный JPEG) & 0xFFFFFFFF; значение помещается во все фрагменты объекта и проверяется после полной сборки.
- packet_crc32: сначала поле packet_crc32 заголовка обнуляется, затем CRC считается как zlib.crc32(header_with_zero_crc + payload) & 0xFFFFFFFF.
- Таким образом packet CRC защищает все поля заголовка и payload.

Функциональные проверки
- PASS header_serialization_round_trip: fixed 32-byte header round trip is exact
- PASS ordered_lossless_transfer: BASE and ROI match original JPEG bytes
- PASS random_packet_order: arbitrary packet order reconstructed correctly
- PASS exact_duplicate_packets: 2 exact duplicates ignored
- PASS packet_crc_corruption: payload bit flip rejected; composite not emitted
- PASS missing_fragment: ROI fragment 10 reported missing
- PASS object_crc_corruption: valid packet CRCs still failed full-object CRC
- PASS adjacent_frame_isolation: two interleaved frame IDs remained independent
- PASS base_without_roi_atomicity: complete BASE retained while composite stayed unpublished

Результаты размеров packet payload
payload | BASE pkt/frame | ROI pkt/frame | all pkt/frame | max pkt/frame | pkt/s | JPEG kbit/s | headers B/s | wire kbit/s | service % | efficiency % | packet mean/p95/max
-------:|---------------:|--------------:|--------------:|--------------:|------:|------------:|------------:|------------:|----------:|-------------:|--------------------:
64 | 36.429 | 66.175 | 102.603 | 117 | 311.268 | 157.770 | 9960.578 | 237.454 | 33.558 | 66.442 | 95.4/96.0/96
128 | 18.429 | 33.270 | 51.698 | 59 | 156.838 | 157.770 | 5018.812 | 197.920 | 20.286 | 79.714 | 157.7/160.0/160
256 | 9.429 | 16.921 | 26.349 | 30 | 79.936 | 157.770 | 2557.945 | 178.233 | 11.481 | 88.519 | 278.7/288.0/288
512 | 5.000 | 8.683 | 13.683 | 15 | 41.509 | 157.770 | 1328.283 | 168.396 | 6.310 | 93.690 | 507.1/544.0/544
1024 | 3.000 | 4.587 | 7.587 | 8 | 23.018 | 157.770 | 736.565 | 163.662 | 3.600 | 96.400 | 888.8/1056.0/1056

JPEG payload bitrate одинаков для всех строк, потому что исходные JPEG не меняются при выборе размера фрагмента.
Wire bitrate включает только JPEG payload и 32-байтные заголовки каждого пакета.
Wire bitrate пока НЕ включает FEC, преамбулу, синхронизацию, модуляцию, интервалы, повторные передачи, команды управления и телеметрию.
Лучший размер packet payload автоматически не выбирается: таблица показывает только транспортный компромисс.

Артефакты
- CSV: data\processed\lab028\lab028_packet_payload_results.csv
- Overhead/efficiency: data\processed\lab028\lab028_overhead_efficiency.png
- Packet count/wire bitrate: data\processed\lab028\lab028_packets_wire_bitrate.png
- Промежуточные JPEG и пакеты сохранялись только в памяти; бинарные дампы не создавались.
