rtpdtmfsrc: fix leak when shutting down mid-event

.. and update rtpdtmfdepay unit test to trigger
the potential leak more reliably (without the fix).

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3633

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7060>
This commit is contained in:
Tim-Philipp Müller 2024-06-19 01:55:57 +01:00 committed by GStreamer Marge Bot
parent c8dfb7c8f0
commit 62047a9f8d
2 changed files with 25 additions and 19 deletions

View file

@ -1084,6 +1084,9 @@ gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition)
}
dtmfsrc->last_event_was_start = FALSE;
// Clear out any unfinished events
g_clear_pointer (&dtmfsrc->payload, g_free);
/* Indicate that we don't do PRE_ROLL */
break;

View file

@ -562,31 +562,34 @@ GST_END_TEST;
GST_START_TEST (test_rtpdtmfdepay_src_caps_fixated)
{
GstElement *pipeline;
GstStructure *s;
// Loop a few times, additional test for rtpdtmfsrc leak on early shutdown
for (int i = 0; i < 50; ++i) {
GstElement *pipeline;
GstStructure *s;
pipeline =
gst_parse_launch ("rtpdtmfsrc ! rtpdtmfdepay ! audioconvert ! fakesink",
NULL);
pipeline =
gst_parse_launch ("rtpdtmfsrc ! rtpdtmfdepay ! audioconvert ! fakesink",
NULL);
fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
GST_STATE_CHANGE_ASYNC);
fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
GST_STATE_CHANGE_ASYNC);
// Send an event so there's some data flow and the pipeline prerolls
s = gst_structure_new ("dtmf-event",
"type", G_TYPE_INT, 1, "number", G_TYPE_INT, 3,
"method", G_TYPE_INT, 1, "volume", G_TYPE_INT, 8,
"start", G_TYPE_BOOLEAN, TRUE, NULL);
// Send an event so there's some data flow and the pipeline prerolls
s = gst_structure_new ("dtmf-event",
"type", G_TYPE_INT, 1, "number", G_TYPE_INT, 3,
"method", G_TYPE_INT, 1, "volume", G_TYPE_INT, 8,
"start", G_TYPE_BOOLEAN, TRUE, NULL);
fail_unless (gst_element_send_event (pipeline,
gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s)));
fail_unless (gst_element_send_event (pipeline,
gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s)));
// Wait for preroll
fail_unless_equals_int (gst_element_get_state (pipeline, NULL, NULL, -1),
GST_STATE_CHANGE_SUCCESS);
// Wait for preroll
fail_unless_equals_int (gst_element_get_state (pipeline, NULL, NULL, -1),
GST_STATE_CHANGE_SUCCESS);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
}
}
GST_END_TEST;