rtpfunnel: Ensure segment events are forwarded after flushs
authorPhilippe Normand <philn@igalia.com>
Tue, 5 Nov 2024 11:49:32 +0000 (11:49 +0000)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 5 Nov 2024 16:57:49 +0000 (16:57 +0000)
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/7835>

subprojects/gst-plugins-good/gst/rtpmanager/gstrtpfunnel.c
subprojects/gst-plugins-good/tests/check/elements/rtpfunnel.c

index d403015e143161e98c6e39a2268dece7cd137347..8de1ae8918c76dd90ad88595acd2ce534371f3bc 100644 (file)
@@ -440,6 +440,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;
   }
@@ -633,6 +640,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;
@@ -657,6 +665,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);
index 676127ca18d35b86e40e4de11ae46b42fb9d56b6..a7da56ad007dc0d893e8d1b70c71806ef58bf73d 100644 (file)
@@ -491,6 +491,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)
 {
@@ -511,6 +550,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;
 }