3 * unit test for gstrtpbin
5 * Copyright (C) <2009> Wim Taymans <wim.taymans@gmail.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
23 #include <gst/check/gstcheck.h>
24 #include <gst/check/gsttestclock.h>
25 #include <gst/check/gstharness.h>
27 #include <gst/rtp/gstrtpbuffer.h>
28 #include <gst/rtp/gstrtcpbuffer.h>
30 GST_START_TEST (test_pads)
35 element = gst_element_factory_make ("rtpsession", NULL);
37 pad = gst_element_get_request_pad (element, "recv_rtcp_sink");
38 gst_object_unref (pad);
39 gst_object_unref (element);
44 GST_START_TEST (test_cleanup_send)
47 GstPad *rtp_sink, *rtp_src, *rtcp_src;
51 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
54 /* request session 0 */
55 rtp_sink = gst_element_get_request_pad (rtpbin, "send_rtp_sink_0");
56 fail_unless (rtp_sink != NULL);
57 ASSERT_OBJECT_REFCOUNT (rtp_sink, "rtp_sink", 2);
59 /* this static pad should be created automatically now */
60 rtp_src = gst_element_get_static_pad (rtpbin, "send_rtp_src_0");
61 fail_unless (rtp_src != NULL);
62 ASSERT_OBJECT_REFCOUNT (rtp_src, "rtp_src", 2);
64 /* we should be able to get an internal session 0 now */
65 g_signal_emit_by_name (rtpbin, "get-internal-session", 0, &session);
66 fail_unless (session != NULL);
67 g_object_unref (session);
69 /* get the send RTCP pad too */
70 rtcp_src = gst_element_get_request_pad (rtpbin, "send_rtcp_src_0");
71 fail_unless (rtcp_src != NULL);
72 ASSERT_OBJECT_REFCOUNT (rtcp_src, "rtcp_src", 2);
74 gst_element_release_request_pad (rtpbin, rtp_sink);
75 /* we should only have our refs to the pads now */
76 ASSERT_OBJECT_REFCOUNT (rtp_sink, "rtp_sink", 1);
77 ASSERT_OBJECT_REFCOUNT (rtp_src, "rtp_src", 1);
78 ASSERT_OBJECT_REFCOUNT (rtcp_src, "rtp_src", 2);
80 /* the other pad should be gone now */
81 fail_unless (gst_element_get_static_pad (rtpbin, "send_rtp_src_0") == NULL);
83 /* internal session should still be there */
84 g_signal_emit_by_name (rtpbin, "get-internal-session", 0, &session);
85 fail_unless (session != NULL);
86 g_object_unref (session);
88 /* release the RTCP pad */
89 gst_element_release_request_pad (rtpbin, rtcp_src);
90 /* we should only have our refs to the pads now */
91 ASSERT_OBJECT_REFCOUNT (rtp_sink, "rtp_sink", 1);
92 ASSERT_OBJECT_REFCOUNT (rtp_src, "rtp_src", 1);
93 ASSERT_OBJECT_REFCOUNT (rtcp_src, "rtp_src", 1);
95 /* the session should be gone now */
96 g_signal_emit_by_name (rtpbin, "get-internal-session", 0, &session);
97 fail_unless (session == NULL);
99 /* unref the request pad and the static pad */
100 gst_object_unref (rtp_sink);
101 gst_object_unref (rtp_src);
102 gst_object_unref (rtcp_src);
105 gst_object_unref (rtpbin);
123 init_data (CleanupData * data)
126 data->pad_added = FALSE;
127 g_mutex_init (&data->lock);
128 g_cond_init (&data->cond);
134 clean_data (CleanupData * data)
136 g_list_foreach (data->pads, (GFunc) gst_object_unref, NULL);
137 g_list_free (data->pads);
138 g_mutex_clear (&data->lock);
139 g_cond_clear (&data->cond);
141 gst_caps_unref (data->caps);
144 static guint8 rtp_packet[] = { 0x80, 0x60, 0x94, 0xbc, 0x8f, 0x37, 0x4e, 0xb8,
145 0x44, 0xa8, 0xf3, 0x7c, 0x06, 0x6a, 0x0c, 0xce,
146 0x13, 0x25, 0x19, 0x69, 0x1f, 0x93, 0x25, 0x9d,
147 0x2b, 0x82, 0x31, 0x3b, 0x36, 0xc1, 0x3c, 0x13
151 chain_rtp_packet (GstPad * pad, CleanupData * data)
158 if (data->caps == NULL) {
159 data->caps = gst_caps_from_string ("application/x-rtp,"
160 "media=(string)audio, clock-rate=(int)44100, "
161 "encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1");
165 gst_pad_send_event (pad, gst_event_new_stream_start (GST_OBJECT_NAME (pad)));
166 gst_pad_send_event (pad, gst_event_new_caps (data->caps));
167 gst_segment_init (&segment, GST_FORMAT_TIME);
168 gst_pad_send_event (pad, gst_event_new_segment (&segment));
170 buffer = gst_buffer_new_and_alloc (sizeof (rtp_packet));
171 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
172 memcpy (map.data, rtp_packet, sizeof (rtp_packet));
174 map.data[2] = (data->seqnum >> 8) & 0xff;
175 map.data[3] = data->seqnum & 0xff;
178 gst_buffer_unmap (buffer, &map);
180 GST_BUFFER_DTS (buffer) = 0;
182 res = gst_pad_chain (pad, buffer);
188 dummy_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
190 gst_buffer_unref (buffer);
195 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
198 GST_STATIC_CAPS ("application/x-rtp"));
202 make_sinkpad (CleanupData * data)
206 pad = gst_pad_new_from_static_template (&sink_factory, "sink");
208 gst_pad_set_chain_function (pad, dummy_chain);
209 gst_pad_set_active (pad, TRUE);
211 data->pads = g_list_prepend (data->pads, pad);
217 pad_added_cb (GstElement * rtpbin, GstPad * pad, CleanupData * data)
221 GST_DEBUG ("pad added %s:%s\n", GST_DEBUG_PAD_NAME (pad));
223 if (GST_PAD_IS_SINK (pad))
226 fail_unless (data->pad_added == FALSE);
228 sinkpad = make_sinkpad (data);
229 fail_unless (gst_pad_link (pad, sinkpad) == GST_PAD_LINK_OK);
231 g_mutex_lock (&data->lock);
232 data->pad_added = TRUE;
234 g_cond_signal (&data->cond);
235 g_mutex_unlock (&data->lock);
239 pad_removed_cb (GstElement * rtpbin, GstPad * pad, CleanupData * data)
241 GST_DEBUG ("pad removed %s:%s\n", GST_DEBUG_PAD_NAME (pad));
243 if (data->pad != pad)
246 fail_unless (data->pad_added == TRUE);
248 g_mutex_lock (&data->lock);
249 data->pad_added = FALSE;
250 g_cond_signal (&data->cond);
251 g_mutex_unlock (&data->lock);
254 GST_START_TEST (test_cleanup_recv)
259 GstStateChangeReturn ret;
265 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
267 g_signal_connect (rtpbin, "pad-added", (GCallback) pad_added_cb, &data);
268 g_signal_connect (rtpbin, "pad-removed", (GCallback) pad_removed_cb, &data);
270 ret = gst_element_set_state (rtpbin, GST_STATE_PLAYING);
271 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
274 /* request session 0 */
275 rtp_sink = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_0");
276 fail_unless (rtp_sink != NULL);
277 ASSERT_OBJECT_REFCOUNT (rtp_sink, "rtp_sink", 2);
279 /* no sourcepads are created yet */
280 fail_unless (rtpbin->numsinkpads == 1);
281 fail_unless (rtpbin->numsrcpads == 0);
283 res = chain_rtp_packet (rtp_sink, &data);
284 GST_DEBUG ("res %d, %s\n", res, gst_flow_get_name (res));
285 fail_unless (res == GST_FLOW_OK);
287 res = chain_rtp_packet (rtp_sink, &data);
288 GST_DEBUG ("res %d, %s\n", res, gst_flow_get_name (res));
289 fail_unless (res == GST_FLOW_OK);
291 /* we wait for the new pad to appear now */
292 g_mutex_lock (&data.lock);
293 while (!data.pad_added)
294 g_cond_wait (&data.cond, &data.lock);
295 g_mutex_unlock (&data.lock);
297 /* sourcepad created now */
298 fail_unless (rtpbin->numsinkpads == 1);
299 fail_unless (rtpbin->numsrcpads == 1);
301 /* remove the session */
302 gst_element_release_request_pad (rtpbin, rtp_sink);
303 gst_object_unref (rtp_sink);
305 /* pad should be gone now */
306 g_mutex_lock (&data.lock);
307 while (data.pad_added)
308 g_cond_wait (&data.cond, &data.lock);
309 g_mutex_unlock (&data.lock);
311 /* nothing left anymore now */
312 fail_unless (rtpbin->numsinkpads == 0);
313 fail_unless (rtpbin->numsrcpads == 0);
316 ret = gst_element_set_state (rtpbin, GST_STATE_NULL);
317 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
319 gst_object_unref (rtpbin);
326 GST_START_TEST (test_cleanup_recv2)
331 GstStateChangeReturn ret;
337 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
339 g_signal_connect (rtpbin, "pad-added", (GCallback) pad_added_cb, &data);
340 g_signal_connect (rtpbin, "pad-removed", (GCallback) pad_removed_cb, &data);
342 ret = gst_element_set_state (rtpbin, GST_STATE_PLAYING);
343 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
345 /* request session 0 */
346 rtp_sink = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_0");
347 fail_unless (rtp_sink != NULL);
348 ASSERT_OBJECT_REFCOUNT (rtp_sink, "rtp_sink", 2);
351 /* no sourcepads are created yet */
352 fail_unless (rtpbin->numsinkpads == 1);
353 fail_unless (rtpbin->numsrcpads == 0);
355 res = chain_rtp_packet (rtp_sink, &data);
356 GST_DEBUG ("res %d, %s\n", res, gst_flow_get_name (res));
357 fail_unless (res == GST_FLOW_OK);
359 res = chain_rtp_packet (rtp_sink, &data);
360 GST_DEBUG ("res %d, %s\n", res, gst_flow_get_name (res));
361 fail_unless (res == GST_FLOW_OK);
363 /* we wait for the new pad to appear now */
364 g_mutex_lock (&data.lock);
365 while (!data.pad_added)
366 g_cond_wait (&data.cond, &data.lock);
367 g_mutex_unlock (&data.lock);
369 /* sourcepad created now */
370 fail_unless (rtpbin->numsinkpads == 1);
371 fail_unless (rtpbin->numsrcpads == 1);
374 ret = gst_element_set_state (rtpbin, GST_STATE_NULL);
375 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
377 /* pad should be gone now */
378 g_mutex_lock (&data.lock);
379 while (data.pad_added)
380 g_cond_wait (&data.cond, &data.lock);
381 g_mutex_unlock (&data.lock);
383 /* back to playing for the next round */
384 ret = gst_element_set_state (rtpbin, GST_STATE_PLAYING);
385 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
388 /* remove the session */
389 gst_element_release_request_pad (rtpbin, rtp_sink);
390 gst_object_unref (rtp_sink);
392 /* nothing left anymore now */
393 fail_unless (rtpbin->numsinkpads == 0);
394 fail_unless (rtpbin->numsrcpads == 0);
396 ret = gst_element_set_state (rtpbin, GST_STATE_NULL);
397 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
399 gst_object_unref (rtpbin);
406 GST_START_TEST (test_request_pad_by_template_name)
409 GstPad *rtp_sink1, *rtp_sink2, *rtp_sink3;
411 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
412 rtp_sink1 = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_%u");
413 fail_unless (rtp_sink1 != NULL);
414 fail_unless_equals_string (GST_PAD_NAME (rtp_sink1), "recv_rtp_sink_0");
415 ASSERT_OBJECT_REFCOUNT (rtp_sink1, "rtp_sink1", 2);
417 rtp_sink2 = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_%u");
418 fail_unless (rtp_sink2 != NULL);
419 fail_unless_equals_string (GST_PAD_NAME (rtp_sink2), "recv_rtp_sink_1");
420 ASSERT_OBJECT_REFCOUNT (rtp_sink2, "rtp_sink2", 2);
422 rtp_sink3 = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_%u");
423 fail_unless (rtp_sink3 != NULL);
424 fail_unless_equals_string (GST_PAD_NAME (rtp_sink3), "recv_rtp_sink_2");
425 ASSERT_OBJECT_REFCOUNT (rtp_sink3, "rtp_sink3", 2);
428 gst_element_release_request_pad (rtpbin, rtp_sink2);
429 gst_element_release_request_pad (rtpbin, rtp_sink1);
430 gst_element_release_request_pad (rtpbin, rtp_sink3);
431 ASSERT_OBJECT_REFCOUNT (rtp_sink3, "rtp_sink3", 1);
432 ASSERT_OBJECT_REFCOUNT (rtp_sink2, "rtp_sink2", 1);
433 ASSERT_OBJECT_REFCOUNT (rtp_sink1, "rtp_sink", 1);
434 gst_object_unref (rtp_sink1);
435 gst_object_unref (rtp_sink2);
436 gst_object_unref (rtp_sink3);
438 gst_object_unref (rtpbin);
444 encoder_cb (GstElement * rtpbin, guint sessid, GstElement * bin)
446 GstPad *srcpad, *sinkpad;
448 fail_unless (sessid == 2);
450 GST_DEBUG ("making encoder");
451 sinkpad = gst_ghost_pad_new_no_target ("rtp_sink_2", GST_PAD_SINK);
452 srcpad = gst_ghost_pad_new_no_target ("rtp_src_2", GST_PAD_SRC);
454 gst_element_add_pad (bin, sinkpad);
455 gst_element_add_pad (bin, srcpad);
457 return gst_object_ref (bin);
461 encoder_cb2 (GstElement * rtpbin, guint sessid, GstElement * bin)
463 GstPad *srcpad, *sinkpad;
465 fail_unless (sessid == 3);
467 GST_DEBUG ("making encoder");
468 sinkpad = gst_ghost_pad_new_no_target ("rtp_sink_3", GST_PAD_SINK);
469 srcpad = gst_ghost_pad_new_no_target ("rtp_src_3", GST_PAD_SRC);
471 gst_element_add_pad (bin, sinkpad);
472 gst_element_add_pad (bin, srcpad);
474 return gst_object_ref (bin);
477 GST_START_TEST (test_encoder)
479 GstElement *rtpbin, *bin;
480 GstPad *rtp_sink1, *rtp_sink2;
483 bin = gst_bin_new ("rtpenc");
485 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
487 id = g_signal_connect (rtpbin, "request-rtp-encoder", (GCallback) encoder_cb,
490 rtp_sink1 = gst_element_get_request_pad (rtpbin, "send_rtp_sink_2");
491 fail_unless (rtp_sink1 != NULL);
492 fail_unless_equals_string (GST_PAD_NAME (rtp_sink1), "send_rtp_sink_2");
493 ASSERT_OBJECT_REFCOUNT (rtp_sink1, "rtp_sink1", 2);
495 g_signal_handler_disconnect (rtpbin, id);
497 id = g_signal_connect (rtpbin, "request-rtp-encoder", (GCallback) encoder_cb2,
500 rtp_sink2 = gst_element_get_request_pad (rtpbin, "send_rtp_sink_3");
501 fail_unless (rtp_sink2 != NULL);
503 /* remove the session */
504 gst_element_release_request_pad (rtpbin, rtp_sink1);
505 gst_object_unref (rtp_sink1);
507 gst_element_release_request_pad (rtpbin, rtp_sink2);
508 gst_object_unref (rtp_sink2);
510 /* nothing left anymore now */
511 fail_unless (rtpbin->numsinkpads == 0);
512 fail_unless (rtpbin->numsrcpads == 0);
514 gst_object_unref (rtpbin);
515 gst_object_unref (bin);
521 decoder_cb (GstElement * rtpbin, guint sessid, gpointer user_data)
524 GstPad *srcpad, *sinkpad;
526 bin = gst_bin_new (NULL);
528 GST_DEBUG ("making decoder");
529 sinkpad = gst_ghost_pad_new_no_target ("rtp_sink", GST_PAD_SINK);
530 srcpad = gst_ghost_pad_new_no_target ("rtp_src", GST_PAD_SRC);
532 gst_element_add_pad (bin, sinkpad);
533 gst_element_add_pad (bin, srcpad);
538 GST_START_TEST (test_decoder)
541 GstPad *rtp_sink1, *rtp_sink2;
545 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
547 id = g_signal_connect (rtpbin, "request-rtp-decoder", (GCallback) decoder_cb,
550 rtp_sink1 = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_2");
551 fail_unless (rtp_sink1 != NULL);
552 fail_unless_equals_string (GST_PAD_NAME (rtp_sink1), "recv_rtp_sink_2");
553 ASSERT_OBJECT_REFCOUNT (rtp_sink1, "rtp_sink1", 2);
555 rtp_sink2 = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_3");
556 fail_unless (rtp_sink2 != NULL);
558 g_signal_handler_disconnect (rtpbin, id);
560 /* remove the session */
561 gst_element_release_request_pad (rtpbin, rtp_sink1);
562 gst_object_unref (rtp_sink1);
564 gst_element_release_request_pad (rtpbin, rtp_sink2);
565 gst_object_unref (rtp_sink2);
567 /* nothing left anymore now */
568 fail_unless (rtpbin->numsinkpads == 0);
569 fail_unless (rtpbin->numsrcpads == 0);
571 gst_object_unref (rtpbin);
577 aux_sender_cb (GstElement * rtpbin, guint sessid, gpointer user_data)
580 GstPad *srcpad, *sinkpad;
582 bin = (GstElement *) user_data;
584 GST_DEBUG ("making AUX sender");
585 sinkpad = gst_ghost_pad_new_no_target ("sink_2", GST_PAD_SINK);
586 gst_element_add_pad (bin, sinkpad);
588 srcpad = gst_ghost_pad_new_no_target ("src_2", GST_PAD_SRC);
589 gst_element_add_pad (bin, srcpad);
590 srcpad = gst_ghost_pad_new_no_target ("src_1", GST_PAD_SRC);
591 gst_element_add_pad (bin, srcpad);
592 srcpad = gst_ghost_pad_new_no_target ("src_3", GST_PAD_SRC);
593 gst_element_add_pad (bin, srcpad);
598 GST_START_TEST (test_aux_sender)
601 GstPad *rtp_sink1, *rtp_src, *rtcp_src;
603 GstElement *aux_sender = gst_object_ref_sink (gst_bin_new ("aux-sender"));
605 gst_object_ref (aux_sender);
607 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
609 id = g_signal_connect (rtpbin, "request-aux-sender",
610 (GCallback) aux_sender_cb, aux_sender);
612 rtp_sink1 = gst_element_get_request_pad (rtpbin, "send_rtp_sink_2");
613 fail_unless (rtp_sink1 != NULL);
614 fail_unless_equals_string (GST_PAD_NAME (rtp_sink1), "send_rtp_sink_2");
615 ASSERT_OBJECT_REFCOUNT (rtp_sink1, "rtp_sink1", 2);
617 g_signal_handler_disconnect (rtpbin, id);
619 rtp_src = gst_element_get_static_pad (rtpbin, "send_rtp_src_2");
620 fail_unless (rtp_src != NULL);
621 gst_object_unref (rtp_src);
623 rtp_src = gst_element_get_static_pad (rtpbin, "send_rtp_src_1");
624 fail_unless (rtp_src != NULL);
625 gst_object_unref (rtp_src);
627 rtcp_src = gst_element_get_request_pad (rtpbin, "send_rtcp_src_1");
628 fail_unless (rtcp_src != NULL);
629 gst_element_release_request_pad (rtpbin, rtcp_src);
630 gst_object_unref (rtcp_src);
632 rtp_src = gst_element_get_static_pad (rtpbin, "send_rtp_src_3");
633 fail_unless (rtp_src != NULL);
634 gst_object_unref (rtp_src);
636 /* remove the session */
637 gst_element_release_request_pad (rtpbin, rtp_sink1);
638 gst_object_unref (rtp_sink1);
640 /* We have sinked the initial reference before returning it
641 * in the request callback, the ref count should now be 1 because
642 * the return of the signal is transfer full, and rtpbin should
643 * have released that reference by now, but we had taken an
644 * extra reference to perform this check
646 ASSERT_OBJECT_REFCOUNT (aux_sender, "aux-sender", 1);
648 gst_object_unref (aux_sender);
649 gst_object_unref (rtpbin);
655 aux_receiver_cb (GstElement * rtpbin, guint sessid, gpointer user_data)
658 GstPad *srcpad, *sinkpad;
660 bin = gst_bin_new (NULL);
662 GST_DEBUG ("making AUX receiver");
663 srcpad = gst_ghost_pad_new_no_target ("src_2", GST_PAD_SRC);
664 gst_element_add_pad (bin, srcpad);
666 sinkpad = gst_ghost_pad_new_no_target ("sink_2", GST_PAD_SINK);
667 gst_element_add_pad (bin, sinkpad);
668 sinkpad = gst_ghost_pad_new_no_target ("sink_1", GST_PAD_SINK);
669 gst_element_add_pad (bin, sinkpad);
670 sinkpad = gst_ghost_pad_new_no_target ("sink_3", GST_PAD_SINK);
671 gst_element_add_pad (bin, sinkpad);
676 GST_START_TEST (test_aux_receiver)
679 GstPad *rtp_sink1, *rtp_sink2, *rtcp_sink;
682 rtpbin = gst_element_factory_make ("rtpbin", "rtpbin");
684 id = g_signal_connect (rtpbin, "request-aux-receiver",
685 (GCallback) aux_receiver_cb, NULL);
687 rtp_sink1 = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_2");
688 fail_unless (rtp_sink1 != NULL);
690 rtp_sink2 = gst_element_get_request_pad (rtpbin, "recv_rtp_sink_1");
691 fail_unless (rtp_sink2 != NULL);
693 g_signal_handler_disconnect (rtpbin, id);
695 rtcp_sink = gst_element_get_request_pad (rtpbin, "recv_rtcp_sink_1");
696 fail_unless (rtcp_sink != NULL);
697 gst_element_release_request_pad (rtpbin, rtcp_sink);
698 gst_object_unref (rtcp_sink);
700 /* remove the session */
701 gst_element_release_request_pad (rtpbin, rtp_sink1);
702 gst_object_unref (rtp_sink1);
703 gst_element_release_request_pad (rtpbin, rtp_sink2);
704 gst_object_unref (rtp_sink2);
706 gst_object_unref (rtpbin);
711 GST_START_TEST (test_sender_eos)
713 GstElement *rtpsession;
714 GstBuffer *rtp_buffer;
715 GstBuffer *rtcp_buffer;
716 GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
717 GstRTCPBuffer rtcpbuf = GST_RTCP_BUFFER_INIT;
718 GstRTCPPacket rtcppacket;
719 static GstStaticPadTemplate recv_tmpl =
720 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
721 GST_STATIC_CAPS ("ANY"));
722 GstPad *send_rtp_sink;
723 GstPad *recv_rtcp_sink;
726 GstPad *rtp_sink, *rtcp_sink;
728 GstTestClock *tclock;
731 guint32 ssrc_in, packet_count, octet_count;
732 gboolean got_bye = FALSE;
734 clock = gst_test_clock_new ();
735 gst_system_clock_set_default (clock);
736 tclock = GST_TEST_CLOCK (clock);
737 gst_test_clock_set_time (tclock, 0);
739 rtpsession = gst_element_factory_make ("rtpsession", NULL);
740 send_rtp_sink = gst_element_get_request_pad (rtpsession, "send_rtp_sink");
741 recv_rtcp_sink = gst_element_get_request_pad (rtpsession, "recv_rtcp_sink");
744 rtp_sink = gst_check_setup_sink_pad_by_name (rtpsession, &recv_tmpl,
746 rtcp_sink = gst_check_setup_sink_pad_by_name (rtpsession, &recv_tmpl,
749 gst_pad_set_active (rtp_sink, TRUE);
750 gst_pad_set_active (rtcp_sink, TRUE);
752 gst_element_set_state (rtpsession, GST_STATE_PLAYING);
754 /* Send initial events */
756 gst_segment_init (&segment, GST_FORMAT_TIME);
757 fail_unless (gst_pad_send_event (send_rtp_sink,
758 gst_event_new_stream_start ("id")));
759 fail_unless (gst_pad_send_event (send_rtp_sink,
760 gst_event_new_segment (&segment)));
762 fail_unless (gst_pad_send_event (recv_rtcp_sink,
763 gst_event_new_stream_start ("id")));
764 fail_unless (gst_pad_send_event (recv_rtcp_sink,
765 gst_event_new_segment (&segment)));
767 /* Get the suggested SSRC from the rtpsession */
769 caps = gst_pad_query_caps (send_rtp_sink, NULL);
770 s = gst_caps_get_structure (caps, 0);
771 gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL);
772 gst_caps_unref (caps);
774 /* Send a RTP packet */
776 rtp_buffer = gst_rtp_buffer_new_allocate (10, 0, 0);
777 gst_rtp_buffer_map (rtp_buffer, GST_MAP_READWRITE, &rtpbuf);
778 gst_rtp_buffer_set_ssrc (&rtpbuf, 1);
779 gst_rtp_buffer_set_seq (&rtpbuf, 0);
780 gst_rtp_buffer_unmap (&rtpbuf);
782 fail_unless (gst_pad_chain (send_rtp_sink, rtp_buffer) == GST_FLOW_OK);
784 /* Make sure it went through */
785 fail_unless_equals_int (g_list_length (buffers), 1);
786 fail_unless_equals_pointer (buffers->data, rtp_buffer);
787 gst_check_drop_buffers ();
789 /* Advance time and send a packet to prevent source sender timeout */
790 gst_test_clock_set_time (tclock, 1 * GST_SECOND);
792 /* Just send a send packet to prevent timeout */
793 rtp_buffer = gst_rtp_buffer_new_allocate (10, 0, 0);
794 gst_rtp_buffer_map (rtp_buffer, GST_MAP_READWRITE, &rtpbuf);
795 gst_rtp_buffer_set_ssrc (&rtpbuf, 1);
796 gst_rtp_buffer_set_seq (&rtpbuf, 1);
797 gst_rtp_buffer_set_timestamp (&rtpbuf, 10);
798 gst_rtp_buffer_unmap (&rtpbuf);
800 fail_unless (gst_pad_chain (send_rtp_sink, rtp_buffer) == GST_FLOW_OK);
802 /* Make sure it went through */
803 fail_unless_equals_int (g_list_length (buffers), 1);
804 fail_unless_equals_pointer (buffers->data, rtp_buffer);
805 gst_check_drop_buffers ();
807 /* Advance clock twice and we should have one RTCP packet at least */
808 gst_test_clock_crank (tclock);
809 gst_test_clock_crank (tclock);
811 g_mutex_lock (&check_mutex);
812 while (buffers == NULL)
813 g_cond_wait (&check_cond, &check_mutex);
815 fail_unless (gst_rtcp_buffer_map (buffers->data, GST_MAP_READ, &rtcpbuf));
817 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcpbuf, &rtcppacket));
819 fail_unless_equals_int (gst_rtcp_packet_get_type (&rtcppacket),
821 gst_rtcp_packet_sr_get_sender_info (&rtcppacket, &ssrc_in, NULL, NULL,
822 &packet_count, &octet_count);
823 fail_unless_equals_int (packet_count, 2);
824 fail_unless_equals_int (octet_count, 20);
826 fail_unless (gst_rtcp_packet_move_to_next (&rtcppacket));
827 fail_unless_equals_int (gst_rtcp_packet_get_type (&rtcppacket),
830 gst_rtcp_buffer_unmap (&rtcpbuf);
831 gst_check_drop_buffers ();
833 g_mutex_unlock (&check_mutex);
836 /* Create and send a valid RTCP reply packet */
837 rtcp_buffer = gst_rtcp_buffer_new (1500);
838 gst_rtcp_buffer_map (rtcp_buffer, GST_MAP_READWRITE, &rtcpbuf);
839 gst_rtcp_buffer_add_packet (&rtcpbuf, GST_RTCP_TYPE_RR, &rtcppacket);
840 gst_rtcp_packet_rr_set_ssrc (&rtcppacket, ssrc + 1);
841 gst_rtcp_packet_add_rb (&rtcppacket, ssrc, 0, 0, 0, 0, 0, 0);
842 gst_rtcp_buffer_add_packet (&rtcpbuf, GST_RTCP_TYPE_SDES, &rtcppacket);
843 gst_rtcp_packet_sdes_add_item (&rtcppacket, ssrc + 1);
844 gst_rtcp_packet_sdes_add_entry (&rtcppacket, GST_RTCP_SDES_CNAME, 3,
846 gst_rtcp_packet_sdes_add_entry (&rtcppacket, GST_RTCP_SDES_NAME, 2,
848 gst_rtcp_packet_sdes_add_entry (&rtcppacket, GST_RTCP_SDES_END, 0,
850 gst_rtcp_buffer_unmap (&rtcpbuf);
851 fail_unless (gst_pad_chain (recv_rtcp_sink, rtcp_buffer) == GST_FLOW_OK);
854 /* Send a EOS to trigger sending a BYE message */
855 fail_unless (gst_pad_send_event (send_rtp_sink, gst_event_new_eos ()));
857 /* Crank to process EOS and wait for BYE */
859 gst_test_clock_crank (tclock);
860 g_mutex_lock (&check_mutex);
861 while (buffers == NULL)
862 g_cond_wait (&check_cond, &check_mutex);
864 fail_unless (gst_rtcp_buffer_map (g_list_last (buffers)->data, GST_MAP_READ,
866 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcpbuf, &rtcppacket));
868 while (gst_rtcp_packet_move_to_next (&rtcppacket)) {
869 if (gst_rtcp_packet_get_type (&rtcppacket) == GST_RTCP_TYPE_BYE) {
874 g_mutex_unlock (&check_mutex);
875 gst_rtcp_buffer_unmap (&rtcpbuf);
881 gst_check_drop_buffers ();
884 fail_unless (GST_PAD_IS_EOS (rtp_sink));
885 fail_unless (GST_PAD_IS_EOS (rtcp_sink));
887 gst_pad_set_active (rtp_sink, FALSE);
888 gst_pad_set_active (rtcp_sink, FALSE);
890 gst_check_teardown_pad_by_name (rtpsession, "send_rtp_src");
891 gst_check_teardown_pad_by_name (rtpsession, "send_rtcp_src");
892 gst_element_release_request_pad (rtpsession, send_rtp_sink);
893 gst_object_unref (send_rtp_sink);
894 gst_element_release_request_pad (rtpsession, recv_rtcp_sink);
895 gst_object_unref (recv_rtcp_sink);
897 gst_check_teardown_element (rtpsession);
899 gst_system_clock_set_default (NULL);
900 gst_object_unref (clock);
907 generate_rtp_buffer (GstClockTime ts,
908 guint seqnum, guint32 rtp_ts, guint pt, guint ssrc)
910 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
911 GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
912 GST_BUFFER_PTS (buf) = ts;
913 GST_BUFFER_DTS (buf) = ts;
915 gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp);
916 gst_rtp_buffer_set_payload_type (&rtp, pt);
917 gst_rtp_buffer_set_seq (&rtp, seqnum);
918 gst_rtp_buffer_set_timestamp (&rtp, rtp_ts);
919 gst_rtp_buffer_set_ssrc (&rtp, ssrc);
921 gst_rtp_buffer_unmap (&rtp);
927 _request_pt_map (G_GNUC_UNUSED GstElement * rtpbin,
928 G_GNUC_UNUSED guint session_id, G_GNUC_UNUSED guint pt,
929 const GstCaps * caps)
931 return gst_caps_copy (caps);
935 _pad_added (G_GNUC_UNUSED GstElement * rtpbin, GstPad * pad, GstHarness * h)
937 gst_harness_add_element_src_pad (h, pad);
940 GST_START_TEST (test_quick_shutdown)
944 for (r = 0; r < 1000; r++) {
946 GstHarness *h = gst_harness_new_with_padnames ("rtpbin",
947 "recv_rtp_sink_0", NULL);
948 GstCaps *caps = gst_caps_new_simple ("application/x-rtp",
949 "clock-rate", G_TYPE_INT, 8000,
950 "payload", G_TYPE_INT, 100, NULL);
952 g_signal_connect (h->element, "request-pt-map",
953 G_CALLBACK (_request_pt_map), caps);
954 g_signal_connect (h->element, "pad-added", G_CALLBACK (_pad_added), h);
956 gst_harness_set_src_caps (h, gst_caps_copy (caps));
958 for (i = 0; i < 50; i++) {
960 generate_rtp_buffer (i * GST_MSECOND * 20, i, i * 160, 100, 1234));
962 gst_harness_crank_single_clock_wait (h);
964 gst_caps_unref (caps);
965 gst_harness_teardown (h);
974 Suite *s = suite_create ("rtpbin");
975 TCase *tc_chain = tcase_create ("general");
977 suite_add_tcase (s, tc_chain);
978 tcase_add_test (tc_chain, test_pads);
979 tcase_add_test (tc_chain, test_cleanup_send);
980 tcase_add_test (tc_chain, test_cleanup_recv);
981 tcase_add_test (tc_chain, test_cleanup_recv2);
982 tcase_add_test (tc_chain, test_request_pad_by_template_name);
983 tcase_add_test (tc_chain, test_encoder);
984 tcase_add_test (tc_chain, test_decoder);
985 tcase_add_test (tc_chain, test_aux_sender);
986 tcase_add_test (tc_chain, test_aux_receiver);
987 tcase_add_test (tc_chain, test_sender_eos);
988 tcase_add_test (tc_chain, test_quick_shutdown);
993 GST_CHECK_MAIN (rtpbin);