GStreamer通过UDP传输带元数据的RTP图像相关问题咨询
问题解答
1. 收发两端探针获取到的缓冲区类型不一致的原因
你观察到的差异是GStreamer不同组件的默认行为导致的,原因如下:
- 发送端
rtpvrawpay的输出特性:你使用的640*480 BGR格式单帧数据大小为921600字节,远大于常规UDP MTU(1500字节),rtpvrawpay会将单帧拆分为多个符合MTU限制的RTP包。为了减少内核态调用次数、提升传输效率,rtpvrawpay默认会将属于同一帧的多个RTP包封装为GstBufferList(缓冲区列表)向下游推送,因此你在它的源侧探针拿到的是缓冲区列表类型。 - 接收端
udpsrc的输出特性:发送端的udpsink会自动拆分缓冲区列表,将列表内的每个缓冲区作为独立UDP报文发送。接收端udpsrc每收到一个UDP报文就会生成一个单独的GstBuffer向下游推送,因此你在rtpvrawdepay的接收侧探针拿到的是单个缓冲区类型。
如果需要接收端也获取缓冲区列表,可以给udpsrc设置buffer-list=TRUE属性,它会将一段时间内收到的报文合并为缓冲区列表推送,一般场景下无需开启。
你之前调用gst_rtp_buffer_map报错的大概率原因是没有先判断探针数据类型,直接将GstBufferList作为单个缓冲区传入接口,只要先判断类型、遍历缓冲区列表中的每个RTP包单独处理即可,示例逻辑如下:
if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER_LIST) { GstBufferList *buf_list = GST_PAD_PROBE_INFO_BUFFER_LIST(info); for (guint i = 0; i < gst_buffer_list_length(buf_list); i++) { GstBuffer *buf = gst_buffer_list_get(buf_list, i); // 此处执行你现有RTP扩展头添加的逻辑 } }
2. UDP传输图像附带元数据的方案说明
你当前使用RTP双字节扩展头挂载元数据的方案是符合RTP标准的官方推荐实现,兼容性和可靠性都较好,已经可以满足需求。如果需要优化可以参考以下方向:
- 减少带宽占用:如果你的元数据是和整帧绑定的,不需要每个RTP包都携带,只需要给
rtpvrawpay输出的缓冲区列表中第一个RTP包加扩展头即可,接收端通过RTP头的序列号和标记位(M位,rtpvrawpay会给每帧的最后一个RTP包设置M位)定位帧首包读取元数据即可。 - 大元数据场景优化:如果元数据体积较大(超过RTP扩展头最大限制)或者更新频率低于帧频,可以采用双端口传输方案:单独开一个UDP端口传输元数据,收发两端通过视频帧的时间戳对齐元数据和视频帧即可。
内容的提问来源于stack exchange,提问作者Michael Gopshtein
相关产品推荐
相关产品推荐

