Объединённое состояние работ:
- Phase 10: source pool, motion-driven layout, Frigate motion_pulse,
zone-filter в pool, --source / --motion-mode CLI
- Phase 11 Steps 1-3c: 8×8 микро-сетка, JSON templates с asymmetric
layouts (tpl_1/3/4/5/6/7/8), reload через ZMQ, auto-labels per camera
В прод отдеплоено и откачено: используем gx/cuframes-composer:0.10 как
baseline. Phase 11 продолжится в branch phase11b-cpp как C++ refactor
с ООП-моделью Cell/Layout/Decoration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
10 predefined layouts (single, dual_horizontal, dual_vertical, quad,
main_plus_preview, six_grid, nine_grid, sixteen_grid, panoramic,
main_with_strip) — normalized [0..1] координаты, port из vf_cuda_grid.c
старого FFmpeg patch'а. Применяются к фактическому output разрешению
композитора через cfc_composer_set_layout(name).
Source pool НЕ пересоздаётся: sources привязаны к индексам cells, layout
меняет только геометрию (cell.x/y/w/h). Это даёт zero-disruption switch
без потери накопленного state и без re-subscribe к cuframes publishers.
ZMQ verbs: set_layout / list_layouts / get_layout. CLI: --layout=NAME
перетирает --cell координаты на старте.
Используется ONVIF wrapper'ом (gx/cctv-onvif:0.1) для PTZ presets:
GotoPreset(token) → ZMQ set_layout(token).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Несколько сессий попыток реализовать audio mixing в композитор'е.
Не достигнуто sub-секундной latency со стабильным video+audio.
Откатано на parallel mode (cfc-grid video-only, live от pipeline с audio).
Полный набор выводов и pitfall'ов — docs/LESSONS-audio-mixing-attempts.md.
Главные lesson'ы для будущей попытки:
- mpegts mux libavformat авто-инсёртит h264_mp4toannexb BSF которому
не нравится Annex-B + inline SPS/PPS — NVENC OUTPUT_SPSPPS per-frame ломает
- SPSC ring drop newest при full, не oldest (consumer's domain)
- av_new_packet (не av_malloc) для av_interleaved_write_frame ownership
- Monotonic PTS на counter (frame_idx, total_samples) — не wallclock
- mediamtx env-var path names не должны иметь '-' (parser limitation)
- Default mediamtx ReadTimeout=10s короткий для burst write'ов
Изменения в repo сохранены для будущей доработки:
- src/writer.c — mpegts backend с audio stream support
- src/audio.c — RTSP AAC consumer + lock-free SPSC ring
- include/cuframes_composer/{writer,audio}.h — public API
- examples/grid_record.c — --format=mpegts + --audio-source flags
- include/cuframes_composer/composer.h — consumer_prefix field
- docker/Dockerfile — libavformat-dev добавлен в builder/runtime
cfc-grid composer стабильно работает на видео (substantially лучше
монолитного pipeline'а с audio bag'ом). TV рекомендуется использовать
rtsp://...:554/cfc-grid + опционально rtsp://...:554/live-audio
parallel.
Phase 4a — control plane через ZMQ REP socket с JSON-командами.
Позволяет операторам менять text overlay'и runtime'ом без рестарта.
Live-validated: команды set_text label-parking → "⚠ ВНИМАНИЕ ⚠"
и set_text label-gate → "Машина у ворот" отрабатывают, текст
обновляется в потоке RTSP без перерывов.
Phase 4b — MQTT health publisher через libmosquitto. Каждые 10с в
composer/<instance>/health публикуется JSON {active,stale,dead,total,
uptime_s} с retain=true. Опционально публикуется HA MQTT discovery
config — четыре сенсора (active/stale/dead/total) появляются в HA
автоматически с expire_after=30s.
Содержимое:
- include/cuframes_composer/overlay.h — cfc_overlay_set_id/get_id/get_type
для lookup'а через control plane.
- include/cuframes_composer/composer.h — cfc_composer_find_overlay(id).
- include/cuframes_composer/control.h — cfc_control_config_t (endpoint +
composer + cuda_ctx для text rebuild в worker thread).
- src/control.c — ZMQ REP socket в фоновом потоке + zmq_poll с 200мс
timeout'ом для проверки stop_flag. JSON-диспатчер для команд ping /
health / set_text / set_visible / list_overlays. cuCtxSetCurrent
на старте worker'а — без этого update_text валится на cuMemAlloc.
- include/cuframes_composer/health.h — cfc_health_config_t (host/port/
user/pass + topic_prefix/instance + interval + publish_discovery).
- src/health.c — mosquitto_connect_async + loop_start + background
thread с publish health каждые N секунд + один разовый publish_discovery
для HA.
- examples/grid_record — флаги --control tcp://0.0.0.0:5599,
--mqtt host[:port], --mqtt-instance NAME, --mqtt-user/--mqtt-pass.
Для text overlay'ев — prefix "id=NAME:" в --text задаёт control-plane ID.
CMakeLists.txt — find_library(zmq), find_library(json-c),
find_library(mosquitto) + linkage всех трёх.
Production TODO: создать отдельного MQTT user'а для composer'а вместо
переиспользования frigate creds (используется только в smoke).
Live-validated на rtsp://192.168.88.23:554/cfc-grid: цветные рамки
вокруг каждой ячейки реализованы через 4 cfc_cugrid_fill_nv12
(top/bottom/left/right) — отдельного kernel'я не понадобилось,
переиспользуем existing fill_nv12 для region α-blend.
Содержимое:
- include/cuframes_composer/overlay.h — opaque cfc_overlay_t + типы
(BORDER реализован, PNG/TEXT skeleton'ы для Phase 3b/3c).
- src/overlay.c — реализация BORDER: clamp rect в границы кадра,
выравнивание координат на чётные (4:2:0 chroma требование),
thickness clamp если 2*thickness > w/h.
- composer.c — список overlays (max 64), z-order = порядок добавления,
draw поверх grid'а перед stream sync.
- examples/grid_record — флаг --border N (толщина пикселей) добавляет
серо-голубой border (Y=180,U=120,V=110 alpha=220) для каждой
ячейки автоматически.
Phase 3b (PNG icons через stb_image + cugrid alpha_blit_rgba) и Phase
3c (text через FreeType + font atlas) — отдельные commit'ы.
Multi-source композитор работает на 4K @ 25fps стабильно. Live-тест с
4 камерами (parking, back_yard, front_yard, gate_lpr): все 4 active,
350 кадров за 14с, 27.6 МБ H.264 файл, кадр декодируется ffmpeg'ом
с корректным 2x2 layout'ом.
Содержимое:
- include/cuframes_composer/cugrid.h — публичный API libcugrid:
cfc_cugrid_fill_nv12 (region fill с alpha blend),
cfc_cugrid_resize_nv12 (bilinear scale в rect).
- src/cugrid/cugrid.cu — извлечённые из vf_cuda_grid kernel'ы
(Y+UV fill + bilinear resize), объединены с C launcher'ом в одном
.cu файле, под LGPL-2.1+.
- include/cuframes_composer/composer.h — публичный API композитора:
cfc_composer_cell_t для layout, get_health для observability.
- src/composer.c — manager N cfc_source_t + единый NV12 output buffer
(cuMemAlloc, переиспользуется на каждом compose'е). compose_clear
fillит фон BT.709-чёрным, compose_cell делает resize ACTIVE
источника или оставляет blackout для DEAD/STALE/CONNECTING.
- examples/grid_record — Phase 2 smoke test: N --cell ключ,x,y,w,h
→ grid composer → NVENC → file.
Сборка: добавлен LANGUAGES CUDA и CMAKE_CUDA_ARCHITECTURES 89;120
(Ada + Blackwell). Compile options раздельные для C и CUDA
(-Wpedantic не подходит для .cu).
Phase 2 RTSP push отложен на отдельный commit — будет через pipe-out
к локальному ffmpeg'у, который публикует в mediamtx (вариант
утверждён в Q2 дизайн-документа).