Files
cuframes-docs/site/i18n/ru/docusaurus-plugin-content-docs/current/reference/api-c.md
T
Claude Opus 8c3c43709d docs: full content + landing + RU translations
Initial documentation site for cuframes:

- Landing page (src/pages/index.mdx) — hero, quick example (publisher +
  subscriber), comparison table vs naive/DeepStream, honest "early but
  production-tested" status
- /docs/intro — full overview
- /docs/getting-started/{install,first-publisher,first-subscriber}
- /docs/concepts/{frame-vs-packet-ring,ownership-modes,sync-vmm-stream}
  with mermaid diagrams
- /docs/integration/{ffmpeg-demuxer,ffmpeg-filter,python}
- /docs/reference/{api-c,api-cpp,protocol} — full v4 wire protocol spec
  incl. VMM_FDS message, magic 0xCC7C1DCE bump diff
- /docs/faq — comparison vs DeepStream/GStreamer, license, multi-host
  limitations
- i18n/ru/ — parallel RU translation (tech terms latin, склонение апостроф)

Build:
- Docusaurus 3.10.1 + theme-mermaid + search-local
- Follows dagstack-* docs convention (canonical: dagstack-plugin-system-docs)
- Apache-2.0 license; cuframes lib itself remains LGPL-2.1+

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 23:31:03 +01:00

