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 的代码量。
三、解码器选择与参数取舍
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,便于后续按通道统计与排障。
v4l2-ctl 确认 /dev/video* 节点与格式,再写入 URI;若直接使用 csi://0 失败,应检查设备树与驱动是否加载,而不是盲目调整解码参数。总结来看,多路接入的关键在于:用 nvmultiurisrcbin 统一管理多路源,用 nvv4l2decoder 走硬件解码,用 rtsp-reconnect-interval 与 select-rtp-protocol 应对网络异常,用 batched-push-timeout 与 max-batch-size 控制批处理节奏。把这几个参数调对,多路管道才能在断流、丢包和码率波动下保持稳定运行。