⚡ 内地版本:电子工业出版社已出版,并在大陆热销。Yocto项目实战教程:高效定制嵌入式Linux系统
⚡ 海外版本:繁体中文版支持全球华人购买,让更多开发者轻松掌握嵌入式系统核心技能。 金石堂购买链接
🎥 更多学习视频请关注 B 站:嵌入式Jerry
深入理解 GStreamer 在 Rockchip 平台的编解码机制:从原理到实战
在 Rockchip 平台上使用 GStreamer 进行视频处理时,很多工程师经常会遇到的问题包括:为什么视频不显示?为什么 CPU 占用过高?为什么提示 reason not-negotiated (-4)?这些问题的根源,其实都指向一个核心主题——GStreamer 的编解码原理与数据格式匹配机制。
本文将系统讲解 GStreamer 的运行原理,结合 Rockchip 平台上的 MPP(Media Process Platform)硬件架构,从数据流、格式匹配、编码参数、到性能调优,带你深入理解硬件编解码的工作机制,并提供可直接运行的实战命令。

一、GStreamer 的整体运行原理
GStreamer 是一个基于插件的多媒体框架。它通过“管线(Pipeline)”描述整个音视频数据流的处理路径:
源 (Source) → 解析 (Parser) → 解码 (Decoder) → 转换 (Convert) → 显示/保存 (Sink)
一个典型的视频播放管线如下:
gst-launch-1.0 filesrc location=test.h265 ! h265parse ! mppvideodec ! videoconvert ! autovideosink
在这条管线中:
filesrc读取文件;h265parse解析 H.265 码流;mppvideodec调用 Rockchip 的硬件解码器(VDPU / RKVDEC);videoconvert将 NV12 转换为 RGB 以便显示;autovideosink自动选择合适的视频输出。
GStreamer 的强大之处在于——所有元素(Element)通过 Caps(能力集)协商 实现自动连接。这也是出现 not-negotiated 错误的根源:一旦上游和下游的格式不匹配,整个管线就无法建立。
二、Rockchip 平台的 MPP 硬件编解码架构
Rockchip 平台上的视频处理由 MPP (Media Process Platform) 框架管理。它封装了底层的 VPU(Video Processing Unit)驱动接口,对上层 GStreamer 提供统一的硬件加速访问。
常见的硬件模块包括:
| 模块名称 | 功能 | 典型设备节点 |
|---|---|---|
| VDPU | Video Decode Processing Unit,视频解码单元 | /dev/mpp_service |
| VEPU | Video Encode Processing Unit,视频编码单元 | /dev/mpp_service |
| RKVDEC | 新一代视频解码单元,支持 8K@60fps | /dev/rkvdec |
| RKVENC | 新一代视频编码单元 | /dev/rkvenc |
在 GStreamer 中,这些模块通过以下插件调用:
| 功能 | 插件名称 | 调用硬件 |
|---|---|---|
| H.264/H.265 解码 | mppvideodec | VDPU / RKVDEC |
| H.264 编码 | mpph264enc | VEPU / RKVENC |
| H.265 编码 | mpph265enc | VEPU2 / RKVENC |
| JPEG 解码/编码 | mppjpegdec / mppjpegenc | JPEGD / JPEGE |
三、数据格式与 Caps 协商机制
GStreamer 管线的每个连接点都必须满足格式匹配,否则协商失败。例如:
ERROR: streaming stopped, reason not-negotiated (-4)
这个错误的含义是:上游(例如 v4l2src)输出的格式与下游(例如 mppvideodec)输入期望的格式不一致。
我们用 v4l2-ctl 来查看设备的输出格式:
v4l2-ctl --device=/dev/video11 --list-formats-ext
常见输出示例:
| Pixel Format | 说明 | GStreamer 对应 caps | 是否需解码 |
|---|---|---|---|
| NV12 | 原始 YUV 帧 | video/x-raw, format=NV12 | ❌ |
| H.264 | 编码视频流 | video/x-h264 | ✅ |
| H.265 | 编码视频流 | video/x-h265 | ✅ |
| MJPG | 压缩 JPEG 流 | image/jpeg | ✅ |
如果你的摄像头输出的是 NV12,就不能写 video/x-h265,否则就会触发 reason not-negotiated (-4)。
正确做法是根据设备格式选择对应管线:
# 原始帧
v4l2src ! video/x-raw,format=NV12 ! autovideosink
# H.264 码流\ nv4l2src ! video/x-h264 ! h264parse ! mppvideodec ! autovideosink
# H.265 码流
v4l2src ! video/x-h265 ! h265parse ! mppvideodec ! autovideosink
四、编码参数详解:format、framerate、bps、gop、rc-mode
在编码过程中,最核心的几个参数包括:
1. format(输入像素格式)
Rockchip 的硬件编码器要求输入为 NV12(YUV420 半平面格式)。
video/x-raw, format=NV12, width=3840, height=2160
2. framerate(帧率)
帧率表示每秒的帧数:
| 设置 | 含义 |
|---|---|
framerate=30/1 | 每秒 30 帧(常见) |
framerate=60/1 | 每秒 60 帧(高帧率) |
GStreamer 并不会强制输出帧率,它依赖于摄像头实际采集能力。若摄像头只支持 30fps 而强行设为 60fps,会导致协商失败或降级运行。
3. bps(比特率)
bps 表示编码后每秒的视频数据量(bit per second),控制压缩质量与文件大小。
| 分辨率 | 推荐码率 | 备注 |
|---|---|---|
| 720p | 2~5 Mbps | 一般监控场景 |
| 1080p | 6~10 Mbps | 高清视频 |
| 4K | 15~25 Mbps | 高质量录制 |
4. gop(关键帧间隔)
gop=60 表示每隔 60 帧插入一个 I 帧。I 帧越密集,seek 性能越好但文件更大。
5. rc-mode(码率控制模式)
vbr(可变码率):画质优先,码率随画面复杂度动态变化;cbr(固定码率):码率恒定,适合网络推流。
示例:
mpph265enc bps=20000000 rc-mode=vbr gop=60
五、实战:从 Raw 数据到编码文件
假设摄像头输出原始 NV12 数据(未压缩),我们可以用以下命令进行硬件编码:
gst-launch-1.0 -v \
v4l2src device=/dev/video11 io-mode=dmabuf ! \
video/x-raw,format=NV12,width=3840,height=2160,framerate=30/1 ! \
mpph265enc bps=20000000 rc-mode=vbr gop=60 ! \
h265parse ! mp4mux ! filesink location=/tmp/test_h265_hwenc.mp4 sync=false
运行结果:
/tmp/test_h265_hwenc.mp4为硬件编码生成的视频文件;- CPU 占用约 10%,说明使用了硬件加速;
- 可直接用
mpv或ffplay播放:
mpv /tmp/test_h265_hwenc.mp4
六、验证:硬件解码与播放
解码时使用 MPP 硬件加速:
gst-launch-1.0 -v filesrc location=/tmp/test_h265_hwenc.mp4 ! \
qtdemux ! h265parse ! mppvideodec ! videoconvert ! autovideosink sync=false
在无图形环境下,可改用:
... ! videoconvert ! kmssink sync=false
GStreamer 会自动选择硬件解码路径,解码速度可轻松达到 4K@60fps,CPU 占用保持在 15% 以下。
七、完整验证:编码 + 解码链路测试
你可以直接在一条管线中完成硬件编码与解码的验证:
gst-launch-1.0 -v \
v4l2src device=/dev/video11 io-mode=dmabuf ! \
video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! \
mpph265enc bps=8000000 rc-mode=vbr gop=60 ! \
h265parse ! mppvideodec ! videoconvert ! autovideosink sync=false
数据流:
Raw 帧 → H.265 编码 (VEPU) → 解码 (VDPU) → 显示
如果这条命令能正常显示画面,就说明你的 MPP 编解码驱动全部正常工作。
八、常见问题与解决方案
| 问题现象 | 原因 | 解决方法 |
|---|---|---|
reason not-negotiated (-4) | caps 不匹配 | 检查摄像头输出格式,修改 video/x-raw 或 video/x-h265 |
EGL_NOT_INITIALIZED | 没有图形环境 | 使用 xvimagesink 或 kmssink |
| 画面卡顿或掉帧 | bps 太低 / framerate 不匹配 | 提高码率,确认摄像头帧率支持 |
| CPU 占用过高 | 未使用硬件加速 | 确认使用 mpph265enc / mppvideodec |
九、性能与调优建议
| 项目 | 软件编解码 (CPU) | 硬件编解码 (MPP) |
|---|---|---|
| 1080p 编码帧率 | ~10fps | 30fps 稳定 |
| 4K 编码帧率 | <5fps | 60fps 稳定 |
| CPU 占用率 | 80%+ | 10~20% |
| 功耗 | 高 | 低 |
优化建议:
- 优先使用 NV12 输入格式。
- 码率控制
bps需与分辨率成比例。 - 避免盲目提高帧率,优先保证流畅与稳定。
- 使用
tee元素实现录制与显示双路径:
gst-launch-1.0 -v \
v4l2src device=/dev/video11 io-mode=dmabuf ! \
video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! tee name=t \
t. ! queue ! videoconvert ! autovideosink sync=false \
t. ! queue ! mpph265enc bps=6000000 rc-mode=vbr ! h265parse ! mp4mux ! filesink location=/tmp/dual_output.mp4 sync=false
十、总结:GStreamer 与 Rockchip MPP 的协同逻辑
| 环节 | 关键点 | 对应模块 |
|---|---|---|
| 采集 | 从 /dev/video 获取 NV12 原始帧 | v4l2src |
| 编码 | 压缩为 H.264/H.265 | mpph264enc / mpph265enc |
| 解码 | 还原为原始帧 | mppvideodec |
| 显示 | 显示或保存输出 | kmssink / autovideosink / filesink |
通过合理设置数据格式(NV12)、帧率(framerate)、码率(bps)与匹配的 Caps,Rockchip 平台可在 GStreamer 框架下充分发挥硬件编解码能力,轻松实现 4K@60fps 的实时视频采集、编码与播放。
一句话总结:
GStreamer 负责“搭管线”,MPP 负责“干活”。只要格式匹配、参数合理,Rockchip 的硬件编解码可以做到高效、稳定、低功耗。
⚡ 内地版本:电子工业出版社已出版,并在大陆热销。Yocto项目实战教程:高效定制嵌入式Linux系统
⚡ 海外版本:繁体中文版支持全球华人购买,让更多开发者轻松掌握嵌入式系统核心技能。 金石堂购买链接
🎥 更多学习视频请关注 B 站:嵌入式Jerry

10万+

被折叠的 条评论
为什么被折叠?



