Files
cuframes/filter/README.md
T
gx 99df68f69c feat(filter): FFmpeg 7.1 cuframes:// input demuxer
Out-of-tree patch + sources для FFmpeg-демаксера, который позволяет любому
FFmpeg-based потребителю (Frigate, кастомные рекордеры, re-streamers)
читать "cuframes://<key>" как обычный URL — без своего NVDEC.

Состав:
- filter/cuframesdec.c — реализация (libavformat-style)
- filter/ffmpeg-7.1-cuframes-demuxer.patch — patch для FFmpeg n7.1
  (Makefile / allformats.c / configure)
- filter/README.md — инструкции по сборке + CLI smoke test + Frigate plan

v1 ограничения (намеренно):
- только NV12
- GPU → CPU копия через cudaMemcpy2DAsync (zero-copy AVHWFramesContext — v2)

CLI smoke test 2026-05-17 (host build FFmpeg + libcuframes,
publisher на камере 192.168.88.98 1920x1080 HEVC 25fps):
  ffmpeg -f cuframes -i cuframes://cam-ff -c:v copy -f null -
  → frame=100 fps=25 q=-1.0 speed=1x  ✓
  → "cuframes: connected to 'cam-ff' — 1920x1080 NV12"

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 09:02:12 +01:00

3.7 KiB
Raw Blame History

FFmpeg cuframes demuxer

Custom input format cuframes://<key> для FFmpeg 7.x. Подключается к запущенному cuframes-rtsp-source (или любому другому cuframes publisher'у) и выдаёт NV12 raw video stream.

Цель: позволить FFmpeg-based потребителям (Frigate, custom recorders, re-streamers) подписываться на уже декодированные кадры — без своего NVDEC. Один decode у publisher'а на N consumer'ов.

Что в этой директории

  • cuframesdec.c — реализация demuxer'а
  • ffmpeg-7.1-cuframes-demuxer.patch — patch для FFmpeg 7.1 (правит libavformat/Makefile, libavformat/allformats.c, configure и кладёт cuframesdec.c в libavformat/)

Limitations v1

  • Пиксельный формат: только NV12 (как нативно отдаёт NVDEC через cuframes-rtsp-source)
  • Кадры копируются GPU → CPU через cudaMemcpy2DAsync — для PoC совместимости со всеми FFmpeg-pipeline'ами. Zero-copy через AVHWFramesContext — запланировано в v2.
  • Один input = один stream; multi-stream publisher'ы — v2.

Как применить и собрать FFmpeg

# 1. Клон FFmpeg 7.1
git clone --depth 1 --branch n7.1 https://github.com/FFmpeg/FFmpeg.git ffmpeg
cd ffmpeg

# 2. Apply patch
patch -p1 < /path/to/cuframes/filter/ffmpeg-7.1-cuframes-demuxer.patch

# 3. Configure (минимальный пример; для Frigate-сборки используйте полный
#    набор опций из их Dockerfile + добавьте --enable-libcuframes)
./configure \
  --enable-libcuframes \
  --extra-cflags='-I/path/to/cuframes/include -I/usr/local/cuda/include' \
  --extra-ldflags='-L/path/to/cuframes/build/libcuframes -L/usr/local/cuda/lib64' \
  ...прочие опции вашей сборки...

# 4. Build
make -j$(nproc)

CLI smoke test

# Терминал 1 — publisher (host):
cuframes-rtsp-source --rtsp rtsp://... --key cam1 --verbose

# Терминал 2 — потребитель через нашу патченую FFmpeg:
LD_LIBRARY_PATH=/path/to/libcuframes ./ffmpeg \
    -f cuframes -i cuframes://cam1 \
    -c:v copy -f null -

Должно быть видно:

[cuframes @ ...] cuframes: connected to 'cam1' — 1920x1080 NV12
...
frame= 100 fps= 25 q=-1.0 size=N/A time=00:00:03.96 speed=1x

speed=1x — pipeline идёт в реальном времени с частотой камеры.

Опции demuxer'а

-cuda_device       <int>  CUDA device index (must match publisher's). Default 0.
-connect_timeout   <int>  Wait for publisher (ms); -1 = forever. Default 5000.

Frigate integration (план)

После того как Frigate-image пересобран с patched FFmpeg, в config.yml:

cameras:
  cam_parking:
    ffmpeg:
      inputs:
        - path: cuframes://cam-parking         # detect через cuframes
          roles: [detect]
        - path: rtsp://admin:***@cam/main      # recording — прямой RTSP
          roles: [record]                       # mux без decode, как раньше

Detect-стрим декодируется один раз в publisher'е cuframes-rtsp-source, recording по-прежнему mux'ится Frigate'ом из encoded RTSP без decode.

Upstream FFmpeg PR (план v2+)

После стабилизации API (NV12 → universal hwframe NV12 в CUDA context) patch можно подать в upstream FFmpeg. Пока что — out-of-tree patch для custom builds.