Files
cuframes-composer/include/cuframes_composer/nvenc.h
T
gx ba68550f4c Phase 1: NVENC через dlopen + источник через cuframes_subscriber
Скелет проекта cuframes-composer (LGPL-2.1+) и MVP кодирования
одного источника в файл H.264.

Что включает Phase 1:

- LICENSE (LGPL-2.1+), README с поэтапным планом, корневой CMake
- Подмодули: cuframes v0.4 (pinned), nv-codec-headers (n12.2.72.0)
- include/cuframes_composer/source.h — публичный API источника
  с явной машиной состояний (DISCONNECTED → CONNECTING → ACTIVE →
  STALE → DEAD) и snapshot-паттерном для чтения без блокировки
- include/cuframes_composer/nvenc.h — публичный API кодировщика
  на CUdeviceptr-вход (zero-copy через VMM-mapped указатели)
- src/nvenc_loader.{h,c} — dlopen libnvidia-encode.so.1 и инициализация
  таблицы функций NVENC через NvEncodeAPICreateInstance. Идёт через
  pthread_once. Сделано отдельно чтобы держать LGPL-совместимость:
  проприетарный SDK не статически линкуется
- src/nvenc.c — обвязка над NVENC: open session, init encoder, кеш
  registered resources, encode/lock/unlock, flush с EOS, поддержка
  H.264 CBR low-latency, preset GUID p1/p4/p7
- src/source.c — обвязка над cuframes_subscriber c фоновым потоком,
  exponential backoff reconnect (1с → 30с), и переходами по таймаутам
  для stale/dead-детекта
- examples/simple_record — smoke-test программа: подписка на cuframes,
  кодирование, запись в .h264 файл, корректное завершение по SIGINT
2026-06-03 04:28:33 +01:00

108 lines
5.4 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 — обвязка вокруг NVIDIA NVENC API.
*
* Динамически грузит libnvidia-encode.so через dlopen, чтобы пакет
* cuframes-composer оставался под LGPL-2.1+ без статической линковки
* проприетарного SDK. См. дизайн-документ часть 1.6.
*
* Принимает на вход CUdeviceptr на NV12 frame (zero-copy через
* NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR + nvEncRegisterResource).
* Выдаёт сжатый H.264 bitstream через callback (caller записывает его
* в файл / RTP-пакетизирует / etc).
*
* Lifecycle:
* create(cfg) — open session, init encoder
* encode_frame(...) — на каждый входной кадр (один CUdeviceptr)
* flush(...) — в конце потока, чтобы вытащить остатки B-кадров
* destroy(...) — закрыть session, выгрузить SDK
*
* Поток должен быть single-threaded для одного encoder'а (NVENC API
* не реентрабельный для одной сессии).
*
* Лицензия: LGPL-2.1+
*/
#ifndef CUFRAMES_COMPOSER_NVENC_H
#define CUFRAMES_COMPOSER_NVENC_H
#include <cuda.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Параметры кодировщика. Для Phase 1 минимальный набор; в будущих фазах
* будут расширяться для RTSP (rate control, GOP, intra-refresh, и т.п.). */
typedef struct cfc_encoder_config {
CUcontext cuda_ctx; /* CUDA-контекст, в котором лежат входные VMM-буферы */
int32_t width; /* ширина кадра в пикселях */
int32_t height; /* высота кадра в пикселях */
int32_t fps_num; /* числитель частоты кадров (25) */
int32_t fps_den; /* знаменатель частоты кадров (1) */
int32_t bitrate_kbps; /* битрейт в килобитах в секунду (5000 = 5 Мбит/с) */
int32_t gop_size; /* интервал между keyframe'ами в кадрах (25 = 1 IDR в секунду) */
int32_t num_b_frames; /* B-кадры (0 для low-latency RTSP) */
/* Пресет — соответствует NV_ENC_TUNING_INFO + preset GUID.
* "ll" = low-latency, "p4" = preset P4 (баланс), "p7" = highest quality. */
const char *preset; /* "ll", "p4", "p7" — по умолчанию "ll" */
} cfc_encoder_config_t;
typedef struct cfc_encoder cfc_encoder_t;
/* Callback для записанного H.264 bitstream'а. Вызывается синхронно из
* cfc_encoder_encode_frame / cfc_encoder_flush. Указатель действителен только
* на время вызова (буфер NVENC будет разблокирован после возврата). */
typedef void (*cfc_encoder_output_cb)(
const uint8_t *bitstream, /* данные H.264 (Annex B byte stream) */
size_t size, /* размер в байтах */
int64_t pts_ns, /* presentation timestamp (передан в encode_frame) */
int is_idr, /* 1 если кадр IDR (keyframe) */
void *user /* user data, переданный в encode_frame */
);
/* Создать encoder. Возвращает 0 при успехе. */
int cfc_encoder_create(const cfc_encoder_config_t *cfg, cfc_encoder_t **out);
/* Закодировать один кадр. ptr — CUdeviceptr на начало NV12 frame в VRAM,
* pitch — ширина строки в байтах (для NV12 равна width).
*
* Callback может быть вызван 0 или 1 раз для одного encode_frame: NVENC
* может буферизовать кадры внутри (особенно при B-кадрах). Чтобы вытащить
* последние буферизованные — вызвать flush в конце потока. */
int cfc_encoder_encode_frame(
cfc_encoder_t *enc,
CUdeviceptr ptr,
int pitch,
int64_t pts_ns,
cfc_encoder_output_cb cb,
void *user
);
/* Завершить поток. Передаёт NVENC флаг end-of-stream, выдаёт оставшиеся
* закодированные кадры через callback. После flush encoder можно либо
* destroy, либо использовать снова с новым GOP'ом. */
int cfc_encoder_flush(
cfc_encoder_t *enc,
cfc_encoder_output_cb cb,
void *user
);
/* Выдать SPS/PPS — заголовки H.264 sequence/picture parameter sets.
* Нужны для записи в начало MP4-контейнера или для отправки в SDP при RTSP. */
int cfc_encoder_get_sequence_params(
cfc_encoder_t *enc,
uint8_t *out, /* буфер caller'а */
size_t *inout_size /* при вызове — размер буфера, при возврате — реальный размер */
);
/* Закрыть encoder, выгрузить SDK. */
int cfc_encoder_destroy(cfc_encoder_t *enc);
#ifdef __cplusplus
}
#endif
#endif /* CUFRAMES_COMPOSER_NVENC_H */