应直接选用NVIDIA Video Codec SDK:它原生支持多路H.264/H.265硬解,每路独占NVDEC单元,延迟比FFmpeg cuvid低3–5ms,避免线程锁竞争与队列阻塞;需Compute Capability ≥ 5.0、驱动≥515、C++实现,且须为每路独立创建实例、分配/释放显存、正确配置PTS时间戳。

用 NVIDIA Video Codec SDK 还是 FFmpeg + CUDA?
直接选 NVIDIA Video Codec SDK。它原生支持多路 H.264/H.265 硬解,每路独占一个 NVDEC 单元(如 A10/A100 上最多 8–16 路),延迟比 FFmpeg 的 cuvid 封装低 3–5ms,且避免了 FFmpeg 解码器线程锁竞争。FFmpeg + CUDA 更适合单路或需软解兜底的场景,多路时容易在 avcodec_send_packet 阶段因内部队列阻塞导致帧率抖动。
关键点:NVIDIA Video Codec SDK 要求显卡 Compute Capability ≥ 5.0(Maxwell 及以上),驱动版本 ≥ 515,且必须用 C++ 编写解码回调——不能用纯 C 接口混搭 STL 容器。
如何为每路视频分配独立 NVDEC 实例并避免内存越界?
NVDEC 不支持“共享实例 + 多路输入”,必须为每路显式调用 nvVideoDecoder::Create() 创建独立对象。常见错误是复用同一块 CUdeviceptr 显存缓冲区,导致多路解码输出覆盖——每路需单独分配:
-
cuMemAlloc(&d_yuv_frame, width * height * 3 / 2)(NV12 格式) - 绑定到该路
nvVideoDecoder实例的SetOutputSurface() - 销毁时按路调用
cuMemFree(d_yuv_frame),不能全局统一释放
漏掉任一 cuMemFree 会导致显存泄漏,连续运行 2 小时后可能触发 CUDA_ERROR_OUT_OF_MEMORY。
立即学习“C++免费学习笔记(深入)”;
YUV 到 RGB 预处理怎么绕过 CPU 拷贝实现 GPU 端流水线?
别用 cuMemcpyDtoH 拉到主机内存再用 OpenCV 转——这会打断流水线。直接在 GPU 上用 cuLaunchKernel 调用自定义 CUDA kernel 做 NV12 → RGB 转换,或者更省事:接入 NPP nppiYUV420ToRGB_8u_P3C3R(注意是 P3C3 版本,不是 C1/C3 混用版)。
性能陷阱:nppiYUV420ToRGB_8u_P3C3R 要求输入为 planar NV12(Y、U、V 分三块内存),而 NVDEC 输出默认是 packed NV12(Y 和 UV 交错)。必须先用 nppiCopy_8u_C1R 拆分,否则得到全绿或全黑画面。
为什么多路解码后帧时间戳(PTS)会乱序?
不是解码器问题,是没正确配置 decodeFrameInfo.timestamp。NVDEC 默认不填充 PTS,需在初始化时设置 stCreateParams.enablePTSTimestamp = 1,并在每次 DecodeFrame() 前手动把当前 packet 的 PTS 写入 stDecodeFrameInfo.timestamp 字段(单位微秒)。否则所有帧 timestamp=0,后续做音画同步或帧率控制时会误判为瞬时爆发流量。
另一个坑:stDecodeFrameInfo.timestamp 是 int64_t,但某些 RTSP 流送来的 PTS 是 32 位 wrap-around 计数,需在用户层做 if (new_pts 补全。
实际部署时最常被忽略的是 PCIe 带宽瓶颈:8 路 1080p60 解码约需 12 GB/s 带宽,PCIe 3.0 x16 仅 16 GB/s,若同时跑预处理+推理,极易触发 CUresult=CUDA_ERROR_LAUNCH_TIMEOUT。得关掉 GPU 的 TCC 模式(用 nvidia-smi -i 0 -dmbs 0),改用 WDDM 兼容模式释放部分带宽余量。


















