4. 多路视频接入与解码

DeepStream 的多路视频接入,本质上是把不同来源的媒体流统一成 GPU 可处理的解码帧。Jetson 平台上,接入层由 GStreamer 插件承担:nvurisrcbin 封装了“源 + 解析 + 解码”的完整链路,nvmultiurisrcbin 则在其上再包一层多路管理,支持动态增删源和断流重连。理解这两者的差异,是搭建稳定多路管道的第一步。

一、五类输入源与对应 URI 写法

DeepStream 通过 URI 描述输入,不同协议的前缀决定了底层使用哪个 GStreamer source 元素:

  • RTSP:rtsp://user:pass@192.168.1.10:554/stream1,底层为 rtspsrc,走 UDP/TCP 传输,是安防摄像机最常用的接入方式。
  • RTMP:rtmp://live.example.com/app/streamkey,底层为 rtmpsrc,常见于推流服务器或直播场景。
  • File:file:///opt/video/sample.mp4,底层为 filesrc + qtdemux,适合离线回放与算法验证。
  • USB:v4l2:///dev/video0,底层为 v4l2src,用于 UVC 摄像头或采集卡,需注意 io-mode 与分辨率协商。
  • GMSL:Jetson 上通过 nvarguscamerasrc 或 v4l2src 访问 CSI/GMSL 相机,如 csi://0,常用于车载与机器人多目场景。

需要注意的是,RTSP 与 RTMP 属于网络流,存在抖动、丢包和断连;File 是有限长度流,播放结束会触发 EOS;USB 与 GMSL 属于本地设备,问题多集中在格式协商与带宽。四类问题的排查方向完全不同。

二、nvurisrcbin 与 nvmultiurisrcbin 的分工

nvurisrcbin 是单路 URI 源封装,内部自动串联 uridecodebin、nvv4l2decoder、nvstreammux 所需的 capsfilter,并暴露 uri、source-id、rtsp-reconnect-interval、latency、select-rtp-protocol 等属性。它适合“每路一个 bin,再统一接入 streammux”的写法。

nvmultiurisrcbin 则把多路管理收进一个元素:通过 uri-list 传入逗号分隔的 URI 列表,内部为每路创建独立的 nvurisrcbin,并统一输出到内部 nvstreammux。它还提供 batched-push-timeout、max-batch-size、live-source 等属性,并支持运行时通过 nvmultiurisrcbin 的 REST API 或 add_uri/remove_uri 动态增删通道。多路场景优先选它,可以显著减少手工管理 bin 的代码量。

多路视频接入与解码链路 RTSP 摄像机 RTMP 推流 File 文件 USB / V4L2 GMSL / CSI nvmultiurisrcbin nvurisrcbin #0 nvurisrcbin #1 nvurisrcbin #N uri-list / add_uri / remove_uri nvv4l2decoder NVDEC 硬件解码 nvstreammux 批处理 → PGIE 码流异常与重连策略 • rtsp-reconnect-interval=10:断流后每 10 秒重试 • select-rtp-protocol=4:强制 TCP,规避 UDP 丢包 • latency=200:增大抖动缓冲,缓解花屏 • 监听 pad-added / EOS / ERROR,动态 remove_uri 后重新 add_uri

三、解码器选择与参数取舍

Jetson 上解码统一走 NVDEC,对应元素是 nvv4l2decoder。它支持 H.264、H.265、VP9、AV1(视 JetPack 版本)等格式,关键属性包括:

  • enable-max-performance=1:允许解码器跑在最高性能档,适合多路高分辨率场景。
  • drop-frame-interval:按间隔丢帧,用于降低下游推理压力,例如设为 5 表示每 5 帧取 1 帧。
  • num-extra-surfaces:增加解码输出缓冲,缓解下游处理慢导致的丢帧。
  • cudadec-memtype:指定输出显存类型,多路场景下影响显存占用。

如果输入是 MJPEG 或需要 CPU 解码,可退回 avdec_h264 等软解元素,但多路场景下 CPU 会迅速成为瓶颈,应尽量避免。判断依据很简单:用 nvidia-smi 或 tegrastats 观察 NVDEC 占用率,若接近 100% 而 CPU 空闲,说明瓶颈在解码器数量而非 CPU。

四、码流异常与重连策略

网络流最常见的异常有三类:断流(摄像机掉线或网络中断)、花屏(UDP 丢包导致关键帧缺失)、卡顿(码率突增超过解码能力)。对应的处理手段如下:

# 典型 nvmultiurisrcbin 配置片段
uri-list=rtsp://cam1/stream,rtsp://cam2/stream,file:///opt/video/a.mp4
rtsp-reconnect-interval=10
select-rtp-protocol=4
latency=200
batched-push-timeout=40000
max-batch-size=4
live-source=1

其中 rtsp-reconnect-interval 是断流重连的核心:设为 0 表示不重连,设为正数表示断流后每隔该秒数重试。若摄像机支持 ONVIF,还可结合 rtspsrc 的 do-retransmission 与 rtpjitterbuffer 降低花屏概率。对于 File 源,播放结束会触发 EOS,若希望循环播放,可在管道中插入 multifilesrc loop=true 或监听 EOS 后重新 seek。

多路场景建议把 batched-push-timeout 设为 40000(微秒),即 40ms,与 25fps 的帧间隔匹配;若某路断流,streammux 会等待该路数据,超时后才继续,避免整条管道被单路拖死。

五、一个可复现的多路接入示例

下面用 nvmultiurisrcbin 接入 2 路 RTSP + 1 路 File,并输出到 nvstreammux 后接 fakesink 验证链路是否通:

gst-launch-1.0 -e \
  nvmultiurisrcbin name=src \
    uri-list="rtsp://192.168.1.10:554/stream1,rtsp://192.168.1.11:554/stream1,file:///opt/video/sample.mp4" \
    rtsp-reconnect-interval=10 \
    select-rtp-protocol=4 \
    latency=200 \
    batched-push-timeout=40000 \
    max-batch-size=4 \
    live-source=1 \
  ! nvstreammux name=mux batch-size=4 width=1920 height=1080 \
  ! fakesink sync=false

运行后观察终端是否出现 Pipeline is PREROLLED 与持续 fakesink 计数。若某路 RTSP 断开,日志会出现 reconnecting 提示,10 秒后自动恢复;若 File 播放结束,管道会收到 EOS,此时可判断为正常结束而非故障。实际工程中,建议把 fakesink 替换为 nvstreamdemux + 推理分支,并对每路单独打上 source-id,便于后续按通道统计与排障。

GMSL 相机在 Jetson 上通常需要先通过 v4l2-ctl 确认 /dev/video* 节点与格式,再写入 URI;若直接使用 csi://0 失败,应检查设备树与驱动是否加载,而不是盲目调整解码参数。

总结来看,多路接入的关键在于:用 nvmultiurisrcbin 统一管理多路源,用 nvv4l2decoder 走硬件解码,用 rtsp-reconnect-interval 与 select-rtp-protocol 应对网络异常,用 batched-push-timeout 与 max-batch-size 控制批处理节奏。把这几个参数调对,多路管道才能在断流、丢包和码率波动下保持稳定运行。