Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / tests / test-gstreamer.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2015 Kurento.
5  *  Contact: Jose Antonio Santos Cadenas
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is the Nice GLib ICE library.
18  *
19  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20  * Corporation. All Rights Reserved.
21  *
22  * Contributors:
23  *   Jose Antonio Santos Cadenas, Kurento.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
27  * case the provisions of LGPL are applicable instead of those above. If you
28  * wish to allow use of your version of this file only under the terms of the
29  * LGPL and not to allow others to use your version of this file under the
30  * MPL, indicate your decision by deleting the provisions above and replace
31  * them with the notice and other provisions required by the LGPL. If you do
32  * not delete the provisions above, a recipient may use your version of this
33  * file under either the MPL or the LGPL.
34  */
35
36 #include <gst/check/gstcheck.h>
37 #include "agent.h"
38
39 #define RTP_HEADER_SIZE 12
40 #define RTP_PAYLOAD_SIZE 1024
41
42 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
43     GST_PAD_SRC,
44     GST_PAD_ALWAYS,
45     GST_STATIC_CAPS_ANY);
46
47 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
48     GST_PAD_SINK,
49     GST_PAD_ALWAYS,
50     GST_STATIC_CAPS_ANY);
51
52 GMainLoop *loop;
53 static gint ready = 0;
54
55
56 static GCond cond;
57 static guint bytes_received;
58 static guint data_size;
59
60
61 static gboolean
62 count_bytes (GstBuffer ** buffer, guint idx, gpointer data)
63 {
64   gsize size = gst_buffer_get_size (*buffer);
65
66   g_debug ("received %" G_GSIZE_FORMAT " bytes", size);
67   g_mutex_lock(&mutex);
68   bytes_received += size;
69   g_cond_signal (&cond);
70   g_mutex_unlock (&mutex);
71
72   return TRUE;
73 }
74
75 static GstFlowReturn
76 sink_chain_list_function (GstPad * pad, GstObject * parent,
77     GstBufferList * list)
78 {
79   gst_buffer_list_foreach (list, count_bytes, NULL);
80
81   gst_buffer_list_unref (list);
82
83   return GST_FLOW_OK;
84 }
85
86 static GstFlowReturn
87 sink_chain_function (GstPad * pad, GstObject * parent, GstBuffer * buffer)
88 {
89   gsize size = gst_buffer_get_size (buffer);
90
91   g_debug ("received %" G_GSIZE_FORMAT " bytes", size);
92   g_mutex_lock(&mutex);
93   bytes_received += size;
94   g_cond_signal (&cond);
95   g_mutex_unlock (&mutex);
96
97   gst_buffer_unref (buffer);
98
99   return GST_FLOW_OK;
100 }
101
102 /*
103  * This function is get from gst-plugins-good tests tests/check/elements/udpsink.c
104  */
105 static GstBufferList *
106 create_buffer_list (void)
107 {
108   GstBufferList *list;
109   GstBuffer *rtp_buffer;
110   GstBuffer *data_buffer;
111
112   list = gst_buffer_list_new ();
113
114   /*** First group, i.e. first packet. **/
115
116   /* Create the RTP header buffer */
117   rtp_buffer = gst_buffer_new_allocate (NULL, RTP_HEADER_SIZE, NULL);
118   gst_buffer_memset (rtp_buffer, 0, 0, RTP_HEADER_SIZE);
119
120   /* Create the buffer that holds the payload */
121   data_buffer = gst_buffer_new_allocate (NULL, RTP_PAYLOAD_SIZE, NULL);
122   gst_buffer_memset (data_buffer, 0, 0, RTP_PAYLOAD_SIZE);
123
124   /* Create a new group to hold the rtp header and the payload */
125   gst_buffer_list_add (list, gst_buffer_append (rtp_buffer, data_buffer));
126
127   /***  Second group, i.e. second packet. ***/
128
129   /* Create the RTP header buffer */
130   rtp_buffer = gst_buffer_new_allocate (NULL, RTP_HEADER_SIZE, NULL);
131   gst_buffer_memset (rtp_buffer, 0, 0, RTP_HEADER_SIZE);
132
133   /* Create the buffer that holds the payload */
134   data_buffer = gst_buffer_new_allocate (NULL, RTP_PAYLOAD_SIZE, NULL);
135   gst_buffer_memset (data_buffer, 0, 0, RTP_PAYLOAD_SIZE);
136
137   /* Create a new group to hold the rtp header and the payload */
138   gst_buffer_list_add (list, gst_buffer_append (rtp_buffer, data_buffer));
139
140   /* Calculate the size of the data */
141   data_size = 2 * RTP_HEADER_SIZE + 2 * RTP_PAYLOAD_SIZE;
142
143   return list;
144 }
145
146 static void
147 recv_cb (NiceAgent * agent,
148     guint stream_id, guint component_id, guint len, gchar * buf, gpointer data)
149 {
150   g_debug ("Received data on agent %p, stream: %d, compoment: %d", agent,
151       stream_id, component_id);
152 }
153
154 static void
155 print_candidate (gpointer data, gpointer user_data)
156 {
157   NiceCandidate *cand = data;
158   gchar str_addr[INET6_ADDRSTRLEN];
159
160   nice_address_to_string (&cand->addr, str_addr);
161   g_debug ("Candidate: %s:%d", str_addr, nice_address_get_port (&cand->addr));
162 }
163
164 static void
165 cb_candidate_gathering_done (NiceAgent * agent, guint stream_id, gpointer data)
166 {
167   GSList *candidates;
168
169   g_debug ("Candidates gathered on agent %p, stream: %d",
170       agent, stream_id);
171
172   candidates = nice_agent_get_local_candidates (agent, stream_id, 1);
173
174   nice_agent_set_remote_candidates (NICE_AGENT (data), stream_id, 1,
175       candidates);
176
177   g_debug ("Got %d candidates", g_slist_length (candidates));
178   g_slist_foreach (candidates, print_candidate, NULL);
179
180   g_slist_free_full (candidates, (GDestroyNotify) nice_candidate_free);
181 }
182
183 static void
184 credentials_negotiation (NiceAgent * a_agent, NiceAgent * b_agent,
185     guint a_stream, guint b_stream)
186 {
187   gchar *user = NULL;
188   gchar *passwd = NULL;
189
190   nice_agent_get_local_credentials (a_agent, a_stream, &user, &passwd);
191   nice_agent_set_remote_credentials (b_agent, b_stream, user, passwd);
192   g_debug ("Agent: %p User: %s", a_agent, user);
193   g_debug ("Agent: %p Passwd: %s", a_agent, passwd);
194
195   g_free (user);
196   g_free (passwd);
197 }
198
199 static void
200 cb_component_state_changed (NiceAgent * agent, guint stream_id,
201     guint component_id, guint state, gpointer user_data)
202 {
203   g_debug ("State changed: %p to %s", agent,
204       nice_component_state_to_string (state));
205
206   if (state == NICE_COMPONENT_STATE_READY) {
207     ready++;
208     if (ready >= 2) {
209       g_main_loop_quit (loop);
210     }
211   }
212 }
213
214 GST_START_TEST (buffer_list_test)
215 {
216   GstSegment segment;
217   GstElement *nicesink, *nicesrc;
218   GstPad *srcpad, *sinkpad;
219   GstBufferList *list;
220   NiceAgent *sink_agent, *src_agent;
221   guint sink_stream, src_stream;
222   NiceAddress *addr;
223
224   loop = g_main_loop_new (NULL, TRUE);
225
226   /* Initialize nice agents */
227   addr = nice_address_new ();
228   nice_address_set_from_string (addr, "127.0.0.1");
229
230   sink_agent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
231   src_agent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
232
233   g_object_set (G_OBJECT (sink_agent), "upnp", FALSE, NULL);
234   g_object_set (G_OBJECT (src_agent), "upnp", FALSE, NULL);
235
236   nice_agent_add_local_address (sink_agent, addr);
237   nice_agent_add_local_address (src_agent, addr);
238
239   sink_stream = nice_agent_add_stream (sink_agent, 1);
240   src_stream = nice_agent_add_stream (src_agent, 1);
241
242   nice_agent_attach_recv (sink_agent, sink_stream, NICE_COMPONENT_TYPE_RTP,
243       NULL, recv_cb, NULL);
244   nice_agent_attach_recv (src_agent, src_stream, NICE_COMPONENT_TYPE_RTP,
245       NULL, recv_cb, NULL);
246
247   g_signal_connect (G_OBJECT (sink_agent), "candidate-gathering-done",
248       G_CALLBACK (cb_candidate_gathering_done), src_agent);
249   g_signal_connect (G_OBJECT (src_agent), "candidate-gathering-done",
250       G_CALLBACK (cb_candidate_gathering_done), sink_agent);
251
252   g_signal_connect (G_OBJECT (sink_agent), "component-state-changed",
253       G_CALLBACK (cb_component_state_changed), NULL);
254   g_signal_connect (G_OBJECT (src_agent), "component-state-changed",
255       G_CALLBACK (cb_component_state_changed), NULL);
256
257   credentials_negotiation (sink_agent, src_agent, sink_stream, src_stream);
258   credentials_negotiation (src_agent, sink_agent, src_stream, src_stream);
259
260   nice_agent_gather_candidates (sink_agent, sink_stream);
261   nice_agent_gather_candidates (src_agent, src_stream);
262
263   /* Create gstreamer elements */
264   nicesink = gst_check_setup_element ("nicesink");
265   nicesrc = gst_check_setup_element ("nicesrc");
266
267   g_object_set (nicesink, "agent", sink_agent, "stream", sink_stream,
268       "component", 1, NULL);
269   g_object_set (nicesrc, "agent", src_agent, "stream", src_stream, "component",
270       1, NULL);
271
272   srcpad = gst_check_setup_src_pad_by_name (nicesink, &srctemplate, "sink");
273   sinkpad = gst_check_setup_sink_pad_by_name (nicesrc, &sinktemplate, "src");
274
275   gst_pad_set_chain_list_function_full (sinkpad, sink_chain_list_function, NULL,
276       NULL);
277   gst_pad_set_chain_function_full (sinkpad, sink_chain_function, NULL, NULL);
278
279   gst_element_set_state (nicesink, GST_STATE_PLAYING);
280   gst_pad_set_active (srcpad, TRUE);
281
282   gst_element_set_state (nicesrc, GST_STATE_PLAYING);
283   gst_pad_set_active (sinkpad, TRUE);
284
285   gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
286
287   gst_segment_init (&segment, GST_FORMAT_TIME);
288   gst_pad_push_event (srcpad, gst_event_new_segment (&segment));
289
290   list = create_buffer_list ();
291
292   g_debug ("Waiting for agents to be ready ready");
293
294   g_main_loop_run (loop);
295
296   fail_unless_equals_int (gst_pad_push_list (srcpad, list), GST_FLOW_OK);
297
298   g_debug ("Waiting for buffers");
299
300   g_mutex_lock (&mutex);
301   while (bytes_received < data_size) {
302     g_cond_wait (&cond, &mutex);
303   }
304   g_mutex_unlock (&mutex);
305
306   g_assert_cmpuint (bytes_received, ==, data_size);
307   g_debug ("We received expected data size");
308
309   fail_unless_equals_int (data_size, bytes_received);
310
311   gst_check_teardown_pad_by_name (nicesink, "sink");
312   gst_check_teardown_element (nicesink);
313
314   gst_check_teardown_pad_by_name (nicesrc, "src");
315   gst_check_teardown_element (nicesrc);
316
317   nice_address_free (addr);
318   g_main_loop_unref (loop);
319 }
320
321 GST_END_TEST;
322
323 static Suite *
324 udpsink_suite (void)
325 {
326   Suite *s = suite_create ("nice_gstreamer_test");
327   TCase *tc_chain = tcase_create ("nice");
328
329   suite_add_tcase (s, tc_chain);
330
331   tcase_add_test (tc_chain, buffer_list_test);
332
333   return s;
334 }
335
336 GST_CHECK_MAIN (udpsink)