Lab036. Долговременная устойчивость видеопланировщика при изменении пропускной способности

1. Исходное состояние и конфигурация
- Commit Lab035: 22c2eeab8cc794e67378485f49c236a622f814a7.
- Рабочее дерево перед Lab036 было чистым; ветка main.
- Модель использует 600 с, 1800 кадров, повтор реальной последовательности размеров 63 кадров, BASE 240×135 Q23, ROI 320×180 Q33 и 3 составных кадра/с.
- Lab036 использует ровно 3 кадра/с в течение 600 с; короткий ролик Lab034 и предшествующих лабораторных давал немного отличающуюся фактическую частоту формирования кадров.
- Длинный опыт уменьшает влияние начального и конечного участков, поэтому значения общей предложенной нагрузки Lab034 и Lab036 не обязаны побайтно совпадать.
- Каждый повтор получает новые composite_frame_id, времена, заголовки и CRC; JPEG и пакеты на диск не записываются.
- Используются внутренний пакет Lab028 с payload 512 байт, FEC 12+3 с выравниванием по кадрам и общий пакет Lab033.
- Команды 20 Гц, телеметрия 10 Гц; аварийные команды создаются в 60, 180, 310 и 480 с.
- Ошибки радиоканала отсутствуют.
- Смена скорости не прерывает начатый пакет: новая скорость применяется только к следующему пакету после завершения текущего.

2. Пятнадцать сочетаний
scenario | policy | published/drop | fps | age P95 ms | queue max packets | queue at 600 packets | drain s | control P95 ms | emergency max ms
constant_300 | no_drop | 1800/0 | 3.000 | 600.000 | 22 | 0 | 0.000 | 17.466 | 1.707
constant_300 | latest_only | 1800/0 | 3.000 | 600.000 | 22 | 0 | 0.000 | 17.466 | 1.707
constant_300 | two_waiting | 1800/0 | 3.000 | 600.000 | 22 | 0 | 0.000 | 17.466 | 1.707
constant_260 | no_drop | 1800/0 | 2.977 | 4866.667 | 268 | 238 | 4.146 | 19.652 | 18.421
constant_260 | latest_only | 1772/28 | 2.953 | 833.333 | 40 | 0 | 0.000 | 19.046 | 10.513
constant_260 | two_waiting | 1787/13 | 2.977 | 1166.667 | 58 | 6 | 0.084 | 19.652 | 18.421
constant_230 | no_drop | 1800/0 | 2.608 | 74633.333 | 4155 | 4139 | 82.753 | 22.157 | 15.896
constant_230 | latest_only | 1570/230 | 2.615 | 1000.000 | 40 | 17 | 0.317 | 22.157 | 10.817
constant_230 | two_waiting | 1571/229 | 2.615 | 1333.333 | 57 | 26 | 0.486 | 22.191 | 12.765
step_300_230_300 | no_drop | 1800/0 | 3.000 | 21966.667 | 1279 | 0 | 0.000 | 19.409 | 21.461
step_300_230_300 | latest_only | 1730/70 | 2.883 | 900.000 | 40 | 0 | 0.000 | 19.444 | 3.791
step_300_230_300 | two_waiting | 1731/69 | 2.885 | 1233.333 | 58 | 0 | 0.000 | 19.339 | 3.826
variable_300_260_230 | no_drop | 1800/0 | 2.970 | 5666.667 | 326 | 295 | 5.804 | 20.403 | 19.077
variable_300_260_230 | latest_only | 1716/84 | 2.858 | 900.000 | 40 | 14 | 0.261 | 20.194 | 14.593
variable_300_260_230 | two_waiting | 1725/75 | 2.872 | 1233.333 | 56 | 29 | 0.562 | 20.309 | 19.077

3. Постоянные скорости: теория и модель
rate | policy | reserve kbps | theory growth B/s | model growth B/s | minimum skip | stable fps | minute queue packets
300 | no_drop | 38.278 | 0.000 | -11.601 | 0.000000 | 3.000 | 21;21;21;20;19;21;21;21;21;0
300 | latest_only | 38.278 | 0.000 | -11.601 | 0.000000 | 3.000 | 21;21;21;20;19;21;21;21;21;0
300 | two_waiting | 38.278 | 0.000 | -11.601 | 0.000000 | 3.000 | 21;21;21;20;19;21;21;21;21;0
260 | no_drop | -1.722 | 215.258 | 218.649 | 0.007063 | 2.979 | 48;65;90;117;149;176;197;214;233;238
260 | latest_only | -1.722 | 215.258 | -5.668 | 0.007063 | 2.979 | 32;24;21;20;21;24;39;32;24;0
260 | two_waiting | -1.722 | 215.258 | -12.199 | 0.007063 | 2.979 | 48;29;35;43;39;49;52;37;37;6
230 | no_drop | -31.722 | 3965.258 | 3967.819 | 0.130116 | 2.610 | 429;841;1255;1672;2093;2511;2924;3335;3745;4139
230 | latest_only | -31.722 | 3965.258 | -6.550 | 0.130116 | 2.610 | 37;33;38;26;34;26;28;37;38;17
230 | two_waiting | -31.722 | 3965.258 | -22.350 | 0.130116 | 2.610 | 42;56;52;53;44;55;55;47;43;26

