rtpfunnel: Ensure segment events are forwarded after flushs

gst_rtp_funnel_forward_segment() returns early when the current_pad is set.
Without clearing current_pad a critical warning would be emitted when
attempting to chain a buffer following a flush.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7830>
This commit is contained in:
Philippe Normand 2024-11-05 11:49:32 +00:00 committed by GStreamer Marge Bot
parent 5a3dd943fe
commit 1e2d488e97
2 changed files with 52 additions and 0 deletions

View file

@ -443,6 +443,13 @@ gst_rtp_funnel_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
forward = FALSE; forward = FALSE;
break; break;
} }
case GST_EVENT_FLUSH_START:
/* By resetting current_pad here the segment will be forwarded next time a
buffer is received. */
GST_OBJECT_LOCK (funnel);
funnel->current_pad = NULL;
GST_OBJECT_UNLOCK (funnel);
break;
default: default:
break; break;
} }
@ -649,6 +656,7 @@ gst_rtp_funnel_change_state (GstElement * element, GstStateChange transition)
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
funnel->send_sticky_events = TRUE; funnel->send_sticky_events = TRUE;
funnel->current_pad = NULL;
break; break;
default: default:
break; break;
@ -673,6 +681,9 @@ gst_rtp_funnel_release_pad (GstElement * element, GstPad * pad)
GST_DEBUG_OBJECT (funnel, "releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); GST_DEBUG_OBJECT (funnel, "releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
if (pad == funnel->current_pad)
funnel->current_pad = NULL;
g_hash_table_foreach_remove (funnel->ssrc_to_pad, _remove_pad_func, pad); g_hash_table_foreach_remove (funnel->ssrc_to_pad, _remove_pad_func, pad);
gst_pad_set_active (pad, FALSE); gst_pad_set_active (pad, FALSE);

View file

@ -501,6 +501,45 @@ GST_START_TEST (rtpfunnel_twcc_passthrough_then_mux)
GST_END_TEST; GST_END_TEST;
GST_START_TEST (rtpfunnel_flush)
{
GstHarness *h = gst_harness_new_with_padnames ("rtpfunnel", NULL, "src");
GstHarness *h0 = gst_harness_new_with_element (h->element, "sink_0", NULL);
GstEvent *event;
GstBuffer *buffer;
gst_harness_set_src_caps_str (h0, "application/x-rtp, ssrc=(uint)123");
/* Push a buffer */
fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h0,
generate_test_buffer (0, 123, 0)));
buffer = gst_harness_try_pull (h);
gst_buffer_unref (buffer);
/* Flush */
fail_unless (gst_harness_push_event (h0, gst_event_new_flush_start ()));
fail_unless (gst_harness_push_event (h0, gst_event_new_flush_stop (TRUE)));
while ((event = gst_harness_try_pull_event (h)))
gst_event_unref (event);
/* Reset caps and segment */
gst_harness_set_src_caps_str (h0, "application/x-rtp, ssrc=(uint)123");
/* Push another buffer, this shouldn't generate "got data flow before segment event" criticals */
fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h0,
generate_test_buffer (1, 123, 0)));
buffer = gst_harness_try_pull (h);
gst_buffer_unref (buffer);
gst_harness_teardown (h0);
gst_harness_teardown (h);
}
GST_END_TEST;
static Suite * static Suite *
rtpfunnel_suite (void) rtpfunnel_suite (void)
{ {
@ -521,6 +560,8 @@ rtpfunnel_suite (void)
tcase_add_test (tc_chain, rtpfunnel_twcc_mux); tcase_add_test (tc_chain, rtpfunnel_twcc_mux);
tcase_add_test (tc_chain, rtpfunnel_twcc_passthrough_then_mux); tcase_add_test (tc_chain, rtpfunnel_twcc_passthrough_then_mux);
tcase_add_test (tc_chain, rtpfunnel_flush);
return s; return s;
} }