Gstreamer关闭重启RTSP流时内存无法释放的解决求助
问题
我正在开发支持36-64路流的视频墙,遇到了重启流时内存持续增长的问题。应用启动后初始占用内存54MB,启动流后增至约110MB;关闭流时内存未释放,再次启动同一路流后内存增至120MB,以此类推,文件描述符也存在类似问题(怀疑由BUS创建)。
目前我仅将pipeline设置为NULL未执行unref,但取消注释以下代码后,内存消耗仍无变化,尽管函数结束时每个元素及pipeline自身的引用计数均为0:
gst_bus_set_sync_handler(m_videoPipe->bus, nullptr, nullptr, nullptr); gst_object_unref(m_videoPipe->pipeline); gst_object_unref(m_videoPipe->bus);
解决方案建议
- 严格遵循GStreamer完整清理流程:
- 先将pipeline状态切换至
GST_STATE_NULL,必须同步等待状态变更完成,示例代码:gst_element_set_state(m_videoPipe->pipeline, GST_STATE_NULL); gst_element_get_state(m_videoPipe->pipeline, nullptr, nullptr, GST_CLOCK_TIME_NONE); - 遍历pipeline内所有子元素,逐个释放引用:
GstIterator *it = gst_bin_iterate_elements(GST_BIN(m_videoPipe->pipeline)); GstElement *elem; while (gst_iterator_next(it, (void**)&elem) == GST_ITERATOR_OK) { gst_object_unref(elem); } gst_iterator_free(it);
- 先将pipeline状态切换至
- 彻底清理Bus相关资源:
关闭流前先移除Bus的消息监听,清空未处理消息,再释放Bus:gst_bus_remove_watch(m_videoPipe->bus); // 清空Bus中剩余消息 GstMessage *msg; while ((msg = gst_bus_pop(m_videoPipe->bus)) != nullptr) { gst_message_unref(msg); } gst_bus_set_sync_handler(m_videoPipe->bus, nullptr, nullptr, nullptr); gst_object_unref(m_videoPipe->bus); - 排查潜在资源泄漏点:
- 检查代码中是否有未释放的
GstBuffer、GstCaps、GstPad等对象,这些小对象累积会导致内存增长; - 启用GStreamer内存调试:
export GST_DEBUG="GST_MEMORY:5",运行程序查看内存分配日志,定位未释放的内存块; - 使用
valgrind工具检测内存泄漏,配合GStreamer的--gst-disable-registry-fork选项避免干扰。
- 检查代码中是否有未释放的
- 解决文件描述符泄漏:
- 用
lsof -p <进程ID>查看打开的文件描述符,确认是否为RTSP连接的socket未关闭; - 确保
rtspsrc等源元素在状态切换到NULL时完成断开,必要时可以手动调用元素的reset接口(如果有的话)。
- 用
- 检查全局引用残留:
排查是否有全局变量、回调函数或其他长期存活的对象持有了pipeline或元素的引用,导致gst_object_unref()后引用计数未真正归0。
内容的提问来源于stack exchange,提问作者Deymoss
相关产品推荐
相关产品推荐

