Files
cuframes-composer/include/cuframes_composer/overlay.h
T
gx e02998cea7 Phase 3c: TEXT overlays через FreeType + GTX 1050 (Pascal) compat
Phase 3c — динамический текст через libfreetype6: открывается font
(.ttf/.otf), измеряется bounding box строки, рендерится в RGBA-атлас
с anti-aliased alpha из FT bitmap, заливается в VRAM. На каждом
кадре блитится через cfc_cugrid_blit_rgba_nv12 (kernels уже есть).
Поддержка UTF-8 через простой inline-decoder (1/2/3/4-byte).

cfc_overlay_update_text() переподдерживает re-render atlas (text /
color change) — для Phase 4 ZMQ control plane (динамическое изменение
NO SIGNAL / RECORDING / timestamp'ов).

Адаптация под GTX 1050 (Pascal) в проде:
- CMAKE_CUDA_ARCHITECTURES = 61;75;86;89;120 (Pascal + Turing +
  Ampere + Ada + Blackwell, покрывает все production-кейсы)
- grid_record default снижен с 4K@10Mbps на 1080p@4Mbps. 4K требует
  явных --width 3840 --height 2160 (Pascal NVENC 4K H.264 на грани).
- Ссылка на research-документ + NVENC §Input Buffers рядом со staging
  buffer'ом в nvenc.c с цитатой "the client is required to use buffers
  allocated using the cuMemAlloc family of APIs".

Содержимое Phase 3c:
- overlay.h — cfc_overlay_create_text + update_text + text_size.
- overlay.c — utf8_next decoder, text_measure (ascender/descender),
  text_render (alpha-over blend в RGBA), text_rebuild_atlas (VRAM
  cycle), full FreeType lifecycle.
- CMakeLists.txt — find_package(Freetype REQUIRED) + link
  Freetype::Freetype.
- examples/grid_record — флаг --text font,size,r,g,b,x,y,text.
2026-06-03 05:44:57 +01:00

136 lines
7.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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);
/* Параметры PNG overlay'я. */
typedef struct cfc_overlay_png_config {
const char *path; /* путь к PNG-файлу (декод один раз) */
int x, y; /* позиция top-left на output буфере (чётные) */
int extra_alpha; /* 0..255 общий множитель прозрачности */
int visible; /* 0/1 — выводить ли */
} cfc_overlay_png_config_t;
/* Создать PNG overlay. Декодирует файл через libpng, аллоцирует RGBA-атлас
* в VRAM (cuMemAlloc), копирует туда декодированные пиксели один раз.
*
* Размер изображения берётся из PNG header'а — caller узнаёт width/height
* через cfc_overlay_png_size после create. */
int cfc_overlay_create_png(const cfc_overlay_png_config_t *cfg,
cfc_overlay_t **out);
/* Получить реальный размер декодированного PNG. После create — стабильны
* до destroy. */
int cfc_overlay_png_size(cfc_overlay_t *ov, int *width, int *height);
/* Обновить параметры PNG overlay'я (без re-decode). */
int cfc_overlay_update_png(cfc_overlay_t *ov,
const cfc_overlay_png_config_t *cfg);
/* Параметры TEXT overlay'я (Phase 3c). */
typedef struct cfc_overlay_text_config {
const char *font_path; /* путь к .ttf / .otf */
const char *text; /* UTF-8 строка для рендера */
int pixel_size; /* высота glyph'а в пикселях (10..200) */
int x, y; /* top-left на output буфере (чётные) */
int r, g, b; /* sRGB цвет 0..255 */
int extra_alpha; /* 0..255 общий множитель прозрачности */
int visible; /* 0/1 — выводить ли */
} cfc_overlay_text_config_t;
/* Создать TEXT overlay. Открывает font через FreeType, рендерит строку
* в RGBA-атлас на CPU (alpha-channel из glyph bitmap'ов anti-aliased),
* заливает в VRAM. */
int cfc_overlay_create_text(const cfc_overlay_text_config_t *cfg,
cfc_overlay_t **out);
/* Обновить TEXT overlay. Если text изменился — re-render atlas (VRAM
* перевыделяется). font_path и pixel_size менять нельзя — заведите новый
* overlay (face и связанные ресурсы пере-init'ить дорого). */
int cfc_overlay_update_text(cfc_overlay_t *ov,
const cfc_overlay_text_config_t *cfg);
/* Получить ширину/высоту текущего рендеренного текста (в пикселях). */
int cfc_overlay_text_size(cfc_overlay_t *ov, int *width, int *height);
/* Обновить параметры 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 */