AGX Xavier 搭建360环视教程【三、原理与数据流】

一、物理视频流的起点

📷1️⃣ 海康摄像头是怎么输出的?

  • 海康工业/监控摄像头通过 RTSP(Real Time Streaming Protocol)输出 H.264 编码的视频流。

  • 也就是说,摄像头本身并不是输出原始帧,而是内部 ISP(图像信号处理)模块把 CMOS 采集的 Bayer Raw 做了去噪、白平衡、去畸变(有限)、压缩成 H.264

  • 所以你拉到的 RTSP,本质是个H.264 编码码流,可以直接喂给硬件解码器

  • 总结一句:我理解为RTSP通信协议内部封装H.264格式的编码视频流。


🔗 2️⃣ GStreamer 拉流和解码是干啥?

  • 你用 rtspsrc + rtph264depay + h264parse + nvv4l2decoder

    • rtspsrc:从摄像头拉取 RTSP。我理解为:通信协议接收。

    • rtph264depay:把 RTP 包里的 H.264 取出来。我理解为:视频编码格式数据提取。

    • h264parse:重新整理一下码流(帧界定、SPS/PPS)。我理解为:拆包组包数据解析。

    • nvv4l2decoder:Jetson 平台的硬件解码,专门把 H.264 码流变成未压缩帧。我理解为:编码视频解压缩并解码。

  • 这一步的输出是 NV12 或 I420 格式的视频帧,但由于你后面要在 OpenCV 里处理,所以通常做了 videoconvert ! video/x-raw,format=BGR

    • videoconvert:颜色格式转换。

    • 转成 BGR,是为了直接塞给 OpenCV 的 cv::Mat,方便用 CUDA、remap、拼接等函数。

    • 因为OpenCV 默认处理的是 BGR 格式。


🎥 3️⃣ OpenCV 为什么默认是 BGR?

  • OpenCV 设计之初是 C++ 图像处理库,核心是 CPU 上的矩阵运算。

  • 绝大多数通用相机、图像文件(JPEG、BMP)都是 BGR 或 RGB。

  • OpenCV 一开始就面向“显示/算法/绘制/检测”场景,BGR/RGB 是最直观的排列顺序。

  • 所以 cv::imread 默认读出来就是 BGR,cv::imshow 也默认显示 BGR。

  • 这就导致你的中间环节(拼接、畸变校正)最好在 BGR 上做。


⚙️ 二、GPU 去畸变和拼接

  • 你用 cv::cuda::remap 对每路帧做鱼眼去畸变

    • 输入是 BGR 格式的 cv::cuda::GpuMat

    • 输出也是 BGR。

  • 如果要拼接,就把多路去畸变后的帧拿出来,放到更大的画布里(同样是 BGR)。

  • 所以,整个环视阶段,你处理的是多路 BGR → 拼成一张大的 BGR pano。


📌 三、为什么要转 I420?

  • 到这时,结果是 一张 BGR pano

  • 但是:

    • 编码器(H.264)最优处理的输入是 YUV420(I420)

    • YUV420 相当于把彩色图像拆成亮度(Y)+ 两个色度(U、V)。

    • U、V 是 1/2 宽高采样,压缩率高。

  • 所以,你需要 cv::cvtColor(BGR → YUV_I420)

    • CPU 做颜色空间转换。

    • 得到连续的 YUV420 平面数据。


🚦 四、appsrc 怎么塞给 GStreamer?

  • 转完 I420,做成 GstBuffer

  • appsrc 是个特殊元素,相当于:

    • “我这里有裸帧数据,要送给管道。”

  • 你设置:

    GstCaps* caps = video/x-raw, format=I420, width=1920, height=1080, framerate=30/1

    表示:

    我后面接收的流就是 I420,分辨率和帧率是这个,别搞错。

  • 然后 g_signal_emit_by_name(appsrc, "push-buffer", buffer),把数据推进去。


🎞️ 五、x264enc 是怎么编码的?

  • appsrc 的输出是连续裸帧

  • x264enc 负责把它做帧内/帧间压缩,编码成 H.264 NAL 单元(SPS、PPS、I 帧、P 帧…)。

  • 这里用了 speed-preset=ultrafast tune=zerolatency

    • 不做复杂分析(比如 B 帧)。

    • 马上输出,不用缓存 GOP。


📦 六、flvmux 为什么必须存在?

  • RTMP 协议要求推送的是 FLV 容器。

  • H.264 本身只是视频帧缺少时间戳、元信息(音视频多路复用、Metadata)。

  • flvmux 把裸 H.264 封装成 FLV Stream:

    • 附带 onMetaDatakeyframe index时间戳

    • 观众端(ffplay、VLC)才能正常解析。


🌐 七、rtmpsink 最终发出去

  • rtmpsink RTMP 协议握手把 FLV 封装通过 TCP 推给你的流媒体服务器(如 MediaMTX)。

  • 观众、ffplay 再从 RTMP 播放时,看到的就是这个流。


完整主线

[海康摄像头 H.264 RTSP]
  → [GStreamer 硬解码 → BGR]
    → [OpenCV CUDA 去畸变/拼接 → BGR pano]
      → [cv::cvtColor → I420]
        → [appsrc 推送裸帧]
          → [x264enc 压缩]
            → [flvmux 封装 FLV]
              → [rtmpsink 推 RTMP]
                → [MediaMTX/SRS]
                  → [观众/播放器]

🔑 核心理念

1️⃣ 解码 → BGR → CUDA 处理
2️⃣ 处理完要给观众,就必须重新编码 → H.264
3️⃣ 编码必须配合 RTMP 协议 → FLV 封装
4️⃣ 所有数据通过 appsrc 塞给 GStreamer → 完成可控推流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值