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 дизайн-документа).
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/* cuframes-composer — высокоуровневый композитор N источников в grid.
|
||||
*
|
||||
* Управляет:
|
||||
* - N cfc_source (фоновые подписки на cuframes-publisher'ы)
|
||||
* - Layout (cell positions + size)
|
||||
* - Output NV12 buffer (cuMemAlloc, переиспользуется)
|
||||
* - Композиция на каждом тике: clear background + resize/blit для каждого ACTIVE,
|
||||
* fill чёрным для DEAD/STALE.
|
||||
*
|
||||
* Phase 2 архитектура:
|
||||
* Композитор работает синхронно: caller вызывает cfc_composer_compose() →
|
||||
* композитор для каждого источника берёт snapshot и пишет в output. После
|
||||
* вызова output NV12 buffer готов к encode.
|
||||
*
|
||||
* Каноническая интеграция:
|
||||
* for (;;) {
|
||||
* cfc_composer_compose(comp); // grid готов в output buffer
|
||||
* cfc_encoder_encode_frame(enc, ...); // → H.264
|
||||
* }
|
||||
*
|
||||
* Лицензия: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef CUFRAMES_COMPOSER_COMPOSER_H
|
||||
#define CUFRAMES_COMPOSER_COMPOSER_H
|
||||
|
||||
#include "source.h"
|
||||
|
||||
#include <cuda.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Описание одной ячейки grid'а — где на output буфере рисуется источник.
|
||||
* Все координаты в full-res пикселях, должны быть чётными. */
|
||||
typedef struct cfc_composer_cell {
|
||||
const char *source_key; /* cuframes key, например "cam-parking" */
|
||||
int x, y; /* top-left угол на output буфере */
|
||||
int w, h; /* размер ячейки */
|
||||
} cfc_composer_cell_t;
|
||||
|
||||
typedef struct cfc_composer_config {
|
||||
/* Output буфер (одно фиксированное разрешение для всего grid'а). */
|
||||
int width; /* output ширина (например 3840 для 2×2 1080p) */
|
||||
int height; /* output высота (например 2160 для 2×2 1080p) */
|
||||
|
||||
/* Cells конфигурация. Массив указателей на cells (для удобства user'а). */
|
||||
const cfc_composer_cell_t *cells; /* array, не копируется — caller держит */
|
||||
int num_cells;
|
||||
|
||||
/* CUDA устройство. */
|
||||
int cuda_device; /* индекс, обычно 0 */
|
||||
|
||||
/* Backgound цвет (BT.709 limited): Y=16/U=128/V=128 = чёрный. */
|
||||
int bg_y, bg_u, bg_v;
|
||||
|
||||
/* Параметры stale/dead для источников. */
|
||||
int reconnect_min_ms; /* default 1000 */
|
||||
int reconnect_max_ms; /* default 30000 */
|
||||
int stale_threshold_ms; /* default 500 */
|
||||
int dead_threshold_ms; /* default 5000 */
|
||||
} cfc_composer_config_t;
|
||||
|
||||
typedef struct cfc_composer cfc_composer_t;
|
||||
|
||||
/* Создать композитор. Выделяет output NV12 буфер, запускает N source thread'ов. */
|
||||
int cfc_composer_create(const cfc_composer_config_t *cfg, cfc_composer_t **out);
|
||||
|
||||
/* Скомпоновать один кадр. Вернёт указатели на output NV12 (Y + UV) и pitch.
|
||||
* Указатели действительны до следующего compose. */
|
||||
int cfc_composer_compose(
|
||||
cfc_composer_t *comp,
|
||||
CUdeviceptr *out_y_ptr,
|
||||
int *out_pitch_y,
|
||||
int *out_width,
|
||||
int *out_height
|
||||
);
|
||||
|
||||
/* Получить layout статистику по источникам — для debug / health-репортов. */
|
||||
typedef struct cfc_composer_health {
|
||||
int total; /* всего источников */
|
||||
int active; /* в состоянии ACTIVE */
|
||||
int stale; /* в STALE */
|
||||
int dead; /* DEAD/DISCONNECTED/CONNECTING */
|
||||
} cfc_composer_health_t;
|
||||
int cfc_composer_get_health(cfc_composer_t *comp, cfc_composer_health_t *out);
|
||||
|
||||
/* Уничтожить композитор. */
|
||||
int cfc_composer_destroy(cfc_composer_t *comp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CUFRAMES_COMPOSER_COMPOSER_H */
|
||||
@@ -0,0 +1,81 @@
|
||||
/* cuframes-composer — CUDA kernels для grid-композиции NV12 кадров.
|
||||
*
|
||||
* Извлечено из vf_cuda_grid (FFmpeg out-of-tree filter), под LGPL-2.1+.
|
||||
* Все операции работают на NV12-кадрах:
|
||||
* - Y plane: full resolution, 1 byte per pixel
|
||||
* - UV plane: half resolution, 2 bytes per pixel (interleaved U,V)
|
||||
*
|
||||
* Все операции:
|
||||
* - Принимают CUstream (NULL = default stream)
|
||||
* - Не аллоцируют память (caller выделяет dst буфер заранее)
|
||||
* - Idempotent для re-use (composer вызывает на каждом кадре)
|
||||
*
|
||||
* Lifecycle:
|
||||
* cfc_cugrid_init() один раз при старте композитора (no-op для CUDA, но
|
||||
* резервирован под cuModuleLoad если перейдём на PTX)
|
||||
*
|
||||
* Лицензия: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef CUFRAMES_COMPOSER_CUGRID_H
|
||||
#define CUFRAMES_COMPOSER_CUGRID_H
|
||||
|
||||
#include <cuda.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Lazy init (no-op в текущей реализации; зарезервировано под future PTX module). */
|
||||
int cfc_cugrid_init(void);
|
||||
|
||||
/* Заполнить прямоугольник на NV12 кадре solid color'ом с alpha-блендингом.
|
||||
*
|
||||
* dst_y, dst_uv — указатели на Y и UV plane соответственно.
|
||||
* pitch_y, pitch_uv — pitch в bytes (для NV12 обычно равны и кратны 256).
|
||||
* x, y, w, h — прямоугольник в full-res пикселях (chroma usually пишется
|
||||
* автоматически на половинном rastr'е).
|
||||
* w и h должны быть чётными (требование 4:2:0 subsampling'а).
|
||||
* color_y/u/v — компоненты цвета в BT.709 limited range (Y: 16-235, UV: 16-240).
|
||||
* Для чёрного: Y=16, U=128, V=128.
|
||||
* alpha — 0..255 (0 = transparent, 255 = opaque).
|
||||
*
|
||||
* Возвращает 0 при успехе.
|
||||
*/
|
||||
int cfc_cugrid_fill_nv12(
|
||||
CUstream stream,
|
||||
CUdeviceptr dst_y, int pitch_y,
|
||||
CUdeviceptr dst_uv, int pitch_uv,
|
||||
int x, int y, int w, int h,
|
||||
int color_y, int color_u, int color_v, int alpha
|
||||
);
|
||||
|
||||
/* Resize NV12 src → rect (dst_x, dst_y, dst_w, dst_h) на NV12 dst.
|
||||
*
|
||||
* Bilinear interpolation на Y и UV. Y и UV plane src'а должны быть одним
|
||||
* allocation'ом (NV12 layout) или хотя бы иметь корректные указатели каждый.
|
||||
*
|
||||
* src_y, src_uv — src указатели.
|
||||
* src_w, src_h — размер src в full-res пикселях.
|
||||
* src_pitch_y/uv — pitch'ы (для NV12 cuframes pitch_y == pitch_uv).
|
||||
* dst_y, dst_uv — dst указатели.
|
||||
* dst_pitch_y/uv — pitch'ы dst NV12 кадра.
|
||||
* dst_x, dst_y_off, — координата top-left прямоугольника на dst (full-res пиксели).
|
||||
* dst_w, dst_h dst_x и dst_y_off, dst_w, dst_h ДОЛЖНЫ быть чётными
|
||||
* (для UV/chroma subsampling'а).
|
||||
*/
|
||||
int cfc_cugrid_resize_nv12(
|
||||
CUstream stream,
|
||||
CUdeviceptr src_y, int src_w, int src_h, int src_pitch_y,
|
||||
CUdeviceptr src_uv, int src_pitch_uv,
|
||||
CUdeviceptr dst_y, int dst_pitch_y,
|
||||
CUdeviceptr dst_uv, int dst_pitch_uv,
|
||||
int dst_x, int dst_y_off, int dst_w, int dst_h
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CUFRAMES_COMPOSER_CUGRID_H */
|
||||
Reference in New Issue
Block a user