rtpsession: Try media_ssrc if no src can be found for PLI sender_ssrc
authorHavard Graff <havard.graff@gmail.com>
Tue, 10 Apr 2018 16:05:47 +0000 (18:05 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Sun, 13 May 2018 19:41:39 +0000 (20:41 +0100)
Some RTP stacks out there does not set the sender_ssrc. In order to be
more robust, try to lookup the media_ssrc before dropping the PLI.

https://bugzilla.gnome.org/show_bug.cgi?id=795139

gst/rtpmanager/rtpsession.c
tests/check/Makefile.am
tests/check/elements/rtpsession.c

index e79dfb6..7b5aca0 100644 (file)
@@ -2612,8 +2612,12 @@ rtp_session_process_pli (RTPSession * sess, guint32 sender_ssrc,
     return;
 
   src = find_source (sess, sender_ssrc);
-  if (src == NULL)
-    return;
+  if (src == NULL) {
+    /* try to find a src with media_ssrc instead */
+    src = find_source (sess, media_ssrc);
+    if (src == NULL)
+      return;
+  }
 
   rtp_session_request_local_key_unit (sess, src, media_ssrc, FALSE,
       current_time);
index 905cd60..8339457 100644 (file)
@@ -603,7 +603,7 @@ elements_rtprtx_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
 elements_rtprtx_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-$(GST_API_VERSION) $(LDADD)
 
 elements_rtpsession_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
-elements_rtpsession_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_NET_LIBS) -lgstrtp-$(GST_API_VERSION) $(GIO_LIBS) $(LDADD)
+elements_rtpsession_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_NET_LIBS) -lgstrtp-$(GST_API_VERSION) -lgstvideo-$(GST_API_VERSION) $(GIO_LIBS) $(LDADD)
 
 elements_rtpcollision_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
 elements_rtpcollision_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_NET_LIBS) -lgstrtp-$(GST_API_VERSION) $(GIO_LIBS) $(LDADD)
index 82243bd..bc02fc2 100644 (file)
@@ -30,6 +30,7 @@
 #include <gst/rtp/gstrtpbuffer.h>
 #include <gst/rtp/gstrtcpbuffer.h>
 #include <gst/net/gstnetaddressmeta.h>
+#include <gst/video/video.h>
 
 #define TEST_BUF_CLOCK_RATE 8000
 #define TEST_BUF_PT 0
@@ -801,6 +802,93 @@ GST_START_TEST (test_ignore_suspicious_bye)
 
 GST_END_TEST;
 
+static GstBuffer *
+create_buffer (guint8 * data, gsize size)
+{
+  return gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
+      data, size, 0, size, NULL, NULL);
+}
+
+GST_START_TEST (test_receive_regular_pli)
+{
+  SessionHarness *h = session_harness_new ();
+  GstEvent *ev;
+
+  /* PLI packet */
+  guint8 rtcp_pkt[] = {
+    0x81,                       /* PLI */
+    0xce,                       /* Type 206 Application layer feedback */
+    0x00, 0x02,                 /* Length */
+    0x37, 0x56, 0x93, 0xed,     /* Sender SSRC */
+    0x37, 0x56, 0x93, 0xed      /* Media SSRC */
+  };
+
+  fail_unless_equals_int (GST_FLOW_OK,
+      session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
+
+  session_harness_recv_rtcp (h, create_buffer (rtcp_pkt, sizeof (rtcp_pkt)));
+  fail_unless_equals_int (3,
+      gst_harness_upstream_events_received (h->send_rtp_h));
+
+  /* Remove the first 2 reconfigure events */
+  fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
+  fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
+  gst_event_unref (ev);
+  fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
+  fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
+  gst_event_unref (ev);
+
+  /* Then pull and check the force key-unit event */
+  fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
+  fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
+  fail_unless (gst_video_event_is_force_key_unit (ev));
+  gst_event_unref (ev);
+
+  session_harness_free (h);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_receive_pli_no_sender_ssrc)
+{
+  SessionHarness *h = session_harness_new ();
+  GstEvent *ev;
+
+  /* PLI packet */
+  guint8 rtcp_pkt[] = {
+    0x81,                       /* PLI */
+    0xce,                       /* Type 206 Application layer feedback */
+    0x00, 0x02,                 /* Length */
+    0x00, 0x00, 0x00, 0x00,     /* Sender SSRC */
+    0x37, 0x56, 0x93, 0xed      /* Media SSRC */
+  };
+
+  fail_unless_equals_int (GST_FLOW_OK,
+      session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
+
+  session_harness_recv_rtcp (h, create_buffer (rtcp_pkt, sizeof (rtcp_pkt)));
+  fail_unless_equals_int (3,
+      gst_harness_upstream_events_received (h->send_rtp_h));
+
+  /* Remove the first 2 reconfigure events */
+  fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
+  fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
+  gst_event_unref (ev);
+  fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
+  fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
+  gst_event_unref (ev);
+
+  /* Then pull and check the force key-unit event */
+  fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
+  fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
+  fail_unless (gst_video_event_is_force_key_unit (ev));
+  gst_event_unref (ev);
+
+  session_harness_free (h);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_illegal_rtcp_fb_packet)
 {
   SessionHarness *h = session_harness_new ();
@@ -921,6 +1009,8 @@ rtpsession_suite (void)
   tcase_add_test (tc_chain, test_ignore_suspicious_bye);
   tcase_add_test (tc_chain, test_illegal_rtcp_fb_packet);
   tcase_add_test (tc_chain, test_feedback_rtcp_race);
+  tcase_add_test (tc_chain, test_receive_regular_pli);
+  tcase_add_test (tc_chain, test_receive_pli_no_sender_ssrc);
   return s;
 }