Gstreamer: RTSP pipeline is not being freed
Hi everyone!
Sorry for posting it here and not in r/gstreamer, I'm waiting to be accepted but this issue is making me crazy.
I'm working on a C++ program which uses gstreamer to get a video from mediamtx via rtsp and send it to other targets via rtp udp, If mediamtx stops the video stream, my program should be trying to read it until the stream is available again. Also, this programs is used for multiple video streams, so every pipeline is run on a separated thread.
When the mediamtx video source is not available, my program enters on a loop where it resets the pipeline every n seconds, so when the video is available again, my program read it again and send to the other targets.
The issue is that every time the video is avaiable again, the pipeline allocates memory (for x264enc I think) but it doesn't frees the memory used before, so after a while between some video restarts, the memory allocated grows a lot, the only way to free it is restarting my program.
I tried to use valgrind, LSAN, GST_TRACER and `gst_deinit()` at the end of my program to check for any memory leak, but there is nothing related to the pipeline, also when the thread that is running the stream is stopped, I'm sure that the pipeline is removed with this:
```cpp
struct GstDeleter
{
void operator()(GstElement *ptr) const
{
if (ptr) gst_object_unref(ptr);
}
};
```
I checked the refcount before the unref, and is 1, so its supposed that the pipeline and the other elements (source, encoders, etc.) will be deleted.
The restart section is the following:
```cpp
void RtspStream::RestartConnection()
{
...
std::cout << Format("Video stream lost for %ld seconds, waiting 3s to reconnect\n", seconds_elapsed);
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "Reconnecting..." << std::endl;
GstState state, pending;
gst_element_set_state(pipeline.get(), GST_STATE_NULL);
gst_element_get_state(pipeline.get(), &state, &pending, GST_CLOCK_TIME_NONE);
gst_element_set_state(pipeline.get(), GST_STATE_PLAYING);
gst_element_get_state(pipeline.get(), &state, &pending, GST_CLOCK_TIME_NONE);
}
```
The pipeline is the following:
```cpp
pipeline = std::unique_ptr<GstElement, GstDeleter>(gst_pipeline_new(pipelineName.c_str()));
const auto pipelineSource = gst_element_factory_make("rtspsrc", "source");
const auto decodebin = gst_element_factory_make("decodebin", "decoder");
const auto videoconvert = gst_element_factory_make("videoconvert", "videoconvert");
const auto x264enc = gst_element_factory_make("x264enc", "x264enc");
const auto h264parse = gst_element_factory_make("h264parse", "h264parse");
const auto rtph264pay = gst_element_factory_make("rtph264pay", "rtph264pay");
const auto tee = gst_element_factory_make("tee", "tee");
const auto fakeQueue = gst_element_factory_make("queue", "fake_queue");
const auto fakesink = gst_element_factory_make("fakesink", "fakesink");
if (!pipeline || !pipelineSource || !decodebin || !videoconvert || !x264enc || !h264parse || !rtph264pay || !tee || !fakeQueue || !fakesink)
{
std::cerr << "Failed to create elements" << std::endl;
return;
}
g_object_set(source, "onvif-rate-control", 0, "location", src.url.value().c_str(), "latency", 0u, nullptr);
gst_util_set_object_arg(G_OBJECT(source), "protocols", "tcp");
gst_util_set_object_arg(G_OBJECT(x264enc), "tune", "zerolatency");
gst_util_set_object_arg(G_OBJECT(x264enc), "speed-preset", "ultrafast");
g_object_set(x264enc, "key-int-max", 15u, nullptr);
g_object_set(rtph264pay, "config-interval", 1, "pt", 96, nullptr);
gst_bin_add_many(GST_BIN(pipeline.get()), pipelineSource, decodebin, videoconvert, x264enc, h264parse, rtph264pay, tee, fakeQueue, fakesink, nullptr);
// Dynamic pad linking for source -> decodebin
// ReSharper disable once CppParameterMayBeConst
g_signal_connect(pipelineSource, "pad-added", G_CALLBACK(+[]([[maybe_unused]] GstElement *src, GstPad *src_pad, gpointer data)
{
const auto decodebin_ref =
Post #24566
14