Symptom (run #1826 fail на u4-runner):
Bootstrap step молча установил Node 12 (Ubuntu default) вместо Node 20
из NodeSource → actions/checkout@v4 не парсится (ES2022 static blocks).
Cause:
curl ... setup_20.x на slow network (u4 через VPN) timeout/fail silently,
apt install fallback на default ubuntu nodejs (Node 12). Без error.
Fix:
- curl --retry 3 --retry-delay 5 --connect-timeout 30
- retry-loop на NodeSource setup (3 попытки)
- явная verification major version >= 18 после install, fail с exit 1
если установился Node < 18
Применяется к обоим jobs (cmake-build и filter-build).
Связано: PR #4 (v0.2), run #1826 fail.
Тесты:
- libcuframes/tests/test_packet_ring.c — 2 scenarios:
1) normal flow: 1 pub × 1 sub × 2000 packets, varied sizes, GOP=30,
payload integrity check (seq в первых 8 байтах + pattern). PTS
monotonicity, first KEY seq, нет data errors.
2) slow consumer (10ms delay): publisher 200 fps, subscriber должен
detect OVERRUN, library resync на keyframe — verify received >10
даже на сильно медленном консьюмере.
- libcuframes/tests/CMakeLists.txt: add_test packet_ring_basic.
Docs:
- CHANGELOG.md: новая [Unreleased] секция с full v0.2 highlights и
явно declared limitations (sub-stream, audio, codec change → v0.3).
- docs/integrations/frigate.md: новая секция "v0.2: dual-input (detect +
record через один RTSP)" с config example, requirements, trade-offs.
Связано: #2, PR #4. Step 6 (final) перед снятием draft.
- cuframes::Publisher (C++ wrapper): добавлены enable_packets(),
set_codec_extradata(), publish_packet() методы.
- cuframes-rtsp-source: новый CLI flag --enable-packet-ring. При его
установке после opening stream — pub.enable_packets(codec_id) +
set_codec_extradata из vstream->codecpar->extradata.
- В main loop: после av_read_frame, до avcodec_send_packet, packet
публикуется в packet ring с конверсией pts/dts из stream_tb в ns,
AV_PKT_FLAG_KEY/CORRUPT/DISCONTINUITY → CUFRAMES_PKT_FLAG_*.
Тест:
cuframes-rtsp-source --rtsp rtsp://... --key cam1 --enable-packet-ring
# frames consumer'ы продолжают работать через cuframes:// (как v0.1)
# record consumer'ы могут brать packets через cuframes_packets:// (Step 5)
Связано: #2, PR #4.
Две идеи добавлены в новую секцию "Future ideas" (без ETA):
- gst-cuframes-src: GStreamer source-element для DeepStream / обычных
GStreamer pipeline'ов. Аналог FFmpeg-демуксера для другого стека.
- vf_cuda_grid: FFmpeg filter с runtime grid composition полностью
на GPU. Заменяет custom C++ GridComposer cctv-processor (см. gx/cctv#22).
Превращает cuframes в GPU-native video routing platform.
Обе идеи waiting на планирование, scope для v0.5+.
Жёсткий URL git.goldix.org не работает на u4-runner — там
gitea доступен только через VPN (10.8.0.6:3222). Используем
переменную runner'а — на R9 = 192.168.88.23:3222, на u4 = 10.8.0.6:3222.
git clone github.com/FFmpeg/FFmpeg на слабом интернете оборвался через 11 мин
(RPC HTTP/2 CANCEL). Local gx/ffmpeg-patched n7.1-cuframes branch имеет
patch уже applied — clone instant без internet round-trip.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- docs/troubleshooting.md — 13 секций с реальными grабельками которые мы
прошли: cudaIpcOpenEventHandle invalid device context (pid namespace),
s6-overlay vs pid share, scale_cuda missing (cuda-llvm + stdbit.h glibc 2.36),
libcuframes not found install paths, ffbuild/ missing source, GMP no working
compiler (long-long reliability), zlib.net deprecated URL, RTSP/RTP UDP
docker NAT, gitea actions Node version
- docs/architecture.md — Appendix A "Production deployment notes" с реальными
observations после 24h+ run: что подтвердилось, что доработали, что не учли
- docs/requirements.md — production deployment matrix + Docker namespace
requirements таблица (cross-container CUDA IPC требует 5 условий)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
cmake --install теперь правильно кладёт libcuframes.so/.a в lib/ и
headers в include/cuframes/. Нужно для downstream builders (FFmpeg
patched build, deb packaging).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
docs/integration.md — детальный guide для интеграции в существующий CCTV
docker-compose: критичные требования (ipc=shareable/container, общий
shared volume для socket), пример CuframesSource для cctv-processor,
verification checklist, troubleshooting (timeout, ipc namespace mismatch,
high latency). Зафиксировано: v0.1 frigate-decode не убирается без
patch'а FFmpeg — это v0.2 scope.
docker/Dockerfile.runtime — multi-stage build (devel → runtime), копирует
libcuframes.so + cuframes-rtsp-source + sub_count в /usr/local. Образ
~700 MB (vs ~7 GB у dev'а). Smoke-test: бинарки запускаются, ldd видит
все нужные libs.
docker-compose.example.yml — reference docker-compose с правильным ipc
mode и volume mounts для копирования в свои проекты.
.dockerignore — исключает build/ и build-*/ из COPY context.
README обновлён: статус v0.1 done, quickstart с реальным docker run,
ссылка на integration guide.
cuframes-rtsp-source — standalone bridge между RTSP/file и cuframes IPC.
Декодирует на CUDA (nvdec), копирует D2D в pre-allocated pool (EXTERNAL
ownership), публикует через cuframes. --realtime для pacing файлового
ввода, --loop для зацикливания. Альтернатива FFmpeg-фильтра до v0.2
(filter требует patch FFmpeg, конфликтует с Frigate's bundled build).
examples/sub_count — reference subscriber на raw C API: counts frames,
trackit gaps, выходит clean при disconnect/timeout/SIGINT.
test_stress (4 subscribers × 2000 frames @ 120fps) — PASS на RTX 5090.
0 torn frames у всех consumers (включая 2 slow с 5ms sleep).
Smoke-проверено: testsrc 25fps → cuframes-rtsp-source → cuframes IPC
→ sub_count (отдельный процесс) → 200/200 frames, 0 gaps, avg_fps=25.2.
R3 (publisher API не работает с FFmpeg's hwframe pool):
- Добавлен ownership_mode field: LIBRARY (default, текущий API) или EXTERNAL.
- Новая функция publisher_create_external(cuda_ptrs[], ptr_count, frame_size)
для случая когда CUDA память выделена upstream (FFmpeg AVHWFramesContext).
- Новая publish_external(cuda_ptr) — публикует один из pre-registered handles.
- Для FFmpeg filter теперь zero-copy: filter получает AVFrame, library уже
имеет IPC handle на этот pointer (registered в create), publish — atomic seq bump.
R1/R2 closure отражено в API:
- publish() теперь принимает cudaStream_t — library делает cudaEventRecord
вместо stream sync.
- next() теперь принимает consumer_stream — library делает cudaStreamWaitEvent
перед возвратом frame. Cross-process sync через cudaIpcEventHandle_t.
Y6 (opaque frame через handle, не struct с _internal_*):
- cuframes_frame_t стал opaque (typedef struct, не определена).
- Accessor functions: cuda_ptr, format, size, pitch_y, pitch_uv, seq, pts_ns.
- ABI-stable при добавлении полей в minor releases.
Y7 (redundant try_next):
- Удалён subscriber_try_next. next(.., timeout_ms=0) — non-blocking
с CUFRAMES_ERR_WOULD_BLOCK.
Y5 (consumer_name uniqueness):
- Документировано что duplicate name → ALREADY_EXISTS.
- Добавлен CUFRAMES_ERR_TOO_MANY для случая >32 subscribers.
Y9 (pts_ns clock):
- Документировано что MONOTONIC у publisher'а, consumer должен sanity-check
на epoch reset при publisher restart.
Также:
- meta-блок (cuframes_frame_meta_t) перестал быть public — meta доступна
через accessor'ы на opaque frame.
- _reserved[4] в configs для forward-compat без breaking ABI.
- Добавлен cuframes_protocol_version() — wire protocol majoring отдельно
от lib version.
Готов к Step 2 (docs/protocol.md + implementation).
См. spike-v2 (commit ad54305) + arch review 2026-05-15.
cudaStreamSynchronize-only фактически работает на single-host single-GPU
(0 torn в 4 scenarios PoC), но NVIDIA Programming Guide §3.2.8 не даёт
contractual гарантии. Переключаемся на cudaIpcEventHandle_t как default,
stream-sync остаётся опциональным fallback.
Net: +20µs mean latency, -3× max latency (predictable tail), future-proof
для multi-GPU.
Architectural review (2026-05-15) указал что cudaStreamSynchronize-only на
producer-side не достаточен для cross-process visibility — NVIDIA Programming
Guide §3.2.8 требует cudaIpcEventHandle_t. Phase 0 PoC v1 не проверял этот
случай из-за cudaMemcpy который имеет implicit barriers.
spike-v2 воспроизводит правильный сценарий: consumer запускает verify_kernel
на ОТДЕЛЬНОМ stream'е (real-world use case — PyTorch / OpenCV CUDA), pattern
включает row-based component для отлова partial-frame torn.
Запуск 4 scenarios × 1500/600 frames:
A-fhd60 (stream sync, FHD@60): 0 torn, p99=267µs, max=14.7ms
B-fhd60 (event sync, FHD@60): 0 torn, p99=344µs, max=5.2ms
A-4k30 (stream sync, 4K@30): 0 torn, p99=606µs, max=4.4ms
B-4k30 (event sync, 4K@30): 0 torn, p99=437µs, max=3.7ms
Все 4 показали 0 torn frames. R1 на single-host single-GPU фактически
не воспроизводится — но NVIDIA contractually не гарантирует это.
Decision: events as default (R1/R2 resolved). Architecture.md §6.6 закрыт.
Tradeoff: mean latency +20µs, max latency в 3× ниже (predictable tail) +
future-proof для multi-GPU.
Также Dockerfile.dev — апдейт CUDA до 13.0.3 (12.4 не существует с devel-ubuntu24.04).
Связано с PR review: R1, R2, R3 (R3, R4 — в следующих коммитах).