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'ы.
This commit is contained in:
2026-06-03 05:20:13 +01:00
parent 962bea11ca
commit 87daff313e
6 changed files with 285 additions and 1 deletions
+6
View File
@@ -25,6 +25,7 @@
#define CUFRAMES_COMPOSER_COMPOSER_H
#include "source.h"
#include "overlay.h"
#include <cuda.h>
#include <stdint.h>
@@ -78,6 +79,11 @@ int cfc_composer_compose(
int *out_height
);
/* Зарегистрировать overlay (border/png/text) для отрисовки поверх grid'а.
* composer takes ownership — на cfc_composer_destroy всё освобождается.
* Порядок добавления = z-order (последний рисуется поверх). Лимит — 64. */
int cfc_composer_add_overlay(cfc_composer_t *comp, cfc_overlay_t *ov);
/* Получить layout статистику по источникам — для debug / health-репортов. */
typedef struct cfc_composer_health {
int total; /* всего источников */
+85
View File
@@ -0,0 +1,85 @@
/* cuframes-composer — overlay'и (border, png-иконка, текст) поверх
* композиции.
*
* Архитектура:
* cfc_overlay_t — opaque объект одного overlay'я (border, png, text).
* composer ведёт список overlays + порядок (z-order); на каждом compose'е
* проходит по списку и рисует их поверх NV12 grid'а.
*
* Типы overlay'ев:
* BORDER — цветная рамка вокруг rect'а (Phase 3a). Реализован через 4
* fill_nv12 операции (top/bottom/left/right). Полезно для:
* - визуальной отбивки ячеек grid'а
* - подсветки активных/неактивных источников (красная при DEAD)
* PNG — RGBA-изображение (Phase 3b). Decode-раз через stb_image,
* upload в VRAM, на каждом кадре alpha-blit через
* cfc_kern_alpha_blit_rgba_*. Для статичных иконок (NO SIGNAL,
* offline, recording dot).
* TEXT — динамический рендер строки (Phase 3c). Требует FreeType +
* font atlas. Сделать позже когда FreeType добавлен как зависимость.
*
* Жизненный цикл:
* cfc_overlay_create_*() — выделяет ресурсы (для PNG/TEXT — VRAM-атлас).
* cfc_overlay_update_*() — обновляет параметры (положение, видимость, текст).
* cfc_overlay_draw() — вызывается composer'ом на каждом кадре.
* cfc_overlay_destroy() — освобождает VRAM.
*
* Phase 3a лимит: только BORDER через fill_nv12.
*
* Лицензия: LGPL-2.1+
*/
#ifndef CUFRAMES_COMPOSER_OVERLAY_H
#define CUFRAMES_COMPOSER_OVERLAY_H
#include <cuda.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum cfc_overlay_type {
CFC_OVERLAY_BORDER = 0,
CFC_OVERLAY_PNG = 1, /* Phase 3b */
CFC_OVERLAY_TEXT = 2, /* Phase 3c */
} cfc_overlay_type_t;
typedef struct cfc_overlay cfc_overlay_t;
/* Параметры BORDER overlay'я. */
typedef struct cfc_overlay_border_config {
int x, y, w, h; /* прямоугольник в full-res пикселях */
int thickness; /* толщина рамки в пикселях */
int color_y, color_u, color_v; /* цвет в BT.709 (Y:16-235, UV:16-240) */
int alpha; /* 0..255; 0 = invisible */
int visible; /* 0/1 — выводить ли вообще */
} cfc_overlay_border_config_t;
/* Создать BORDER overlay. */
int cfc_overlay_create_border(const cfc_overlay_border_config_t *cfg,
cfc_overlay_t **out);
/* Обновить параметры BORDER overlay'я (можно переключить visible,
* сменить цвет, изменить позицию). Thread-safe? Нет — caller должен сам
* заботиться о том, чтобы update не пересекался с draw. В рамках одного
* compose-thread'а это естественно. */
int cfc_overlay_update_border(cfc_overlay_t *ov,
const cfc_overlay_border_config_t *cfg);
/* Нарисовать overlay поверх NV12 кадра. Вызывается из cfc_composer_compose.
* Возвращает 0 при успехе. */
int cfc_overlay_draw(cfc_overlay_t *ov,
CUstream stream,
CUdeviceptr dst_y, int pitch_y,
CUdeviceptr dst_uv, int pitch_uv,
int frame_w, int frame_h);
/* Уничтожить overlay (освободить VRAM если был). */
int cfc_overlay_destroy(cfc_overlay_t *ov);
#ifdef __cplusplus
}
#endif
#endif /* CUFRAMES_COMPOSER_OVERLAY_H */