Lab031. Перемежение пакетов между FEC-блоками

Исходные данные и неизменные слои
- Видео: data\raw\lab026_rover_source.mp4
- 63 реальных синхронных пар BASE/ROI, 3 fps; длительность источника 20.766667 с.
- BASE 240x135 grayscale JPEG Q23; ROI 320x180 grayscale JPEG Q33.
- Внутренний транспорт Lab028: payload 512 байт, packet CRC32, object CRC32, атомарная публикация BASE+ROI.
- Внешний формат и GF(256) Lab030 используются без изменений; k=8, parity r=2 или r=4.

Точное правило перестановки
- Последовательные готовые FEC-блоки делятся на группы не более D блоков.
- Для symbol_index=0,1,2,... передаётся символ с этим индексом блока 0, затем блока 1, ... блока D-1.
- Если блок короче, отсутствующий symbol_index пропускается. Внутри блока сохраняется порядок systematic, затем parity.
- Перестановка не изменяет байты, block_id или symbol_index и не добавляет пакеты.

Формирование и буферизация групп
- Полная группа D>1 выпускается после готовности D-го последовательного блока; все её пакеты получают это время доступности перед FIFO-передатчиком.
- Неполная последняя группа выпускается в момент окончания видеопотока; синтетические блоки и символы не добавляются.
- D=1 сохраняет порядок и времена доступности Lab030 и имеет нулевую добавочную задержку ожидания группы.
- Размер группы формируется в порядке возрастания block_id; полные группы имеют D блоков, последняя — остаток.
- Средний буфер — среднее заполнение после каждого прихода готового блока (1..размер группы); максимум включает момент непосредственно перед выпуском группы.

Семь фиксированных режимов и статические метрики
mode | k+r | D | groups | final group | source/parity packets | outer kbit/s | overhead | wait mean/max s | buffer mean/max | queue mean/max | symbol gap/span ms
----:|----:|--:|-------:|------------:|----------------------:|-------------:|---------:|----------------:|----------------:|---------------:|-------------------:
Без FEC | none | 1 | 0 | 0 | 862/0 | 168.396 | 6.310% | 0.000000/0.000000 | 0.000/0 | 13.717/15 | 0.000/0.000
8+2, D=1 | 8+2 | 1 | 108 | 1 | 862/216 | 226.951 | 30.483% | 0.000000/0.000000 | 1.000/1 | 17.210/21 | 19.547/175.558
8+2, D=2 | 8+2 | 2 | 54 | 2 | 862/216 | 226.951 | 30.483% | 0.098765/0.333333 | 1.500/2 | 20.635/38 | 29.178/262.058
8+2, D=4 | 8+2 | 4 | 27 | 4 | 862/216 | 226.951 | 30.483% | 0.290123/0.666667 | 2.500/4 | 39.929/40 | 58.283/523.467
8+2, D=8 | 8+2 | 8 | 14 | 4 | 862/216 | 226.951 | 30.483% | 0.651852/1.666667 | 4.426/8 | 79.506/80 | 114.400/1027.482
8+4, D=1 | 8+4 | 1 | 108 | 1 | 862/431 | 274.659 | 42.558% | 0.000000/0.000000 | 1.000/1 | 20.859/26 | 16.379/179.710
8+4, D=4 | 8+4 | 4 | 27 | 4 | 862/431 | 274.659 | 42.558% | 0.290123/0.666667 | 2.500/4 | 51.026/57 | 58.817/645.351

Временная модель и статистика
- Непрерывные чередующиеся экспоненциальные Good/Bad интервалы Lab029B, средняя доля Bad около 2%.
- Средние Bad: 10, 50, 200, 1000 мс; 200 повторов на условие; seeds 310310...310313.
- Пакет теряется при любом пересечении интервала его передачи с Bad; скорость FIFO 300 кбит/с.
- Учитываются фактическая длина каждого внутреннего и внешнего пакета, ожидание группы и накопление очереди.
- Приёмник группирует внешние символы по block_id, декодирует после любых k принятых символов и передаёт восстановленные внутренние пакеты в CompositeReassembler.
- Соседние composite_frame_id не смешиваются; неполный BASE+ROI кадр не публикуется.