532 lines
25 KiB
Markdown
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.
---
sidebar_position: 1
title: C API
---
# C API reference
Полный листинг public C API из `<cuframes/cuframes.h>` (libcuframes 0.4.0). Source of truth — header в repo, эта страница его дублирует в Docusaurus-формате с cross-links на концептуальные разделы.
## Headers & linkage
```c
#include <cuframes/cuframes.h>
```
```bash
# pkg-config (если установлено через .deb)
cc app.c $(pkg-config --cflags --libs cuframes)
# вручную
cc app.c -lcuframes
```
`libcuframes.so.0` динамически линкуется к `libcuda.so.1` (CUDA driver API, не runtime). Для большинства user-кода также нужен `-lcudart`, чтобы манипулировать своими CUDA streams.
## Соглашения
- Все функции возвращают `int``0` (CUFRAMES_OK) при успехе, отрицательный код из [`cuframes_error_t`](#error-codes) при ошибке. Расшифровка кода — [`cuframes_strerror`](#error-decoding).
- Все handle types (`cuframes_publisher_t`, `cuframes_subscriber_t`, `cuframes_frame_t`, `cuframes_packet_t`) — **opaque**. Поля недоступны напрямую, только через accessor-функции. Это даёт ABI-stability в minor-релизах.
- Каждый handle принадлежит **одному потоку**. Cross-thread access — undefined behavior. Несколько handle'ов в разных потоках — OK.
- Endianness — little-endian (это и так фиксируется CUDA-платформами).
## Версии и error codes
### Версия библиотеки
```c
const char *cuframes_version_string(void);
uint32_t cuframes_protocol_version(void);
```
`cuframes_version_string` возвращает runtime-версию libcuframes в формате `"MAJOR.MINOR.PATCH"` (например `"0.4.0"`). Compile-time константы:
```c
#define CUFRAMES_VERSION_MAJOR 0
#define CUFRAMES_VERSION_MINOR 4
#define CUFRAMES_VERSION_PATCH 0
```
`cuframes_protocol_version` возвращает версию wire-protocol (для v0.4 — `4`). Subscribers с другой protocol-версией не подключатся — publisher вернёт `HELLO_RESP(result=CUFRAMES_ERR_PROTOCOL)`. См. [Protocol reference](/docs/reference/protocol).
### Error codes
```c
typedef enum cuframes_error {
CUFRAMES_OK = 0,
CUFRAMES_ERR_INVALID_ARG = -1,
CUFRAMES_ERR_OUT_OF_MEMORY = -2,
CUFRAMES_ERR_CUDA = -3,
CUFRAMES_ERR_IO = -4,
CUFRAMES_ERR_NOT_FOUND = -5,
CUFRAMES_ERR_ALREADY_EXISTS = -6,
CUFRAMES_ERR_TIMEOUT = -7,
CUFRAMES_ERR_PROTOCOL = -8,
CUFRAMES_ERR_DISCONNECTED = -9,
CUFRAMES_ERR_FORMAT = -10,
CUFRAMES_ERR_WOULD_BLOCK = -11,
CUFRAMES_ERR_TOO_MANY = -12,
CUFRAMES_ERR_PACKET_OVERSIZED = -20,
CUFRAMES_ERR_NO_PACKET_RING = -21,
CUFRAMES_ERR_NO_CODEC_PARAMS = -22,
CUFRAMES_ERR_PACKET_OVERRUN = -23,
CUFRAMES_ERR_INTERNAL = -100,
} cuframes_error_t;
```
| Код | Имя | Значение |
|---|---|---|
| `0` | `CUFRAMES_OK` | Success |
| `-1` | `CUFRAMES_ERR_INVALID_ARG` | NULL pointer или невалидное значение в config |
| `-2` | `CUFRAMES_ERR_OUT_OF_MEMORY` | malloc / cudaMalloc fail |
| `-3` | `CUFRAMES_ERR_CUDA` | Ошибка CUDA runtime / driver |
| `-4` | `CUFRAMES_ERR_IO` | socket / mmap / eventfd |
| `-5` | `CUFRAMES_ERR_NOT_FOUND` | Publisher с таким key не найден |
| `-6` | `CUFRAMES_ERR_ALREADY_EXISTS` | Publisher с этим key уже есть, либо `consumer_name` занят |
| `-7` | `CUFRAMES_ERR_TIMEOUT` | Операция не завершилась за timeout |
| `-8` | `CUFRAMES_ERR_PROTOCOL` | Несовместимая версия wire protocol |
| `-9` | `CUFRAMES_ERR_DISCONNECTED` | Publisher умер или сеть оборвалась |
| `-10` | `CUFRAMES_ERR_FORMAT` | Неподдерживаемый pixel format или несовпадение размеров |
| `-11` | `CUFRAMES_ERR_WOULD_BLOCK` | Non-blocking call — данных пока нет |
| `-12` | `CUFRAMES_ERR_TOO_MANY` | Превышен `MAX_SUBSCRIBERS` (32) |
| `-20` | `CUFRAMES_ERR_PACKET_OVERSIZED` | `publish_packet` size > `max_packet_size` |
| `-21` | `CUFRAMES_ERR_NO_PACKET_RING` | Subscriber запросил packets, у publisher'а нет ring'а |
| `-22` | `CUFRAMES_ERR_NO_CODEC_PARAMS` | Extradata ещё не set publisher'ом |
| `-23` | `CUFRAMES_ERR_PACKET_OVERRUN` | Slow subscriber, packet seq уехал — resync на keyframe |
| `-100` | `CUFRAMES_ERR_INTERNAL` | Bug в библиотеке — воспроизводи и репорти |
### Расшифровка ошибок
```c
const char *cuframes_strerror(int err);
```
Возвращает human-readable строку для error code. Pointer указывает на static storage, владеть им дальше не надо. Никогда не возвращает NULL — для unknown code вернёт `"unknown error"`.
## Pixel formats
```c
typedef enum cuframes_format {
CUFRAMES_FORMAT_NV12 = 0,
CUFRAMES_FORMAT_YUV420P = 1,
CUFRAMES_FORMAT_RGB = 2,
CUFRAMES_FORMAT_BGR = 3,
CUFRAMES_FORMAT_RGBA = 4,
CUFRAMES_FORMAT_GRAYSCALE = 5,
} cuframes_format_t;
```
| Format | Layout | Когда |
|---|---|---|
| `NV12` | Y plane + interleaved UV plane | NVDEC native, default для video pipeline'ов |
| `YUV420P` | Y + U + V separate planes | FFmpeg `yuv420p` |
| `RGB` | 24bpp packed RGB | ML inference, OpenGL |
| `BGR` | 24bpp packed BGR | OpenCV native |
| `RGBA` | 32bpp packed RGBA | overlays, compositing |
| `GRAYSCALE` | 8bpp single plane | depth maps, masks |
Format фиксирован для publisher'а в момент create — поменять нельзя без destroy + recreate с новым key.
## Policy & mode enums
### Publisher policy
```c
typedef enum cuframes_publisher_policy {
CUFRAMES_POLICY_DROP_OLDEST = 0,
CUFRAMES_POLICY_STRICT_WAIT = 1,
} cuframes_publisher_policy_t;
```
- `DROP_OLDEST` — publisher не ждёт, перезаписывает next slot. Slow consumer пропускает кадры. **Default для real-time.**
- `STRICT_WAIT` — publisher блокируется, пока все подписанные consumers не ACK'нут. Не теряет кадры, но slowest consumer тормозит всех. Для recording или критичной аналитики.
### Subscriber mode
```c
typedef enum cuframes_subscriber_mode {
CUFRAMES_MODE_NEWEST_ONLY = 0,
CUFRAMES_MODE_STRICT_ORDER = 1,
} cuframes_subscriber_mode_t;
```
- `NEWEST_ONLY` — брать самый свежий frame, пропускать промежуточные. **Default.**
- `STRICT_ORDER` — все frames по порядку. Если ring overflow — вернётся `CUFRAMES_ERR_DISCONNECTED`, нужно reconnect.
### Ownership mode
```c
typedef enum cuframes_ownership_mode {
CUFRAMES_OWNERSHIP_LIBRARY = 0,
CUFRAMES_OWNERSHIP_EXTERNAL = 1,
} cuframes_ownership_mode_t;
```
- `LIBRARY` — library владеет VMM-pool'ом (см. [Sync model](/docs/concepts/sync-vmm-stream)). Publisher делает `acquire()` → пишет → `publish()`. **Единственный поддерживаемый mode в v0.4.**
- `EXTERNAL`**в v0.4 deprecated.** `cuframes_publisher_create_external` возвращает `CUFRAMES_ERR_INVALID_ARG`. Для FFmpeg filter integration используй `LIBRARY` + одна D2D-копия в acquire'нутый slot (cuframes-rtsp-source именно так и работает с v0.4).
## Frame accessors
`cuframes_frame_t` — opaque handle на frame, полученный у subscriber'а. Валиден от `cuframes_subscriber_next` до `cuframes_subscriber_release`.
```c
typedef struct cuframes_frame cuframes_frame_t;
void *cuframes_frame_cuda_ptr(const cuframes_frame_t *frame);
cuframes_format_t cuframes_frame_format(const cuframes_frame_t *frame);
void cuframes_frame_size(const cuframes_frame_t *frame,
int32_t *width_out, int32_t *height_out);
int32_t cuframes_frame_pitch_y(const cuframes_frame_t *frame);
int32_t cuframes_frame_pitch_uv(const cuframes_frame_t *frame);
uint64_t cuframes_frame_seq(const cuframes_frame_t *frame);
int64_t cuframes_frame_pts_ns(const cuframes_frame_t *frame);
```
| Функция | Возвращает |
|---|---|
| `cuda_ptr` | CUDA device pointer на frame data (read-only для consumer'а) |
| `format` | `cuframes_format_t` |
| `size` | Ширина и высота в пикселях через out-параметры |
| `pitch_y` | Pitch (байт на строку) для Y plane или единственного plane |
| `pitch_uv` | Pitch для UV plane (NV12 / YUV420P); `0` для форматов без UV |
| `seq` | Sequence number — монотонная нумерация у publisher'а |
| `pts_ns` | Timestamp publisher'а (наносекунды, `CLOCK_MONOTONIC`) |
PTS epoch caveat: publisher и consumer могут иметь разные эпохи `CLOCK_MONOTONIC` (после publisher restart counter сбрасывается). Consumer должен sanity-checkить — например, детектить epoch change, когда `pts_ns_curr < pts_ns_prev`.
## Publisher API
### Config struct
```c
typedef struct cuframes_publisher_config {
const char *key; /* unique имя ("cam1"). Не NULL. */
int32_t width;
int32_t height;
cuframes_format_t format;
cuframes_ownership_mode_t ownership;
int32_t ring_size; /* 2..16, рекомендуется 4 */
cuframes_publisher_policy_t policy;
int32_t consumer_ack_timeout_ms; /* STRICT_WAIT; 0 = ждать вечно */
int32_t cuda_device;
uint64_t _reserved[4]; /* должно быть 0 */
} cuframes_publisher_config_t;
```
| Поле | Ограничения |
|---|---|
| `key` | ASCII `[a-zA-Z0-9_-]{1,63}`. Не NULL. |
| `width`, `height` | Pixels. Фиксированы после create. |
| `format` | См. [Pixel formats](#pixel-formats). Фиксирован. |
| `ownership` | В v0.4 — только `LIBRARY`. |
| `ring_size` | 2..16 для `LIBRARY`. Меньше — больше шанс overrun, больше — больше VRAM. |
| `policy` | См. [Policy](#publisher-policy). |
| `consumer_ack_timeout_ms` | Только для `STRICT_WAIT`. `0` = ждать бесконечно. |
| `cuda_device` | Обычно `0`. Должен совпадать с consumer'ским. |
| `_reserved` | Reserved для ABI-stability, должно быть нулями. |
### Create / destroy
```c
int cuframes_publisher_create(const cuframes_publisher_config_t *cfg,
cuframes_publisher_t **out);
int cuframes_publisher_create_external(const cuframes_publisher_config_t *cfg,
void *const *cuda_ptrs,
int32_t ptr_count,
size_t frame_size,
cuframes_publisher_t **out);
int cuframes_publisher_destroy(cuframes_publisher_t *pub);
```
`cuframes_publisher_create` аллоцирует `ring_size` × `frame_size` через `cuMemCreate(POSIX_FILE_DESCRIPTOR)`, открывает Unix socket `/run/cuframes/<key>.sock`, mmap'ит `/dev/shm/cuframes-<key>`. См. [Synchronization & VMM stream](/docs/concepts/sync-vmm-stream).
Ошибки:
| Код | Когда |
|---|---|
| `INVALID_ARG` | `cfg` NULL, ring_size out of range, key не проходит regex |
| `ALREADY_EXISTS` | Publisher с этим key уже есть и его процесс живой |
| `CUDA` | `cuMemCreate` fail (out of VRAM, unsupported driver) |
| `IO` | Не получилось `bind()` socket или `shm_open()` |
`cuframes_publisher_create_external`**в v0.4 возвращает `CUFRAMES_ERR_INVALID_ARG`**. EXTERNAL ownership убран потому, что VMM требует `cuMemCreate`-allocated memory. Для упомянутого FFmpeg filter use case — переходи на `LIBRARY` + одна `cudaMemcpyAsync(D2D)` в acquire'нутый slot. Cuframes-rtsp-source работает именно так начиная с v0.4.
`cuframes_publisher_destroy` шлёт `SHUTDOWN` всем connected subscribers, unlink'ает socket и shm. NULL-safe.
### Publish (LIBRARY mode)
```c
int cuframes_publisher_acquire(cuframes_publisher_t *pub,
void **cuda_ptr_out);
int cuframes_publisher_publish(cuframes_publisher_t *pub,
void *stream, /* cudaStream_t */
int64_t pts_ns);
```
`acquire` возвращает CUDA device pointer на следующий slot в ring'е для записи. Pointer стабилен, пока ты держишь ring slot — обычно до следующего `publish`.
Ошибки:
| Код | Когда |
|---|---|
| `TIMEOUT` | Все slots заняты в `STRICT_WAIT` mode |
| `INVALID_ARG` | `pub` NULL, или publisher был создан в EXTERNAL mode |
`publish` финализирует acquire'нутый slot. Внутри: `cuStreamSynchronize(stream)` гарантирует, что producer's writes hardware-coherent, затем atomic update `slot.seq` + `global_seq`. См. [Synchronization](/docs/concepts/sync-vmm-stream) — почему именно stream sync, а не CUDA events.
| Параметр | Значение |
|---|---|
| `stream` | CUDA stream, на котором писались данные. `0` для default stream. |
| `pts_ns` | Timestamp, рекомендуется [`cuframes_now_ns()`](#utils). |
### Publish (EXTERNAL mode)
```c
int cuframes_publisher_publish_external(cuframes_publisher_t *pub,
void *cuda_ptr,
void *stream,
int64_t pts_ns);
```
**В v0.4 deprecated** — см. note про `create_external` выше. Всегда возвращает `CUFRAMES_ERR_INVALID_ARG`.
## Subscriber API (sync)
### Config struct
```c
typedef struct cuframes_subscriber_config {
const char *key;
const char *consumer_name; /* NULL = auto */
cuframes_subscriber_mode_t mode;
int32_t cuda_device;
int32_t connect_timeout_ms; /* 0=fail, -1=ждать вечно */
uint64_t _reserved[4];
} cuframes_subscriber_config_t;
```
| Поле | Ограничения |
|---|---|
| `key` | Должен совпадать с publisher'ским |
| `consumer_name` | Если NULL — library сгенерирует `subscriber-<pid>-<random>`. Unique в пределах publisher'а — иначе `ALREADY_EXISTS`. MAX 32 subscribers. |
| `mode` | См. [Subscriber mode](#subscriber-mode) |
| `cuda_device` | Должен совпадать с publisher'ским — VMM FD импортируется на тот же device |
| `connect_timeout_ms` | `0` = fail сразу с `NOT_FOUND`; `-1` = ждать вечно |
### Create / destroy
```c
int cuframes_subscriber_create(const cuframes_subscriber_config_t *cfg,
cuframes_subscriber_t **out);
int cuframes_subscriber_destroy(cuframes_subscriber_t *sub);
```
`create` выполняет handshake (`HELLO``SUBSCRIBE``VMM_FDS`), импортирует N file descriptors через `cuMemImportFromShareableHandle`. См. [Protocol reference §3](/docs/reference/protocol).
Ошибки:
| Код | Когда |
|---|---|
| `NOT_FOUND` | Publisher с этим key не найден до `connect_timeout_ms` |
| `PROTOCOL` | Publisher имеет другую protocol version |
| `TOO_MANY` | Publisher уже имеет 32 subscriber'а |
| `ALREADY_EXISTS` | `consumer_name` занят |
| `CUDA` | `cuMemImportFromShareableHandle` fail |
`destroy` — graceful close: `UNSUBSCRIBE` msg → cleanup VMM mappings → close socket. NULL-safe.
### Next frame
```c
int cuframes_subscriber_next(cuframes_subscriber_t *sub,
void *consumer_stream,
cuframes_frame_t **frame_out,
int32_t timeout_ms);
int cuframes_subscriber_release(cuframes_subscriber_t *sub,
cuframes_frame_t *frame);
```
`next` блокируется до `timeout_ms`, ожидая новый frame. Семантика по mode:
- `NEWEST_ONLY` — возвращает самый свежий frame, пропускает промежуточные;
- `STRICT_ORDER` — следующий по seq; `DISCONNECTED` при overflow.
`consumer_stream` — твой CUDA stream, на котором будешь читать frame. В v0.4 синхронизация делается на стороне publisher'а через `cuStreamSynchronize`, так что параметр зарезервирован для будущего event-based fast path и сейчас не обязателен (`0` допустимо).
| Параметр | Значение |
|---|---|
| `consumer_stream` | CUDA stream consumer'а. `0` допустимо. |
| `frame_out` | Output handle. Освободить через `release`. |
| `timeout_ms` | `<0` = блокироваться, `0` = non-blocking (вернёт `WOULD_BLOCK`), `>0` = с timeout'ом |
Ошибки:
| Код | Когда |
|---|---|
| `WOULD_BLOCK` | `timeout_ms=0` и нет данных |
| `TIMEOUT` | За `timeout_ms` ничего не пришло |
| `DISCONNECTED` | Publisher shutdown, либо ring overrun в `STRICT_ORDER` |
`release` ACK'ает frame publisher'у (важно для `STRICT_WAIT` policy). NULL-safe. После release frame handle invalid.
## Subscriber API (async)
```c
typedef void (*cuframes_frame_callback_t)(const cuframes_frame_t *frame,
void *user_data);
typedef void (*cuframes_error_callback_t)(int err, const char *msg,
void *user_data);
int cuframes_async_subscriber_create(const cuframes_subscriber_config_t *cfg,
cuframes_frame_callback_t on_frame,
cuframes_error_callback_t on_error,
void *user_data,
cuframes_async_subscriber_t **out);
int cuframes_async_subscriber_destroy(cuframes_async_subscriber_t *sub);
```
Callback-based wrapper над sync API. Library поднимает internal thread, который сидит на `next`, вызывает `on_frame` / `on_error`, сам делает `release` после возврата из callback.
Ограничения:
- Frame **валиден только в течение callback'а** — никаких saved pointer'ов;
- Library использует internal CUDA stream, pre-wait уже выполнен — для своего stream'а используй sync API;
- `destroy` join'ит internal thread и гарантирует, что callback больше не вызовется после возврата (может занять до длительности текущего callback'а).
## Packet ring API
См. [Frame vs Packet ring](/docs/concepts/frame-vs-packet-ring) — когда нужно использовать packet ring.
### Flags
```c
#define CUFRAMES_PKT_FLAG_KEY 0x01u
#define CUFRAMES_PKT_FLAG_CORRUPT 0x02u
#define CUFRAMES_PKT_FLAG_DISCONTINUITY 0x04u
#define CUFRAMES_PKT_FLAG_LAST_IN_AU 0x08u
```
Биты соответствуют `AV_PKT_FLAG_*` у FFmpeg.
### Publisher-side
```c
typedef struct cuframes_packet_ring_options {
uint32_t ring_slots; /* default 64 */
uint32_t data_size; /* default 8 MiB */
uint32_t max_packet_size; /* default 2 MiB */
uint32_t codec_id; /* AV_CODEC_ID_* */
uint64_t _reserved[4];
} cuframes_packet_ring_options_t;
int cuframes_publisher_enable_packets(cuframes_publisher_t *pub,
const cuframes_packet_ring_options_t *opts);
int cuframes_publisher_set_codec_extradata(cuframes_publisher_t *pub,
const void *extradata, size_t size);
int cuframes_publisher_publish_packet(cuframes_publisher_t *pub,
const void *data, size_t size,
int64_t pts_ns, int64_t dts_ns,
uint32_t flags);
```
`enable_packets` создаёт отдельный SHM `/dev/shm/cuframes-<key>-packets`. **Должно быть вызвано до первого `publish_packet` и желательно до того, как subscribers начнут подключаться** — иначе subscriber увидит publisher без ring'а и не получит packets. `opts=NULL` → default sizing.
`set_codec_extradata` пишет SPS/PPS/VPS bytes в shared header. Subscribers (FFmpeg demuxer) подставят это в `AVCodecContext.extradata`. Size ≤ 4096 байт.
`publish_packet` записывает один NAL unit (Annex B). На IDR обязательно ставить `CUFRAMES_PKT_FLAG_KEY` — иначе late subscriber не сможет resync'нуться.
Ошибки:
| Код | Когда |
|---|---|
| `NO_PACKET_RING` | Не вызвали `enable_packets` |
| `PACKET_OVERSIZED` | `size > max_packet_size` |
| `ALREADY_EXISTS` | (`enable_packets`) ring уже активирован |
### Subscriber-side
```c
typedef struct cuframes_packet cuframes_packet_t;
const void *cuframes_packet_data(const cuframes_packet_t *p);
size_t cuframes_packet_size(const cuframes_packet_t *p);
int64_t cuframes_packet_pts(const cuframes_packet_t *p);
int64_t cuframes_packet_dts(const cuframes_packet_t *p);
uint32_t cuframes_packet_flags(const cuframes_packet_t *p);
uint64_t cuframes_packet_seq(const cuframes_packet_t *p);
int cuframes_subscriber_enable_packets(cuframes_subscriber_t *sub);
int cuframes_subscriber_next_packet(cuframes_subscriber_t *sub,
cuframes_packet_t **pkt_out,
int32_t timeout_ms);
int cuframes_subscriber_release_packet(cuframes_subscriber_t *sub,
cuframes_packet_t *pkt);
int cuframes_subscriber_get_codec_params(cuframes_subscriber_t *sub,
uint32_t *codec_id_out,
const void **extradata_out,
size_t *extradata_size_out);
```
`enable_packets` открывает второй SHM (если publisher его создал). Subscriber может одновременно иметь frames ring и packets ring, или только один из них.
`next_packet` — late subscriber на первом вызове начнёт с `last_keyframe_seq` publisher'а (decoder получит valid stream без glitches). См. [Protocol §10.14](/docs/reference/protocol).
Ошибки:
| Код | Когда |
|---|---|
| `WOULD_BLOCK` | `timeout_ms=0`, нет данных |
| `TIMEOUT` | За `timeout_ms` ничего не пришло |
| `PACKET_OVERRUN` | Subscriber отстал; library автоматически resync'нется на keyframe на next call |
| `DISCONNECTED` | Publisher shutdown |
| `NOT_FOUND` | (`enable_packets`) publisher не имеет packet ring |
`get_codec_params` возвращает pointer в library-local buffer, валидный пока subscriber жив. Если хочешь hold data past subscriber lifetime — копируй сам. Возвращает `NO_CODEC_PARAMS`, если publisher ещё не звал `set_codec_extradata`.
`release_packet` — NULL-safe. После release pointer'ы от `cuframes_packet_*` invalid.
## Utils
### Расчёт frame size
```c
int cuframes_calc_frame_size(cuframes_format_t format,
int32_t width, int32_t height,
size_t *size_out,
int32_t *pitch_y_out,
int32_t *pitch_uv_out);
```
Учитывает pitch alignment 256 байт (CUDA recommendation). `pitch_y_out` / `pitch_uv_out` опциональны (можно NULL). Возвращает `INVALID_ARG` для unknown format.
### Monotonic time
```c
int64_t cuframes_now_ns(void);
```
`CLOCK_MONOTONIC` в наносекундах. Используй как `pts_ns` для real-time pipeline'ов:
```c
cuframes_publisher_publish(pub, stream, cuframes_now_ns());
```
## См. также
- [C++ API](/docs/reference/api-cpp) — RAII wrapper.
- [Protocol reference](/docs/reference/protocol) — wire format, handshake, ABI layouts.
- [Frame vs Packet ring](/docs/concepts/frame-vs-packet-ring) — когда какой использовать.
- [Synchronization](/docs/concepts/sync-vmm-stream) — почему `cuStreamSynchronize`, а не CUDA events.
- [First publisher](/docs/getting-started/first-publisher) — рабочий C-пример.