1 /* GStreamer
2 *
3 * unit test for rtpfunnel
4 *
5 * Copyright (C) <2017> Pexip.
6 * Contact: Havard Graff <havard@pexip.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23 #include <gst/check/gstcheck.h>
24 #include <gst/check/gstharness.h>
25
GST_START_TEST(rtpfunnel_ssrc_demuxing)26 GST_START_TEST (rtpfunnel_ssrc_demuxing)
27 {
28 GstHarness *h = gst_harness_new_with_padnames ("rtpfunnel", NULL, "src");
29 GstHarness *h0 = gst_harness_new_with_element (h->element, "sink_0", NULL);
30 GstHarness *h1 = gst_harness_new_with_element (h->element, "sink_1", NULL);
31
32 gst_harness_set_src_caps_str (h0, "application/x-rtp, ssrc=(uint)123");
33 gst_harness_set_src_caps_str (h1, "application/x-rtp, ssrc=(uint)321");
34
35 /* unref latency events */
36 gst_event_unref (gst_harness_pull_upstream_event (h0));
37 gst_event_unref (gst_harness_pull_upstream_event (h1));
38 fail_unless_equals_int (1, gst_harness_upstream_events_received (h0));
39 fail_unless_equals_int (1, gst_harness_upstream_events_received (h1));
40
41 /* send to pad 0 */
42 gst_harness_push_upstream_event (h,
43 gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
44 gst_structure_new ("GstForceKeyUnit",
45 "ssrc", G_TYPE_UINT, 123, NULL)));
46 fail_unless_equals_int (2, gst_harness_upstream_events_received (h0));
47 fail_unless_equals_int (1, gst_harness_upstream_events_received (h1));
48
49 /* send to pad 1 */
50 gst_harness_push_upstream_event (h,
51 gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
52 gst_structure_new ("GstForceKeyUnit",
53 "ssrc", G_TYPE_UINT, 321, NULL)));
54 fail_unless_equals_int (2, gst_harness_upstream_events_received (h0));
55 fail_unless_equals_int (2, gst_harness_upstream_events_received (h1));
56
57 /* unknown ssrc, we drop it */
58 gst_harness_push_upstream_event (h,
59 gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
60 gst_structure_new ("GstForceKeyUnit",
61 "ssrc", G_TYPE_UINT, 666, NULL)));
62 fail_unless_equals_int (2, gst_harness_upstream_events_received (h0));
63 fail_unless_equals_int (2, gst_harness_upstream_events_received (h1));
64
65 /* no ssrc, we send to all */
66 gst_harness_push_upstream_event (h,
67 gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
68 gst_structure_new_empty ("GstForceKeyUnit")));
69 fail_unless_equals_int (3, gst_harness_upstream_events_received (h0));
70 fail_unless_equals_int (3, gst_harness_upstream_events_received (h1));
71
72 /* remove pad 0, and send an event referencing the now dead ssrc */
73 gst_harness_teardown (h0);
74 gst_harness_push_upstream_event (h,
75 gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
76 gst_structure_new ("GstForceKeyUnit",
77 "ssrc", G_TYPE_UINT, 123, NULL)));
78 fail_unless_equals_int (3, gst_harness_upstream_events_received (h1));
79
80 gst_harness_teardown (h);
81 gst_harness_teardown (h1);
82 }
83
84 GST_END_TEST
GST_START_TEST(rtpfunnel_ssrc_downstream_not_leaking_through)85 GST_START_TEST (rtpfunnel_ssrc_downstream_not_leaking_through)
86 {
87 GstHarness *h = gst_harness_new_with_padnames ("rtpfunnel",
88 "sink_0", "src");
89 GstCaps *caps;
90 const GstStructure *s;
91
92 gst_harness_set_sink_caps_str (h, "application/x-rtp, ssrc=(uint)123");
93
94 caps = gst_pad_peer_query_caps (h->srcpad, NULL);
95 s = gst_caps_get_structure (caps, 0);
96
97 fail_unless (!gst_structure_has_field (s, "ssrc"));
98
99 gst_caps_unref (caps);
100 gst_harness_teardown (h);
101 }
102
103 GST_END_TEST
GST_START_TEST(rtpfunnel_common_ts_offset)104 GST_START_TEST (rtpfunnel_common_ts_offset)
105 {
106 GstHarness *h = gst_harness_new_with_padnames ("rtpfunnel",
107 "sink_0", "src");
108 GstCaps *caps;
109 const GstStructure *s;
110 const guint expected_ts_offset = 12345;
111 guint ts_offset;
112
113 g_object_set (h->element, "common-ts-offset", expected_ts_offset, NULL);
114
115 caps = gst_pad_peer_query_caps (h->srcpad, NULL);
116 s = gst_caps_get_structure (caps, 0);
117
118 fail_unless (gst_structure_get_uint (s, "timestamp-offset", &ts_offset));
119 fail_unless_equals_int (expected_ts_offset, ts_offset);
120
121 gst_caps_unref (caps);
122 gst_harness_teardown (h);
123 }
124
125 GST_END_TEST
GST_START_TEST(rtpfunnel_stress)126 GST_START_TEST (rtpfunnel_stress)
127 {
128 GstHarness *h = gst_harness_new_with_padnames ("rtpfunnel",
129 "sink_0", "src");
130 GstHarness *h1 = gst_harness_new_with_element (h->element, "sink_1", NULL);
131
132 GstPadTemplate *templ =
133 gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (h->element),
134 "sink_%u");
135 GstCaps *caps = gst_caps_from_string ("application/x-rtp, ssrc=(uint)123");
136 GstBuffer *buf = gst_buffer_new_allocate (NULL, 0, NULL);
137 GstSegment segment;
138 GstHarnessThread *statechange, *push, *req, *push1;
139
140 gst_check_add_log_filter ("GStreamer", G_LOG_LEVEL_WARNING,
141 g_regex_new ("Got data flow before (stream-start|segment) event",
142 (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL),
143 NULL, NULL, NULL);
144 gst_check_add_log_filter ("GStreamer", G_LOG_LEVEL_WARNING,
145 g_regex_new ("Sticky event misordering",
146 (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL),
147 NULL, NULL, NULL);
148
149
150 gst_segment_init (&segment, GST_FORMAT_TIME);
151
152 statechange = gst_harness_stress_statechange_start (h);
153 push = gst_harness_stress_push_buffer_start (h, caps, &segment, buf);
154 req = gst_harness_stress_requestpad_start (h, templ, NULL, NULL, TRUE);
155 push1 = gst_harness_stress_push_buffer_start (h1, caps, &segment, buf);
156
157 gst_caps_unref (caps);
158 gst_buffer_unref (buf);
159
160 /* test-length */
161 g_usleep (G_USEC_PER_SEC * 1);
162
163 gst_harness_stress_thread_stop (push1);
164 gst_harness_stress_thread_stop (req);
165 gst_harness_stress_thread_stop (push);
166 gst_harness_stress_thread_stop (statechange);
167
168 gst_harness_teardown (h1);
169 gst_harness_teardown (h);
170
171 gst_check_clear_log_filter ();
172 }
173
174 GST_END_TEST;
175
176 static Suite *
rtpfunnel_suite(void)177 rtpfunnel_suite (void)
178 {
179 Suite *s = suite_create ("rtpfunnel");
180 TCase *tc_chain = tcase_create ("general");
181
182 suite_add_tcase (s, tc_chain);
183
184 tcase_add_test (tc_chain, rtpfunnel_ssrc_demuxing);
185 tcase_add_test (tc_chain, rtpfunnel_ssrc_downstream_not_leaking_through);
186 tcase_add_test (tc_chain, rtpfunnel_common_ts_offset);
187
188 tcase_add_test (tc_chain, rtpfunnel_stress);
189
190 return s;
191 }
192
193 GST_CHECK_MAIN (rtpfunnel)
194