
一、问题背景我用MYZR-RK3588-EK360官网为MYZR-RK3588-EK360 — 明远智睿的文档 文档生成WebRTC网页实时流效果如下网页实时流通过GStreamer的webrtcbin插件实现。webrtcbin负责RTP封装、SRTP加密、DTLS握手、ICE穿透、NAT处理、SDP offer/answer、数据通道.....这样这些功能就不用用户自己实现了。webrtcbin的官方文档为https://gstreamer.freedesktop.org/documentation/webrtc/?gi-languagec整个网页实时流的架构为节目单素材解码 │ ├─ 原始视频 ─→ tee │ ├─→ kmssink │ └─→ mpph264enc → H.264 │ └─ 原始音频 ─→ 音轨选择/音量 → tee ├─→ alsasink └─→ opusenc → Opus H.264 Opus ↓ 每个浏览器一个 webrtcbin ↓ 浏览器 RTCPeerConnection但是给某个素材生成实时流是软件崩溃了出现问题的素材为文件复仇者联盟4-单音轨.mp4视频编码H.264可见分辨率1280x718硬件解码stride1280x720帧率约 29.97 fps二、故障现象HDMI 已正常显示画面时发送 streamControl start接口先返回成功[WebRTC-1] Shared H.264/Opus encoder started [ChannelPlayer-1] ReloadPlaylist called Response sent: {code:200,data:{channelIndex:1,enabled:true,...},msg:Success.}播放器随后重建 HDMI pipeline并在视频格式转换阶段输出Video sink: capsfilter capsvideo/x-raw,formatNV12 ! identity drop-allocationtrue ! tee namestream_video_tee ... ! videoconvert ! video/x-raw,formatI420 ! intervideosink ... rga_api version 1.10.1_[10] RGA_BLIT fail: Invalid argument rect[0, 0, 1280, 718, 1280, 720, 2560, 0] rect[0, 0, 1280, 718, 1280, 718, 2816, 0] Segmentation fault这不是普通的 pipeline 协商失败。RGA 在失败路径中破坏了内存除了播放器段错误外 还可能导致控制台、SSH 或其他板端命令异常只能重启板子恢复。三、触发链路1.未开启网页流时解码后的 NV12 主要送入 kmssink素材可以正常显示。2.streamControl start 启动共享 H.264/Opus 编码 pipeline。3.ChannelPlayer::ReloadPlaylist() 中断旧 pipeline并按当前播放位置重新开始。4.新 pipeline 增加网页流分支需要将 NV12 转换成 I420 后送入 intervideosink。5.Rockchip 修改版 libgstvideo 尝试用 RGA 加速该转换。6.源画面可见高度为 718但底层硬件缓冲按 720 行对齐。7.RGA 1.10.1 对这组参数返回 Invalid argument随后发生内存破坏和段错误。四. 排查过程4.1 从崩溃日志锁定 RGA 和特殊高度首先从日志提取错误、pipeline 和尺寸信息rg -n RGA|Segmentation|ERROR|Failed|streamControl|WebRTC|Video sink player.log关键证据不是单独的 Segmentation fault而是它前面的两组矩形参数源1280x718stride 1280x720格式 2560NV12 目标1280x718stride 1280x718格式 2816I4204.2 第一阶段判断怀疑 MPP 插件内部 RGA仓库中的 Rockchip MPP 插件源码存在 RGA 转换函数rg -n gst_mpp_use_rga|gst_mpp_dec_rga_convert|gst_mpp_enc_convert|RgaBlit \ third_party/sources/gstreamer1-rockchip-master对应源码包括gst/rockchipmpp/gstmpp.cgst/rockchipmpp/gstmppdec.cgst/rockchipmpp/gstmppenc.c因此第一阶段采取了以下措施在解码器和 tee 之间固定 NV12 caps。增加 identity drop-allocationtrue阻止下游分支的 allocation query 影响解码器。设置 GST_MPP_NO_RGA1。使用 -Drgadisabled 重新交叉编译 libgstrockchipmpp.so。4.3 核对板端实际加载的插件为了排除“改了源码但板子仍加载旧插件”使用启动脚本运行 gst-inspect/root/Test/gst-test/use-gst-test.sh gst-inspect-1.0 mppvideodec /root/Test/gst-test/use-gst-test.sh gst-inspect-1.0 mpph264enc确认实际路径为/root/Test/gst-test/lib/gstreamer-1.0/libgstrockchipmpp.so随后通过 SHA-256、ELF 依赖和字符串确认sha256sum /root/Test/gst-test/lib/gstreamer-1.0/libgstrockchipmpp.so readelf -d libgstrockchipmpp.so strings libgstrockchipmpp.so | grep RGA disabled结果表明新 MPP 插件已部署插件自身不再直接依赖 RGA并包含RGA disabled at compile time4.4 关键转折禁用 MPP RGA 后仍出现完全相同的 RgaBlit重新测试后日志仍在 videoconvert ! I420 处出现相同 RGA 错误。这证明MPP 插件确实包含一条 RGA 路径但它不是本次最终仍在执行的 RGA 调用者。 仅设置 GST_MPP_NO_RGA 无法关闭 GStreamer 视频转换库里的另一条 RGA 路径。4.5 扫描全部插件的动态符号和依赖使用交叉工具链扫描目标运行时中的插件for f in third_party/rk3588-sdk/target/usr/lib/gstreamer-1.0/*.so; do aarch64-none-linux-gnu-nm -D $f | rg RgaBlit|c_RkRgaBlit done同时检查动态依赖aarch64-none-linux-gnu-readelf -d libgstvideoconvertscale.so aarch64-none-linux-gnu-readelf -d libgstvideo-1.0.so.0.2209.0发现 videoconvert 元素本身位于 libgstvideoconvertscale.so它通过 libgstvideo-1.0.so 完成真正的像素转换后者直接依赖 librga.so.2并含有 c_RkRgaBlit 未定义符号。4.6 从二进制证据回到源码继续在 GStreamer Base 源码中搜索rg -n RgaBlit|GST_VIDEO_CONVERT_USE_RGA \ third_party/sources/gst1-plugins-base-1.22.9最终定位到third_party/sources/gst1-plugins-base-1.22.9/ gst-libs/gst/video/video-converter.c关键逻辑为buf g_getenv (GST_VIDEO_CONVERT_USE_RGA); if (!buf || strcmp (buf, 1)) return FALSE; ... if (c_RkRgaBlit (src_info, dst_info, NULL) 0) return FALSE;这段源码说明只要 GST_VIDEO_CONVERT_USE_RGA 的值精确等于 1 videoconvert/videoscale 就会优先走 Rockchip RGA否则回退到标准 GStreamer CPU 转换。五. 根本原因根本原因由四个条件共同构成条件作用特殊视频高度素材可见高度为 718硬件解码缓冲按 720 行对齐。网页流分支开启网页流后需要执行 NV12 到 I420 的格式转换。Rockchip GStreamer 修改libgstvideo增加了 RGA 加速路径。RGA 1.10.1 缺陷无法安全处理该可见高度与 stride 组合失败后产生内存破坏。streamControl start | v 重建带 WebRTC tee 的 HDMI pipeline | v videoconvert: NV12 1280x718 (stride 720) -- I420 1280x718 | v libgstvideo 检测到 GST_VIDEO_CONVERT_USE_RGA1 | v c_RkRgaBlit() -- Invalid argument -- 内存破坏 | v Segmentation fault严重时板端 SSH/控制台卡死