1 /* GStreamer UDP source unit tests
2  * Copyright (C) 2011 Tim-Philipp Müller <tim centricular net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #include <gst/check/gstcheck.h>
20 #include <gio/gio.h>
21 #include <stdlib.h>
22 
23 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
24     GST_PAD_SINK,
25     GST_PAD_ALWAYS,
26     GST_STATIC_CAPS_ANY);
27 
28 static gboolean
udpsrc_setup(GstElement ** udpsrc,GSocket ** socket,GstPad ** sinkpad,GSocketAddress ** sa)29 udpsrc_setup (GstElement ** udpsrc, GSocket ** socket,
30     GstPad ** sinkpad, GSocketAddress ** sa)
31 {
32   GInetAddress *ia;
33   int port = 0;
34   gchar *s;
35 
36   *udpsrc = gst_check_setup_element ("udpsrc");
37   fail_unless (*udpsrc != NULL);
38   g_object_set (*udpsrc, "port", 0, NULL);
39 
40   *sinkpad = gst_check_setup_sink_pad_by_name (*udpsrc, &sinktemplate, "src");
41   fail_unless (*sinkpad != NULL);
42   gst_pad_set_active (*sinkpad, TRUE);
43 
44   gst_element_set_state (*udpsrc, GST_STATE_PLAYING);
45   g_object_get (*udpsrc, "port", &port, NULL);
46   GST_INFO ("udpsrc port = %d", port);
47 
48   *socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
49       G_SOCKET_PROTOCOL_UDP, NULL);
50 
51   if (*socket == NULL) {
52     GST_WARNING ("Could not create IPv4 UDP socket for unit test");
53     return FALSE;
54   }
55 
56   ia = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
57   s = g_inet_address_to_string (ia);
58   GST_LOG ("inet address %s", s);
59   g_free (s);
60   *sa = g_inet_socket_address_new (ia, port);
61   g_object_unref (ia);
62 
63   return TRUE;
64 }
65 
GST_START_TEST(test_udpsrc_empty_packet)66 GST_START_TEST (test_udpsrc_empty_packet)
67 {
68   GSocketAddress *sa = NULL;
69   GstElement *udpsrc = NULL;
70   GSocket *socket = NULL;
71   GstPad *sinkpad = NULL;
72 
73   if (!udpsrc_setup (&udpsrc, &socket, &sinkpad, &sa))
74     goto no_socket;
75 
76   if (g_socket_send_to (socket, sa, "HeLL0", 0, NULL, NULL) == 0) {
77     GST_INFO ("sent 0 bytes");
78     if (g_socket_send_to (socket, sa, "HeLL0", 6, NULL, NULL) == 6) {
79       GstMapInfo map;
80       GstBuffer *buf;
81       guint len = 0;
82 
83       GST_INFO ("sent 6 bytes");
84 
85       g_mutex_lock (&check_mutex);
86       len = g_list_length (buffers);
87       while (len < 1) {
88         g_cond_wait (&check_cond, &check_mutex);
89         len = g_list_length (buffers);
90         GST_INFO ("%u buffers", len);
91       }
92 
93       /* wait a bit more for a second buffer */
94       if (len < 2) {
95         g_cond_wait_until (&check_cond, &check_mutex,
96             g_get_monotonic_time () + G_TIME_SPAN_SECOND / 100);
97 
98         len = g_list_length (buffers);
99         GST_INFO ("%u buffers", len);
100       }
101 
102       fail_unless (len == 1 || len == 2);
103 
104       /* last buffer should be our HeLL0 string */
105       buf = GST_BUFFER (g_list_nth_data (buffers, len - 1));
106       gst_buffer_map (buf, &map, GST_MAP_READ);
107       fail_unless_equals_int (map.size, 6);
108       fail_unless_equals_string ((gchar *) map.data, "HeLL0");
109       gst_buffer_unmap (buf, &map);
110 
111       /* if there's another buffer, it should be 0 bytes */
112       if (len == 2) {
113         buf = GST_BUFFER (g_list_nth_data (buffers, 0));
114         fail_unless_equals_int (gst_buffer_get_size (buf), 0);
115       }
116       g_mutex_unlock (&check_mutex);
117     } else {
118       GST_WARNING ("send_to(6 bytes) failed");
119     }
120   } else {
121     GST_WARNING ("send_to(0 bytes) failed");
122   }
123 
124 no_socket:
125 
126   gst_element_set_state (udpsrc, GST_STATE_NULL);
127 
128   gst_check_drop_buffers ();
129   gst_check_teardown_pad_by_name (udpsrc, "src");
130   gst_check_teardown_element (udpsrc);
131 
132   g_object_unref (socket);
133   g_object_unref (sa);
134 }
135 
136 GST_END_TEST;
137 
GST_START_TEST(test_udpsrc)138 GST_START_TEST (test_udpsrc)
139 {
140   GSocketAddress *sa = NULL;
141   GstElement *udpsrc = NULL;
142   GSocket *socket = NULL;
143   GstPad *sinkpad = NULL;
144   GstBuffer *buf;
145   GstMemory *mem;
146   gchar data[48000];
147   gsize max_size;
148   int i, len = 0;
149   gssize sent;
150   GError *err = NULL;
151 
152   for (i = 0; i < G_N_ELEMENTS (data); ++i)
153     data[i] = i & 0xff;
154 
155   if (!udpsrc_setup (&udpsrc, &socket, &sinkpad, &sa))
156     goto no_socket;
157 
158   if ((sent = g_socket_send_to (socket, sa, data, 48000, NULL, &err)) == -1)
159     goto send_failure;
160   fail_unless_equals_int (sent, 48000);
161 
162   if ((sent = g_socket_send_to (socket, sa, data, 21000, NULL, &err)) == -1)
163     goto send_failure;
164   fail_unless_equals_int (sent, 21000);
165 
166   if ((sent = g_socket_send_to (socket, sa, data, 500, NULL, &err)) == -1)
167     goto send_failure;
168   fail_unless_equals_int (sent, 500);
169 
170   if ((sent = g_socket_send_to (socket, sa, data, 1600, NULL, &err)) == -1)
171     goto send_failure;
172   fail_unless_equals_int (sent, 1600);
173 
174   if ((sent = g_socket_send_to (socket, sa, data, 1400, NULL, &err)) == -1)
175     goto send_failure;
176   fail_unless_equals_int (sent, 1400);
177 
178   GST_INFO ("sent some packets");
179 
180   g_mutex_lock (&check_mutex);
181   len = g_list_length (buffers);
182   while (len < 5) {
183     g_cond_wait (&check_cond, &check_mutex);
184     len = g_list_length (buffers);
185     GST_INFO ("%u buffers", len);
186   }
187 
188   /* check that large packets are made up of multiple memory chunks and that
189    * the first one is fairly small */
190   buf = GST_BUFFER (g_list_nth_data (buffers, 0));
191   fail_unless_equals_int (gst_buffer_get_size (buf), 48000);
192   fail_unless_equals_int (gst_buffer_n_memory (buf), 2);
193   mem = gst_buffer_peek_memory (buf, 0);
194   gst_memory_get_sizes (mem, NULL, &max_size);
195   fail_unless (max_size <= 2000);
196 
197   buf = GST_BUFFER (g_list_nth_data (buffers, 1));
198   fail_unless_equals_int (gst_buffer_get_size (buf), 21000);
199   fail_unless_equals_int (gst_buffer_n_memory (buf), 2);
200   mem = gst_buffer_peek_memory (buf, 0);
201   gst_memory_get_sizes (mem, NULL, &max_size);
202   fail_unless (max_size <= 2000);
203 
204   buf = GST_BUFFER (g_list_nth_data (buffers, 2));
205   fail_unless_equals_int (gst_buffer_get_size (buf), 500);
206   fail_unless_equals_int (gst_buffer_n_memory (buf), 1);
207   mem = gst_buffer_peek_memory (buf, 0);
208   gst_memory_get_sizes (mem, NULL, &max_size);
209   fail_unless (max_size <= 2000);
210 
211   buf = GST_BUFFER (g_list_nth_data (buffers, 3));
212   fail_unless_equals_int (gst_buffer_get_size (buf), 1600);
213   fail_unless_equals_int (gst_buffer_n_memory (buf), 2);
214   mem = gst_buffer_peek_memory (buf, 0);
215   gst_memory_get_sizes (mem, NULL, &max_size);
216   fail_unless (max_size <= 2000);
217 
218   buf = GST_BUFFER (g_list_nth_data (buffers, 4));
219   fail_unless_equals_int (gst_buffer_get_size (buf), 1400);
220   fail_unless_equals_int (gst_buffer_n_memory (buf), 1);
221   mem = gst_buffer_peek_memory (buf, 0);
222   gst_memory_get_sizes (mem, NULL, &max_size);
223   fail_unless (max_size <= 2000);
224 
225   g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
226   g_list_free (buffers);
227   buffers = NULL;
228 
229   g_mutex_unlock (&check_mutex);
230 
231 no_socket:
232 send_failure:
233   if (err) {
234     GST_WARNING ("Socket send error, skipping test: %s", err->message);
235     g_clear_error (&err);
236   }
237 
238   gst_element_set_state (udpsrc, GST_STATE_NULL);
239 
240   gst_check_drop_buffers ();
241   gst_check_teardown_pad_by_name (udpsrc, "src");
242   gst_check_teardown_element (udpsrc);
243 
244   g_object_unref (socket);
245   g_object_unref (sa);
246 }
247 
248 GST_END_TEST;
249 
250 static Suite *
udpsrc_suite(void)251 udpsrc_suite (void)
252 {
253   Suite *s = suite_create ("udpsrc");
254   TCase *tc_chain = tcase_create ("udpsrc");
255 
256   suite_add_tcase (s, tc_chain);
257   tcase_add_test (tc_chain, test_udpsrc_empty_packet);
258   tcase_add_test (tc_chain, test_udpsrc);
259   return s;
260 }
261 
262 GST_CHECK_MAIN (udpsrc)
263