我一直在尝试制作一个通过 gstreamer 运行一些相机的程序。程序首先设置管道,然后根据用户输入在“播放”或“暂停”状态之间切换。 我注意到运行该程序一段时间后,该程序的内存使用量会随着时间的推移慢慢增加。在尝试了很多不同的事情之后,我能够用一个非常小的示例程序重现该问题:
#include <gst/gst.h>
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <iostream>
int main(int argc, char* argv[])
{
gst_init(&argc, &argv);
GError* err = NULL;
std::string pipeline_str = "fakesrc ! fakesink sync = false ";
GstElement* pipeline = gst_parse_launch(pipeline_str.c_str(), &err);
gst_element_set_state(pipeline, GST_STATE_READY);
gst_element_get_state(pipeline, NULL, NULL, 4000000000ll);
for (;;)
{
gst_element_set_state(pipeline, GST_STATE_PAUSED);
GstStateChangeReturn result = gst_element_get_state(pipeline, NULL, NULL, 4000000000ll);
if (result != GST_STATE_CHANGE_SUCCESS){
std::cout << "error" << std::endl;
break;
}
usleep(100);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
result = gst_element_get_state(pipeline, NULL, NULL, 4000000000ll);
if (result != GST_STATE_CHANGE_SUCCESS){
std::cout << "error" << std::endl;
break;
}
usleep(100);
}
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
}
运行此程序,我可以看到使用 htop 时内存使用量增加得相当快。所以在我看来问题是在状态切换时发生的?有人遇到过类似问题吗
状态更改是异步的。您生成的状态更改请求多于管道可以处理的数量,因此很可能您的消息队列是由这些请求建立的。
等待状态更改完成,然后再尝试再次更改。检查总线以了解从管道发出的状态更改。
编辑,示例:
#include <gst/gst.h>
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <iostream>
int main(int argc, char* argv[])
{
gst_init(&argc, &argv);
GError* err = NULL;
std::string pipeline_str = "videotestsrc ! fakesink sync=false";
GstElement* pipeline = gst_parse_launch(pipeline_str.c_str(), &err);
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_element_set_state(pipeline, GST_STATE_READY);
for (;;)
{
GstMessage* msg = gst_bus_timed_pop_filtered(bus, -1, GST_MESSAGE_STATE_CHANGED);
if (msg->src == GST_OBJECT(pipeline))
{
gst_message_unref(msg);
break;
}
gst_message_unref(msg);
}
for (;;)
{
gst_element_set_state(pipeline, GST_STATE_PAUSED);
for (;;)
{
GstMessage* msg = gst_bus_timed_pop_filtered(bus, -1, GST_MESSAGE_STATE_CHANGED);
if (msg->src == GST_OBJECT(pipeline))
{
gst_message_unref(msg);
break;
}
gst_message_unref(msg);
}
gst_element_set_state(pipeline, GST_STATE_PLAYING);
for (;;)
{
GstMessage* msg = gst_bus_timed_pop_filtered(bus, -1, GST_MESSAGE_STATE_CHANGED);
if (msg->src == GST_OBJECT(pipeline))
{
gst_message_unref(msg);
break;
}
gst_message_unref(msg);
}
}
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(bus);
gst_object_unref(pipeline);
return 0;
}