4. Восстановление после ухудшения
policy | age at 300 ms | below 1000 s | below 500 s | excess queue clear s | dropped old | published old
no_drop | 24333.333 | 147.641 | 149.802 | 150.023 | 0 | 72
latest_only | 666.667 | 0.000 | 0.077 | 0.008 | 0 | 1
two_waiting | 1000.000 | 0.059 | 1.135 | 1.355 | 0 | 2

5. Видео, очередь, команды и телеметрия
- constant_300: fps=3.000, age P95=600.000 мс, queue max=22, waiting max=1, control P95/max=17.466/17.787 мс, emergency=1.706667;1.706667;1.706667;1.706667 мс, telemetry P95=19.574 мс.
- constant_260: fps=2.953, age P95=833.333 мс, queue max=40, waiting max=1, control P95/max=19.046/20.667 мс, emergency=7.528538;1.969231;10.513154;7.528538 мс, telemetry P95=22.144 мс.
- constant_230: fps=2.615, age P95=1000.000 мс, queue max=40, waiting max=1, control P95/max=22.157/23.357 мс, emergency=6.852174;4.660870;9.808696;10.817391 мс, telemetry P95=25.426 мс.
- step_300_230_300: fps=2.883, age P95=900.000 мс, queue max=40, waiting max=1, control P95/max=19.444/23.357 мс, emergency=1.706667;3.791304;1.706667;1.706667 мс, telemetry P95=22.541 мс.
- variable_300_260_230: fps=2.858, age P95=900.000 мс, queue max=40, waiting max=1, control P95/max=20.194/23.373 мс, emergency=7.528538;1.969231;10.513154;14.593065 мс, telemetry P95=23.376 мс.
- Политика самого свежего кадра ограничивает ожидающую видеоочередь одним кадром и не передаёт накопленную историю после восстановления.
- Политика двух ожидающих кадров ограничивает очередь двумя кадрами, но увеличивает возраст изображения относительно основной политики.
- Без удаления при дефиците скорости очередь растёт; при 300 кбит/с запас достаточен.
- У упреждающих политик нет бесполезно переданных видеобайтов: начатый кадр всегда завершается.

6. Функциональные проверки
- PASS 01_unique_repeated_frames_and_crc: PASS
- PASS 02_300kbps_latest_has_no_unnecessary_drop: PASS
- PASS 03_260kbps_no_drop_matches_small_deficit: PASS
- PASS 04_230kbps_no_drop_grows_faster: PASS
- PASS 05_latest_waiting_limit: PASS
- PASS 06_two_waiting_limit: PASS
- PASS 07_started_frame_never_dropped: PASS
- PASS 08_active_video_frames_do_not_interleave: PASS
- PASS 09_priority_between_video_packets: PASS
- PASS 10_emergency_never_deleted: PASS
- PASS 11_speed_change_bit_accounting: PASS
- PASS 12_latest_does_not_replay_full_history: PASS
- PASS 13_proactive_policies_have_no_waste: PASS
- PASS 14_incomplete_frame_not_published: PASS
- PASS 15_all_three_crc_layers_pass: PASS
- PASS 16_frame_accounting: PASS
- PASS 17_packet_and_byte_accounting: PASS
- PASS 18_reproducible: PASS
- CRC-проверено общих пакетов: 49794; FEC-блоков: 3571.

7. Созданные файлы
- tests/lab036_long_duration_scheduler.py
- data/processed/lab036/lab036_summary.csv
- data/processed/lab036/lab036_video_metrics.csv
- data/processed/lab036/lab036_control_metrics.csv
- data/processed/lab036/lab036_recovery_metrics.csv
- data/processed/lab036/lab036_report.txt
- data/processed/lab036/lab036_image_age_timeline.png
- data/processed/lab036/lab036_queue_timeline.png
- data/processed/lab036/lab036_minute_update_rate.png
- data/processed/lab036/lab036_recovery.png
- data/processed/lab036/lab036_control_delay.png
- data/processed/lab036/lab036_frame_outcomes.png
- data/processed/lab036/lab036_queue_growth_theory.png
- data/processed/lab036/lab036_policy_comparison.png

8. Итоговый Git status
- Lab036 не добавлена в индекс и не закоммичена.

## main...origin/main
?? data/processed/lab036/
?? tests/lab036_long_duration_scheduler.py