Результаты при средней Bad 200 мс
mode | composite | no-image mean/p95/max s | publication mean/p95/max s | affected blocks | all blocks | unrecoverable | delivered kbit/s | incomplete run mean/p95/max
----:|----------:|------------------------:|-------------------------:|----------------:|-----------:|--------------:|----------------:|------------------------:
Без FEC | 0.960079 | 0.780292/1.322480/2.001440 | 0.185041/0.203013/0.209680 | 0.000000 | 0.000000 | 0.000000 | 150.735 | 1.393/3.000/5
8+2, D=1 | 0.963095 | 0.827615/1.346867/2.032160 | 0.246248/0.275067/0.464720 | 0.152235 | 0.971898 | 0.028102 | 150.452 | 1.520/3.000/5
8+2, D=2 | 0.957143 | 1.026629/1.727381/2.670480 | 0.509783/0.670480/0.933093 | 0.225694 | 0.969028 | 0.030972 | 147.820 | 2.134/4.000/7
8+2, D=4 | 0.958333 | 1.387432/2.317012/3.306267 | 0.923445/1.134053/1.536720 | 0.408333 | 0.967130 | 0.032870 | 147.993 | 3.017/5.000/10
8+2, D=8 | 0.964921 | 2.088808/3.261775/4.919493 | 1.724311/2.252480/2.735360 | 0.644555 | 0.970231 | 0.029769 | 145.481 | 3.946/6.000/10
8+4, D=1 | 0.964048 | 0.875715/1.383067/2.062880 | 0.295702/0.336507/0.481920 | 0.247453 | 0.976065 | 0.023935 | 150.049 | 1.647/3.000/5
8+4, D=4 | 0.974841 | 1.338860/1.827840/2.774213 | 0.966677/1.152507/1.665707 | 0.669316 | 0.980741 | 0.019259 | 148.676 | 2.805/4.000/7

Когда 8+2 с перемежением превосходит 8+4 без него
- Критерий ниже: строго более высокая доля атомарно восстановленных составных кадров; задержки приведены рядом как цена перемежения.
- Bad 50 мс, 8+2, D=4: composite 0.972063 > 0.958175; P95 no-image 1.660629 с против 1.017307 с; P95 публикации 1.150264 с против 0.338693 с.
- Bad 50 мс, 8+2, D=8: composite 0.989603 > 0.958175; P95 no-image 2.456107 с против 1.017307 с; P95 публикации 2.271840 с против 0.338693 с.
- Bad 200 мс, 8+2, D=8: composite 0.964921 > 0.964048; P95 no-image 3.261775 с против 1.383067 с; P95 публикации 2.252480 с против 0.336507 с.

Функциональные проверки
- PASS d1_matches_lab030: D=1 wire order is byte-identical to Lab030
- PASS permutation_preserves_packets: all 1078 packets preserved
- PASS each_packet_once: every protected-mode packet appears exactly once
- PASS identifiers_preserved: block_id and symbol_index survived permutation
- PASS inverse_distribution: inverse grouping passed for D=[2, 4, 8]
- PASS decoded_inner_byte_exact: decoded inner packets are byte-exact
- PASS inner_outer_crc: outer and recovered Lab028 CRC32 checks passed
- PASS zero_bad_100_percent: all seven modes restored 100% of frames without Bad
- PASS fixed_seed_reproducibility: identical seed produced identical result fields
- PASS atomic_incomplete_composite: missing final ROI fragment prevented publication
- PASS depth_increases_symbol_distance: D=1/2/4/8 strictly increase intrablock symbol spacing
- PASS group_wait_in_publication_delay: D=4 group wait 0.290123 s is reflected in publication delay
- PASS final_partial_group: final 4-block group emitted 38 packets at end of stream

Допущения модели
- Видеопрофиль конечный и детерминированный; JPEG кодируются в памяти один раз перед Monte Carlo.
- Устройство знает конец потока и только тогда выпускает неполную последнюю группу D>1.
- Время готовности FEC-блока равно максимальному времени генерации его исходных пакетов; вычислительная задержка GF(256) считается нулевой.
- D=1 определён как точный режим Lab030; поэтому он не ждёт завершения блока перед отправкой уже готовых systematic symbols.
- Передатчик и канал общие FIFO; параллельные радиоканалы, ARQ, повторные передачи, команды, телеметрия, модуляция и реальный SDR не моделируются.
- Потеря является стиранием полного внешнего пакета; отдельные битовые ошибки не добавляются.
- Publication delay считается от frame_id/3 до конца пакета, завершившего атомарную сборку; no-image включает время до следующего опубликованного кадра или конца расписания.
- Intrablock symbol gap измеряется между временами конца последовательных symbol_index; span — от первого до последнего символа блока.

Артефакты
- CSV: data\processed\lab031\lab031_results.csv
- Отчёт: data\processed\lab031\lab031_report.txt
- Доля восстановленных кадров: data\processed\lab031\lab031_composite_success.png
- Отсутствие нового изображения: data\processed\lab031\lab031_no_image_duration.png
- Задержка публикации: data\processed\lab031\lab031_publication_delay.png
- Доля восстановленных блоков: data\processed\lab031\lab031_block_recovery.png
- Устойчивость/задержка от D: data\processed\lab031\lab031_depth_tradeoff.png
- Итоговое сравнение: data\processed\lab031\lab031_mode_comparison.png
- JPEG, внешние пакеты и бинарные дампы на диск не сохранялись.
