From 1e2d488e9716746ccb656d0ed48727487d3f315a Mon Sep 17 00:00:00 2001 From: Philippe Normand Date: Tue, 5 Nov 2024 11:49:32 +0000 Subject: [PATCH] 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: --- .../gst/rtpmanager/gstrtpfunnel.c | 11 +++++ .../tests/check/elements/rtpfunnel.c | 41 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpfunnel.c b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpfunnel.c index 0e33d05b24..ee819676ec 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpfunnel.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpfunnel.c @@ -443,6 +443,13 @@ gst_rtp_funnel_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) forward = FALSE; 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: break; } @@ -649,6 +656,7 @@ gst_rtp_funnel_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: funnel->send_sticky_events = TRUE; + funnel->current_pad = NULL; break; default: 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)); + if (pad == funnel->current_pad) + funnel->current_pad = NULL; + g_hash_table_foreach_remove (funnel->ssrc_to_pad, _remove_pad_func, pad); gst_pad_set_active (pad, FALSE); diff --git a/subprojects/gst-plugins-good/tests/check/elements/rtpfunnel.c b/subprojects/gst-plugins-good/tests/check/elements/rtpfunnel.c index 1bb6be2a3d..e755ea8500 100644 --- a/subprojects/gst-plugins-good/tests/check/elements/rtpfunnel.c +++ b/subprojects/gst-plugins-good/tests/check/elements/rtpfunnel.c @@ -501,6 +501,45 @@ GST_START_TEST (rtpfunnel_twcc_passthrough_then_mux) 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 * 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_passthrough_then_mux); + tcase_add_test (tc_chain, rtpfunnel_flush); + return s; }