c3e95b190711416dc7b4849948b3be098c96f219
[platform/upstream/gstreamer.git] / tests / check / gst / rtspclientsink.c
1 /* GStreamer unit test for rtspclientsink
2  * Copyright (C) 2012 Axis Communications <dev-gstreamer at axis dot com>
3  *   @author David Svensson Fors <davidsf at axis dot com>
4  * Copyright (C) 2015 Centricular Ltd
5  *   @author Tim-Philipp Müller <tim@centricular.com>
6  *   @author Jan Schmidt <jan@centricular.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
24 #include <gst/check/gstcheck.h>
25 #include <gst/sdp/gstsdpmessage.h>
26 #include <gst/rtp/gstrtpbuffer.h>
27 #include <gst/rtp/gstrtcpbuffer.h>
28
29 #include <stdio.h>
30 #include <netinet/in.h>
31
32 #include "rtsp-server.h"
33
34 #define TEST_MOUNT_POINT  "/test"
35
36 /* tested rtsp server */
37 static GstRTSPServer *server = NULL;
38
39 /* tcp port that the test server listens for rtsp requests on */
40 static gint test_port = 0;
41 static gint server_send_rtcp_port;
42
43 /* id of the server's source within the GMainContext */
44 static guint source_id;
45
46 /* iterate the default main context until there are no events to dispatch */
47 static void
48 iterate (void)
49 {
50   while (g_main_context_iteration (NULL, FALSE)) {
51     GST_DEBUG ("iteration");
52   }
53 }
54
55 /* start the testing rtsp server for RECORD mode */
56 static GstRTSPMediaFactory *
57 start_record_server (const gchar * launch_line)
58 {
59   GstRTSPMediaFactory *factory;
60   GstRTSPMountPoints *mounts;
61   gchar *service;
62
63   mounts = gst_rtsp_server_get_mount_points (server);
64
65   factory = gst_rtsp_media_factory_new ();
66
67   gst_rtsp_media_factory_set_transport_mode (factory,
68       GST_RTSP_TRANSPORT_MODE_RECORD);
69   gst_rtsp_media_factory_set_launch (factory, launch_line);
70   gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, factory);
71   g_object_unref (mounts);
72
73   /* set port to any */
74   gst_rtsp_server_set_service (server, "0");
75
76   /* attach to default main context */
77   source_id = gst_rtsp_server_attach (server, NULL);
78   fail_if (source_id == 0);
79
80   /* get port */
81   service = gst_rtsp_server_get_service (server);
82   test_port = atoi (service);
83   fail_unless (test_port != 0);
84   g_free (service);
85
86   GST_DEBUG ("rtsp server listening on port %d", test_port);
87   return factory;
88 }
89
90 /* stop the tested rtsp server */
91 static void
92 stop_server (void)
93 {
94   g_source_remove (source_id);
95   source_id = 0;
96
97   GST_DEBUG ("rtsp server stopped");
98 }
99
100 /* fixture setup function */
101 static void
102 setup (void)
103 {
104   server = gst_rtsp_server_new ();
105 }
106
107 /* fixture clean-up function */
108 static void
109 teardown (void)
110 {
111   if (server) {
112     g_object_unref (server);
113     server = NULL;
114   }
115   test_port = 0;
116 }
117
118 /* create an rtsp connection to the server on test_port */
119 static gchar *
120 get_server_uri (gint port, const gchar * mount_point)
121 {
122   gchar *address;
123   gchar *uri_string;
124   GstRTSPUrl *url = NULL;
125
126   address = gst_rtsp_server_get_address (server);
127   uri_string = g_strdup_printf ("rtsp://%s:%d%s", address, port, mount_point);
128   g_free (address);
129
130   fail_unless (gst_rtsp_url_parse (uri_string, &url) == GST_RTSP_OK);
131   gst_rtsp_url_free (url);
132
133   return uri_string;
134 }
135
136 static GstRTSPFilterResult
137 check_transport (GstRTSPStream * stream, GstRTSPStreamTransport * strans,
138     gpointer user_data)
139 {
140   const GstRTSPTransport *trans =
141       gst_rtsp_stream_transport_get_transport (strans);
142
143   server_send_rtcp_port = trans->client_port.max;
144
145   return GST_RTSP_FILTER_KEEP;
146 }
147
148 static void
149 new_state_cb (GstRTSPMedia * media, gint state, gpointer user_data)
150 {
151   if (state == GST_STATE_PLAYING) {
152     GstRTSPStream *stream = gst_rtsp_media_get_stream (media, 0);
153
154     gst_rtsp_stream_transport_filter (stream,
155         (GstRTSPStreamTransportFilterFunc) check_transport, user_data);
156   }
157 }
158
159 static void
160 media_constructed_cb (GstRTSPMediaFactory * mfactory, GstRTSPMedia * media,
161     gpointer user_data)
162 {
163   GstElement **p_sink = user_data;
164   GstElement *bin;
165
166   g_signal_connect (media, "new-state", G_CALLBACK (new_state_cb), user_data);
167
168   bin = gst_rtsp_media_get_element (media);
169   *p_sink = gst_bin_get_by_name (GST_BIN (bin), "sink");
170   GST_INFO ("media constructed!: %" GST_PTR_FORMAT, *p_sink);
171   gst_object_unref (bin);
172 }
173
174 #define AUDIO_PIPELINE "audiotestsrc num-buffers=%d ! " \
175   "audio/x-raw,rate=8000 ! alawenc ! rtspclientsink name=sink location=%s"
176 #define RECORD_N_BUFS 10
177
178 GST_START_TEST (test_record)
179 {
180   GstRTSPMediaFactory *mfactory;
181   GstElement *server_sink = NULL;
182   gint i;
183
184   mfactory =
185       start_record_server ("( rtppcmadepay name=depay0 ! appsink name=sink )");
186
187   g_signal_connect (mfactory, "media-constructed",
188       G_CALLBACK (media_constructed_cb), &server_sink);
189
190   /* Create an rtspclientsink and send some data */
191   {
192     gchar *uri = get_server_uri (test_port, TEST_MOUNT_POINT);
193     gchar *pipe_str;
194     GstMessage *msg;
195     GstElement *pipeline;
196     GstBus *bus;
197
198     pipe_str = g_strdup_printf (AUDIO_PIPELINE, RECORD_N_BUFS, uri);
199     g_free (uri);
200
201     pipeline = gst_parse_launch (pipe_str, NULL);
202     g_free (pipe_str);
203
204     fail_unless (pipeline != NULL);
205
206     bus = gst_element_get_bus (pipeline);
207     fail_if (bus == NULL);
208
209     gst_element_set_state (pipeline, GST_STATE_PLAYING);
210
211     msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
212     fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS);
213     gst_message_unref (msg);
214
215     gst_element_set_state (pipeline, GST_STATE_NULL);
216     gst_object_unref (pipeline);
217   }
218
219   iterate ();
220
221   fail_unless (server_send_rtcp_port != 0);
222
223   /* check received data (we assume every buffer created by audiotestsrc and
224    * subsequently encoded by mulawenc results in exactly one RTP packet) */
225   for (i = 0; i < RECORD_N_BUFS; ++i) {
226     GstSample *sample = NULL;
227
228     g_signal_emit_by_name (G_OBJECT (server_sink), "pull-sample", &sample);
229     GST_INFO ("%2d recv sample: %p", i, sample);
230     if (sample)
231       gst_sample_unref (sample);
232   }
233
234   /* clean up and iterate so the clean-up can finish */
235   stop_server ();
236   iterate ();
237 }
238
239 GST_END_TEST;
240
241 /* Make sure we can shut down rtspclientsink while it's still waiting for
242  * the initial preroll data */
243 GST_START_TEST (test_record_no_data)
244 {
245
246   start_record_server ("( rtppcmadepay name=depay0 ! fakesink )");
247
248   /* Create an rtspclientsink and send some data */
249   {
250     gchar *uri = get_server_uri (test_port, TEST_MOUNT_POINT);
251     gchar *pipe_str;
252     GstMessage *msg;
253     GstElement *pipeline;
254     GstBus *bus;
255
256     pipe_str = g_strdup_printf ("appsrc caps=audio/x-alaw,rate=8000,channels=1"
257         " ! rtspclientsink name=sink location=%s", uri);
258     g_free (uri);
259
260     pipeline = gst_parse_launch (pipe_str, NULL);
261     g_free (pipe_str);
262
263     fail_unless (pipeline != NULL);
264
265     bus = gst_element_get_bus (pipeline);
266     fail_if (bus == NULL);
267
268     gst_element_set_state (pipeline, GST_STATE_PLAYING);
269
270     /* wait for a bit */
271     msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR,
272         500 * GST_MSECOND);
273     fail_unless (msg == NULL);
274
275     gst_element_set_state (pipeline, GST_STATE_NULL);
276     gst_object_unref (pipeline);
277     gst_object_unref (bus);
278   }
279
280   /* clean up and iterate so the clean-up can finish */
281   stop_server ();
282   iterate ();
283 }
284
285 GST_END_TEST;
286
287 static Suite *
288 rtspclientsink_suite (void)
289 {
290   Suite *s = suite_create ("rtspclientsink");
291   TCase *tc = tcase_create ("general");
292
293   suite_add_tcase (s, tc);
294   tcase_add_checked_fixture (tc, setup, teardown);
295   tcase_set_timeout (tc, 120);
296   tcase_add_test (tc, test_record);
297   tcase_add_test (tc, test_record_no_data);
298   return s;
299 }
300
301 GST_CHECK_MAIN (rtspclientsink);