6 Commits

Author SHA1 Message Date
gx f8e27b9e85 Phase 10/11 WIP — pool + motion-mode + 8×8 templates (rolled back)
Объединённое состояние работ:
  - 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>
2026-06-03 21:24:23 +01:00
gx 2d7fc1e640 Phase 9 #193: runtime layout switching через ZMQ set_layout
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>
2026-06-03 18:14:58 +01:00
gx fa6ab3069a Phase 7 audio mixing — attempt + rollback + lessons
Несколько сессий попыток реализовать 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.
2026-06-03 14:29:56 +01:00
gx 636b70b64c Phase 4: ZMQ control plane + MQTT health publisher
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).
2026-06-03 06:20:38 +01:00
gx 87daff313e Phase 3a: BORDER overlays через 4 fill_nv12 операции
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'ы.
2026-06-03 05:20:13 +01:00
gx 1e2b5d4e16 Phase 2: composer + libcugrid (N источников → 2x2 grid в NV12 буфер)
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 дизайн-документа).
2026-06-03 05:01:49 +01:00