3 * unit test for gstrtpsession
5 * Copyright (C) <2009> Wim Taymans <wim.taymans@gmail.com>
6 * Copyright (C) 2013 Collabora Ltd.
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.
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.
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.
23 #define GLIB_DISABLE_DEPRECATION_WARNINGS
25 #include <gst/check/gstharness.h>
26 #include <gst/check/gstcheck.h>
27 #include <gst/check/gsttestclock.h>
28 #include <gst/check/gstharness.h>
30 #include <gst/rtp/gstrtpbuffer.h>
31 #include <gst/rtp/gstrtcpbuffer.h>
32 #include <gst/net/gstnetaddressmeta.h>
33 #include <gst/video/video.h>
35 #define TEST_BUF_CLOCK_RATE 8000
37 #define TEST_BUF_SSRC 0x01BADBAD
38 #define TEST_BUF_MS 20
39 #define TEST_BUF_DURATION (TEST_BUF_MS * GST_MSECOND)
40 #define TEST_BUF_SIZE (64000 * TEST_BUF_MS / 1000)
41 #define TEST_RTP_TS_DURATION (TEST_BUF_CLOCK_RATE * TEST_BUF_MS / 1000)
46 return gst_caps_new_simple ("application/x-rtp",
47 "clock-rate", G_TYPE_INT, TEST_BUF_CLOCK_RATE,
48 "payload", G_TYPE_INT, TEST_BUF_PT, NULL);
52 generate_test_buffer_full (GstClockTime dts,
53 guint seq_num, guint32 rtp_ts, guint ssrc)
58 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
60 buf = gst_rtp_buffer_new_allocate (TEST_BUF_SIZE, 0, 0);
61 GST_BUFFER_DTS (buf) = dts;
63 gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp);
64 gst_rtp_buffer_set_payload_type (&rtp, TEST_BUF_PT);
65 gst_rtp_buffer_set_seq (&rtp, seq_num);
66 gst_rtp_buffer_set_timestamp (&rtp, rtp_ts);
67 gst_rtp_buffer_set_ssrc (&rtp, ssrc);
69 payload = gst_rtp_buffer_get_payload (&rtp);
70 for (i = 0; i < TEST_BUF_SIZE; i++)
73 gst_rtp_buffer_unmap (&rtp);
79 generate_test_buffer (guint seq_num, guint ssrc)
81 return generate_test_buffer_full (seq_num * TEST_BUF_DURATION,
82 seq_num, seq_num * TEST_RTP_TS_DURATION, ssrc);
87 GstHarness *send_rtp_h;
88 GstHarness *recv_rtp_h;
92 GObject *internal_session;
93 GstTestClock *testclock;
98 _pt_map_requested (GstElement * element, guint pt, gpointer data)
100 SessionHarness *h = data;
101 return gst_caps_copy (h->caps);
104 static SessionHarness *
105 session_harness_new (void)
107 SessionHarness *h = g_new0 (SessionHarness, 1);
108 h->caps = generate_caps ();
110 h->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
111 gst_system_clock_set_default (GST_CLOCK_CAST (h->testclock));
113 h->session = gst_element_factory_make ("rtpsession", NULL);
114 gst_element_set_clock (h->session, GST_CLOCK_CAST (h->testclock));
116 h->send_rtp_h = gst_harness_new_with_element (h->session,
117 "send_rtp_sink", "send_rtp_src");
118 gst_harness_set_src_caps (h->send_rtp_h, gst_caps_copy (h->caps));
120 h->recv_rtp_h = gst_harness_new_with_element (h->session,
121 "recv_rtp_sink", "recv_rtp_src");
122 gst_harness_set_src_caps (h->recv_rtp_h, gst_caps_copy (h->caps));
124 h->rtcp_h = gst_harness_new_with_element (h->session,
125 "recv_rtcp_sink", "send_rtcp_src");
126 gst_harness_set_src_caps_str (h->rtcp_h, "application/x-rtcp");
128 g_signal_connect (h->session, "request-pt-map",
129 (GCallback) _pt_map_requested, h);
131 g_object_get (h->session, "internal-session", &h->internal_session, NULL);
137 session_harness_free (SessionHarness * h)
139 gst_system_clock_set_default (NULL);
141 gst_caps_unref (h->caps);
142 gst_object_unref (h->testclock);
144 gst_harness_teardown (h->rtcp_h);
145 gst_harness_teardown (h->recv_rtp_h);
146 gst_harness_teardown (h->send_rtp_h);
148 g_object_unref (h->internal_session);
149 gst_object_unref (h->session);
154 session_harness_send_rtp (SessionHarness * h, GstBuffer * buf)
156 return gst_harness_push (h->send_rtp_h, buf);
160 session_harness_recv_rtp (SessionHarness * h, GstBuffer * buf)
162 return gst_harness_push (h->recv_rtp_h, buf);
166 session_harness_recv_rtcp (SessionHarness * h, GstBuffer * buf)
168 return gst_harness_push (h->rtcp_h, buf);
172 session_harness_pull_rtcp (SessionHarness * h)
174 return gst_harness_pull (h->rtcp_h);
178 session_harness_crank_clock (SessionHarness * h)
180 gst_test_clock_crank (h->testclock);
184 session_harness_advance_and_crank (SessionHarness * h, GstClockTime delta)
186 GstClockID res, pending;
188 gst_test_clock_wait_for_next_pending_id (h->testclock, &pending);
189 gst_test_clock_advance_time (h->testclock, delta);
190 res = gst_test_clock_process_next_clock_id (h->testclock);
196 gst_clock_id_unref (res);
197 gst_clock_id_unref (pending);
202 session_harness_produce_rtcp (SessionHarness * h, gint num_rtcp_packets)
204 /* due to randomness in rescheduling of RTCP timeout, we need to
205 keep cranking until we have the desired amount of packets */
206 while (gst_harness_buffers_in_queue (h->rtcp_h) < num_rtcp_packets)
207 session_harness_crank_clock (h);
211 session_harness_force_key_unit (SessionHarness * h,
212 guint count, guint ssrc, guint payload, gint * reqid, guint64 * sfr)
214 GstClockTime running_time = GST_CLOCK_TIME_NONE;
215 gboolean all_headers = TRUE;
217 GstStructure *s = gst_structure_new ("GstForceKeyUnit",
218 "running-time", GST_TYPE_CLOCK_TIME, running_time,
219 "all-headers", G_TYPE_BOOLEAN, all_headers,
220 "count", G_TYPE_UINT, count,
221 "ssrc", G_TYPE_UINT, ssrc,
222 "payload", G_TYPE_UINT, payload,
226 gst_structure_set (s, "reqid", G_TYPE_INT, *reqid, NULL);
228 gst_structure_set (s, "sfr", G_TYPE_UINT64, *sfr, NULL);
230 gst_harness_push_upstream_event (h->recv_rtp_h,
231 gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s));
234 GST_START_TEST (test_multiple_ssrc_rr)
236 SessionHarness *h = session_harness_new ();
238 GstBuffer *in_buf, *out_buf;
239 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
240 GstRTCPPacket rtcp_packet;
249 /* receive buffers with multiple ssrcs */
250 for (i = 0; i < 2; i++) {
251 for (j = 0; j < G_N_ELEMENTS (ssrcs); j++) {
252 in_buf = generate_test_buffer (i, ssrcs[j]);
253 res = session_harness_recv_rtp (h, in_buf);
254 fail_unless_equals_int (GST_FLOW_OK, res);
258 /* crank the rtcp-thread and pull out the rtcp-packet we have generated */
259 session_harness_crank_clock (h);
260 out_buf = session_harness_pull_rtcp (h);
262 /* verify we have report blocks for both ssrcs */
263 g_assert (out_buf != NULL);
264 fail_unless (gst_rtcp_buffer_validate (out_buf));
265 gst_rtcp_buffer_map (out_buf, GST_MAP_READ, &rtcp);
266 g_assert (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
267 fail_unless_equals_int (GST_RTCP_TYPE_RR,
268 gst_rtcp_packet_get_type (&rtcp_packet));
270 fail_unless_equals_int (G_N_ELEMENTS (ssrcs),
271 gst_rtcp_packet_get_rb_count (&rtcp_packet));
274 for (i = 0; i < G_N_ELEMENTS (ssrcs); i++) {
276 gst_rtcp_packet_get_rb (&rtcp_packet, i, &ssrc,
277 NULL, NULL, NULL, NULL, NULL, NULL);
278 for (j = 0; j < G_N_ELEMENTS (ssrcs); j++) {
279 if (ssrcs[j] == ssrc)
283 fail_unless_equals_int (G_N_ELEMENTS (ssrcs), ssrc_match);
285 gst_rtcp_buffer_unmap (&rtcp);
286 gst_buffer_unref (out_buf);
288 session_harness_free (h);
293 /* This verifies that rtpsession will correctly place RBs round-robin
294 * across multiple RRs when there are too many senders that their RBs
295 * do not fit in one RR */
296 GST_START_TEST (test_multiple_senders_roundrobin_rbs)
298 SessionHarness *h = session_harness_new ();
301 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
302 GstRTCPPacket rtcp_packet;
305 GHashTable *rb_ssrcs, *tmp_set;
307 g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
309 for (i = 0; i < 2; i++) { /* cycles between RR reports */
310 for (j = 0; j < 5; j++) { /* packets per ssrc */
311 gint seq = (i * 5) + j;
312 for (k = 0; k < 35; k++) { /* number of ssrcs */
313 buf = generate_test_buffer (seq, 10000 + k);
314 res = session_harness_recv_rtp (h, buf);
315 fail_unless_equals_int (GST_FLOW_OK, res);
320 rb_ssrcs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
321 (GDestroyNotify) g_hash_table_unref);
323 /* verify the rtcp packets */
324 for (i = 0; i < 2; i++) {
325 guint expected_rb_count = (i < 1) ? GST_RTCP_MAX_RB_COUNT :
326 (35 - GST_RTCP_MAX_RB_COUNT);
328 session_harness_produce_rtcp (h, 1);
329 buf = session_harness_pull_rtcp (h);
330 g_assert (buf != NULL);
331 fail_unless (gst_rtcp_buffer_validate (buf));
333 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
334 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
335 fail_unless_equals_int (GST_RTCP_TYPE_RR,
336 gst_rtcp_packet_get_type (&rtcp_packet));
338 ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
339 fail_unless_equals_int (0xDEADBEEF, ssrc);
341 /* inspect the RBs */
342 fail_unless_equals_int (expected_rb_count,
343 gst_rtcp_packet_get_rb_count (&rtcp_packet));
346 tmp_set = g_hash_table_new (g_direct_hash, g_direct_equal);
347 g_hash_table_insert (rb_ssrcs, GUINT_TO_POINTER (ssrc), tmp_set);
349 tmp_set = g_hash_table_lookup (rb_ssrcs, GUINT_TO_POINTER (ssrc));
353 for (j = 0; j < expected_rb_count; j++) {
354 gst_rtcp_packet_get_rb (&rtcp_packet, j, &ssrc, NULL, NULL,
355 NULL, NULL, NULL, NULL);
356 g_assert_cmpint (ssrc, >=, 10000);
357 g_assert_cmpint (ssrc, <=, 10035);
358 g_hash_table_add (tmp_set, GUINT_TO_POINTER (ssrc));
361 gst_rtcp_buffer_unmap (&rtcp);
362 gst_buffer_unref (buf);
365 /* now verify all received ssrcs have been reported */
366 fail_unless_equals_int (1, g_hash_table_size (rb_ssrcs));
367 tmp_set = g_hash_table_lookup (rb_ssrcs, GUINT_TO_POINTER (0xDEADBEEF));
369 fail_unless_equals_int (35, g_hash_table_size (tmp_set));
371 g_hash_table_unref (rb_ssrcs);
372 session_harness_free (h);
377 GST_START_TEST (test_no_rbs_for_internal_senders)
379 SessionHarness *h = session_harness_new ();
382 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
383 GstRTCPPacket rtcp_packet;
386 GHashTable *sr_ssrcs;
387 GHashTable *rb_ssrcs, *tmp_set;
389 /* Push RTP from our send SSRCs */
390 for (j = 0; j < 5; j++) { /* packets per ssrc */
391 for (k = 0; k < 2; k++) { /* number of ssrcs */
392 buf = generate_test_buffer (j, 10000 + k);
393 res = session_harness_send_rtp (h, buf);
394 fail_unless_equals_int (GST_FLOW_OK, res);
398 /* crank the RTCP pad thread */
399 session_harness_crank_clock (h);
401 sr_ssrcs = g_hash_table_new (g_direct_hash, g_direct_equal);
403 /* verify the rtcp packets */
404 for (i = 0; i < 2; i++) {
405 buf = session_harness_pull_rtcp (h);
406 g_assert (buf != NULL);
407 g_assert (gst_rtcp_buffer_validate (buf));
409 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
410 g_assert (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
411 fail_unless_equals_int (GST_RTCP_TYPE_SR,
412 gst_rtcp_packet_get_type (&rtcp_packet));
414 gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL,
416 g_assert_cmpint (ssrc, >=, 10000);
417 g_assert_cmpint (ssrc, <=, 10001);
418 g_hash_table_add (sr_ssrcs, GUINT_TO_POINTER (ssrc));
420 /* There should be no RBs as there are no remote senders */
421 fail_unless_equals_int (0, gst_rtcp_packet_get_rb_count (&rtcp_packet));
423 gst_rtcp_buffer_unmap (&rtcp);
424 gst_buffer_unref (buf);
427 /* Ensure both internal senders generated RTCP */
428 fail_unless_equals_int (2, g_hash_table_size (sr_ssrcs));
429 g_hash_table_unref (sr_ssrcs);
431 /* Generate RTP from remote side */
432 for (j = 0; j < 5; j++) { /* packets per ssrc */
433 for (k = 0; k < 2; k++) { /* number of ssrcs */
434 buf = generate_test_buffer (j, 20000 + k);
435 res = session_harness_recv_rtp (h, buf);
436 fail_unless_equals_int (GST_FLOW_OK, res);
440 sr_ssrcs = g_hash_table_new (g_direct_hash, g_direct_equal);
441 rb_ssrcs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
442 (GDestroyNotify) g_hash_table_unref);
444 /* verify the rtcp packets */
445 for (i = 0; i < 2; i++) {
446 session_harness_produce_rtcp (h, 1);
447 buf = session_harness_pull_rtcp (h);
448 g_assert (buf != NULL);
449 g_assert (gst_rtcp_buffer_validate (buf));
451 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
452 g_assert (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
453 fail_unless_equals_int (GST_RTCP_TYPE_SR,
454 gst_rtcp_packet_get_type (&rtcp_packet));
456 gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL,
458 g_assert_cmpint (ssrc, >=, 10000);
459 g_assert_cmpint (ssrc, <=, 10001);
460 g_hash_table_add (sr_ssrcs, GUINT_TO_POINTER (ssrc));
462 /* There should be 2 RBs: one for each remote sender */
463 fail_unless_equals_int (2, gst_rtcp_packet_get_rb_count (&rtcp_packet));
465 tmp_set = g_hash_table_new (g_direct_hash, g_direct_equal);
466 g_hash_table_insert (rb_ssrcs, GUINT_TO_POINTER (ssrc), tmp_set);
468 for (j = 0; j < 2; j++) {
469 gst_rtcp_packet_get_rb (&rtcp_packet, j, &ssrc, NULL, NULL,
470 NULL, NULL, NULL, NULL);
471 g_assert_cmpint (ssrc, >=, 20000);
472 g_assert_cmpint (ssrc, <=, 20001);
473 g_hash_table_add (tmp_set, GUINT_TO_POINTER (ssrc));
476 gst_rtcp_buffer_unmap (&rtcp);
477 gst_buffer_unref (buf);
480 /* now verify all received ssrcs have been reported */
481 fail_unless_equals_int (2, g_hash_table_size (sr_ssrcs));
482 fail_unless_equals_int (2, g_hash_table_size (rb_ssrcs));
483 for (i = 10000; i < 10002; i++) {
484 tmp_set = g_hash_table_lookup (rb_ssrcs, GUINT_TO_POINTER (i));
486 fail_unless_equals_int (2, g_hash_table_size (tmp_set));
489 g_hash_table_unref (rb_ssrcs);
490 g_hash_table_unref (sr_ssrcs);
492 session_harness_free (h);
497 GST_START_TEST (test_internal_sources_timeout)
499 SessionHarness *h = session_harness_new ();
503 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
504 GstRTCPPacket rtcp_packet;
505 GstRTCPType rtcp_type;
511 g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
512 g_object_get (h->internal_session, "internal-ssrc", &internal_ssrc, NULL);
513 fail_unless_equals_int (0xDEADBEEF, internal_ssrc);
515 for (i = 1; i < 4; i++) {
516 buf = generate_test_buffer (i, 0xBEEFDEAD);
517 res = session_harness_recv_rtp (h, buf);
518 fail_unless_equals_int (GST_FLOW_OK, res);
521 /* verify that rtpsession has sent RR for an internally-created
522 * RTPSource that is using the internal-ssrc */
523 session_harness_produce_rtcp (h, 1);
524 buf = session_harness_pull_rtcp (h);
526 fail_unless (buf != NULL);
527 fail_unless (gst_rtcp_buffer_validate (buf));
528 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
529 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
530 fail_unless_equals_int (GST_RTCP_TYPE_RR,
531 gst_rtcp_packet_get_type (&rtcp_packet));
532 ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
533 fail_unless_equals_int (ssrc, internal_ssrc);
534 gst_rtcp_buffer_unmap (&rtcp);
535 gst_buffer_unref (buf);
537 /* ok, now let's push some RTP packets */
538 caps = gst_caps_new_simple ("application/x-rtp",
539 "ssrc", G_TYPE_UINT, 0x01BADBAD, NULL);
540 gst_harness_set_src_caps (h->send_rtp_h, caps);
542 for (i = 1; i < 4; i++) {
543 buf = generate_test_buffer (i, 0x01BADBAD);
544 res = session_harness_send_rtp (h, buf);
545 fail_unless_equals_int (GST_FLOW_OK, res);
548 /* internal ssrc must have changed already */
549 g_object_get (h->internal_session, "internal-ssrc", &internal_ssrc, NULL);
550 fail_unless (internal_ssrc != ssrc);
551 fail_unless_equals_int (0x01BADBAD, internal_ssrc);
553 /* verify SR and RR */
555 for (i = 0; i < 5; i++) {
556 session_harness_produce_rtcp (h, 1);
557 buf = session_harness_pull_rtcp (h);
558 g_assert (buf != NULL);
559 fail_unless (gst_rtcp_buffer_validate (buf));
560 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
561 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
562 rtcp_type = gst_rtcp_packet_get_type (&rtcp_packet);
564 if (rtcp_type == GST_RTCP_TYPE_SR) {
565 gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL, NULL,
567 fail_unless_equals_int (internal_ssrc, ssrc);
568 fail_unless_equals_int (0x01BADBAD, ssrc);
570 } else if (rtcp_type == GST_RTCP_TYPE_RR) {
571 ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
572 if (internal_ssrc != ssrc)
575 gst_rtcp_buffer_unmap (&rtcp);
576 gst_buffer_unref (buf);
578 fail_unless_equals_int (0x3, j); /* verify we got both SR and RR */
580 /* go 30 seconds in the future and observe both sources timing out:
581 * 0xDEADBEEF -> BYE, 0x01BADBAD -> becomes receiver only */
582 fail_unless (session_harness_advance_and_crank (h, 30 * GST_SECOND));
584 /* verify BYE and RR */
588 session_harness_produce_rtcp (h, 1);
589 buf = session_harness_pull_rtcp (h);
590 fail_unless (buf != NULL);
591 fail_unless (gst_rtcp_buffer_validate (buf));
592 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
593 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
594 rtcp_type = gst_rtcp_packet_get_type (&rtcp_packet);
596 if (rtcp_type == GST_RTCP_TYPE_RR) {
597 ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
598 if (ssrc == 0x01BADBAD) {
600 fail_unless_equals_int (internal_ssrc, ssrc);
601 /* 2 => RR, SDES. There is no BYE here */
602 fail_unless_equals_int (2, gst_rtcp_buffer_get_packet_count (&rtcp));
603 } else if (ssrc == 0xDEADBEEF) {
605 g_assert_cmpint (ssrc, !=, internal_ssrc);
606 /* 3 => RR, SDES, BYE */
607 if (gst_rtcp_buffer_get_packet_count (&rtcp) == 3) {
608 fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
609 fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
610 fail_unless_equals_int (GST_RTCP_TYPE_BYE,
611 gst_rtcp_packet_get_type (&rtcp_packet));
616 gst_rtcp_buffer_unmap (&rtcp);
617 gst_buffer_unref (buf);
619 fail_unless_equals_int (0x3, j); /* verify we got both BYE and RR */
621 session_harness_free (h);
635 on_app_rtcp_cb (GObject * session, guint subtype, guint ssrc,
636 const gchar * name, GstBuffer * data, RTCPAppResult * result)
638 result->subtype = subtype;
640 result->name = g_strdup (name);
641 result->data = data ? gst_buffer_ref (data) : NULL;
644 GST_START_TEST (test_receive_rtcp_app_packet)
646 SessionHarness *h = session_harness_new ();
648 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
649 GstRTCPPacket packet;
650 RTCPAppResult result = { 0 };
651 guint8 data[] = { 0x11, 0x22, 0x33, 0x44 };
653 g_signal_connect (h->internal_session, "on-app-rtcp",
654 G_CALLBACK (on_app_rtcp_cb), &result);
656 /* Push APP buffer with no data */
657 buf = gst_rtcp_buffer_new (1000);
658 fail_unless (gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcp));
659 fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_APP, &packet));
660 gst_rtcp_packet_app_set_subtype (&packet, 21);
661 gst_rtcp_packet_app_set_ssrc (&packet, 0x11111111);
662 gst_rtcp_packet_app_set_name (&packet, "Test");
663 gst_rtcp_buffer_unmap (&rtcp);
665 fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
667 fail_unless_equals_int (21, result.subtype);
668 fail_unless_equals_int (0x11111111, result.ssrc);
669 fail_unless_equals_string ("Test", result.name);
670 fail_unless_equals_pointer (NULL, result.data);
672 g_free (result.name);
674 /* Push APP buffer with data */
675 memset (&result, 0, sizeof (result));
676 buf = gst_rtcp_buffer_new (1000);
677 fail_unless (gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcp));
678 fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_APP, &packet));
679 gst_rtcp_packet_app_set_subtype (&packet, 22);
680 gst_rtcp_packet_app_set_ssrc (&packet, 0x22222222);
681 gst_rtcp_packet_app_set_name (&packet, "Test");
682 gst_rtcp_packet_app_set_data_length (&packet, sizeof (data) / 4);
683 memcpy (gst_rtcp_packet_app_get_data (&packet), data, sizeof (data));
684 gst_rtcp_buffer_unmap (&rtcp);
686 fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
688 fail_unless_equals_int (22, result.subtype);
689 fail_unless_equals_int (0x22222222, result.ssrc);
690 fail_unless_equals_string ("Test", result.name);
691 fail_unless (gst_buffer_memcmp (result.data, 0, data, sizeof (data)) == 0);
693 g_free (result.name);
694 gst_buffer_unref (result.data);
696 session_harness_free (h);
702 stats_test_cb (GObject * object, GParamSpec * spec, gpointer data)
704 guint num_sources = 0;
705 gboolean *cb_called = data;
706 g_assert (*cb_called == FALSE);
708 /* We should be able to get a rtpsession property
709 without introducing the deadlock */
710 g_object_get (object, "num-sources", &num_sources, NULL);
715 GST_START_TEST (test_dont_lock_on_stats)
717 SessionHarness *h = session_harness_new ();
718 gboolean cb_called = FALSE;
720 /* connect to the stats-reporting */
721 g_signal_connect (h->session, "notify::stats",
722 G_CALLBACK (stats_test_cb), &cb_called);
724 /* Push RTP buffer to make sure RTCP-thread have started */
725 fail_unless_equals_int (GST_FLOW_OK,
726 session_harness_send_rtp (h, generate_test_buffer (0, 0xDEADBEEF)));
728 /* crank the RTCP-thread and pull out rtcp, generating a stats-callback */
729 session_harness_crank_clock (h);
730 gst_buffer_unref (session_harness_pull_rtcp (h));
731 fail_unless (cb_called);
733 session_harness_free (h);
739 suspicious_bye_cb (GObject * object, GParamSpec * spec, gpointer data)
741 GValueArray *stats_arr;
742 GstStructure *stats, *internal_stats;
743 gboolean *cb_called = data;
744 gboolean internal = FALSE, sent_bye = TRUE;
748 g_assert (*cb_called == FALSE);
751 g_object_get (object, "stats", &stats, NULL);
753 g_value_get_boxed (gst_structure_get_value (stats, "source-stats"));
754 g_assert (stats_arr != NULL);
755 fail_unless (stats_arr->n_values >= 1);
757 for (i = 0; i < stats_arr->n_values; i++) {
758 internal_stats = g_value_get_boxed (g_value_array_get_nth (stats_arr, i));
759 g_assert (internal_stats != NULL);
761 gst_structure_get (internal_stats,
762 "ssrc", G_TYPE_UINT, &ssrc,
763 "internal", G_TYPE_BOOLEAN, &internal,
764 "received-bye", G_TYPE_BOOLEAN, &sent_bye, NULL);
766 if (ssrc == 0xDEADBEEF) {
767 fail_unless (internal);
768 fail_unless (!sent_bye);
772 fail_unless_equals_int (ssrc, 0xDEADBEEF);
774 gst_structure_free (stats);
778 create_bye_rtcp (guint32 ssrc)
780 GstRTCPPacket packet;
781 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
782 GSocketAddress *saddr;
783 GstBuffer *buffer = gst_rtcp_buffer_new (1000);
785 fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
786 fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_BYE, &packet));
787 gst_rtcp_packet_bye_add_ssrc (&packet, ssrc);
788 gst_rtcp_buffer_unmap (&rtcp);
790 /* Need to add meta to trigger collision detection */
791 saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 3490);
792 gst_buffer_add_net_address_meta (buffer, saddr);
793 g_object_unref (saddr);
797 GST_START_TEST (test_ignore_suspicious_bye)
799 SessionHarness *h = session_harness_new ();
800 gboolean cb_called = FALSE;
802 /* connect to the stats-reporting */
803 g_signal_connect (h->session, "notify::stats",
804 G_CALLBACK (suspicious_bye_cb), &cb_called);
806 /* Push RTP buffer making our internal SSRC=0xDEADBEEF */
807 fail_unless_equals_int (GST_FLOW_OK,
808 session_harness_send_rtp (h, generate_test_buffer (0, 0xDEADBEEF)));
810 /* Receive BYE RTCP referencing our internal SSRC(!?!) (0xDEADBEEF) */
811 fail_unless_equals_int (GST_FLOW_OK,
812 session_harness_recv_rtcp (h, create_bye_rtcp (0xDEADBEEF)));
814 /* "crank" and check the stats */
815 session_harness_crank_clock (h);
816 gst_buffer_unref (session_harness_pull_rtcp (h));
817 fail_unless (cb_called);
819 session_harness_free (h);
825 create_buffer (guint8 * data, gsize size)
827 return gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
828 data, size, 0, size, NULL, NULL);
831 GST_START_TEST (test_receive_regular_pli)
833 SessionHarness *h = session_harness_new ();
837 guint8 rtcp_pkt[] = {
839 0xce, /* Type 206 Application layer feedback */
840 0x00, 0x02, /* Length */
841 0x37, 0x56, 0x93, 0xed, /* Sender SSRC */
842 0x37, 0x56, 0x93, 0xed /* Media SSRC */
845 fail_unless_equals_int (GST_FLOW_OK,
846 session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
848 session_harness_recv_rtcp (h, create_buffer (rtcp_pkt, sizeof (rtcp_pkt)));
849 fail_unless_equals_int (3,
850 gst_harness_upstream_events_received (h->send_rtp_h));
852 /* Remove the first 2 reconfigure events */
853 fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
854 fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
855 gst_event_unref (ev);
856 fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
857 fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
858 gst_event_unref (ev);
860 /* Then pull and check the force key-unit event */
861 fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
862 fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
863 fail_unless (gst_video_event_is_force_key_unit (ev));
864 gst_event_unref (ev);
866 session_harness_free (h);
871 GST_START_TEST (test_receive_pli_no_sender_ssrc)
873 SessionHarness *h = session_harness_new ();
877 guint8 rtcp_pkt[] = {
879 0xce, /* Type 206 Application layer feedback */
880 0x00, 0x02, /* Length */
881 0x00, 0x00, 0x00, 0x00, /* Sender SSRC */
882 0x37, 0x56, 0x93, 0xed /* Media SSRC */
885 fail_unless_equals_int (GST_FLOW_OK,
886 session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
888 session_harness_recv_rtcp (h, create_buffer (rtcp_pkt, sizeof (rtcp_pkt)));
889 fail_unless_equals_int (3,
890 gst_harness_upstream_events_received (h->send_rtp_h));
892 /* Remove the first 2 reconfigure events */
893 fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
894 fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
895 gst_event_unref (ev);
896 fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
897 fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
898 gst_event_unref (ev);
900 /* Then pull and check the force key-unit event */
901 fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
902 fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
903 fail_unless (gst_video_event_is_force_key_unit (ev));
904 gst_event_unref (ev);
906 session_harness_free (h);
912 add_rtcp_sdes_packet (GstBuffer * gstbuf, guint32 ssrc, const char *cname)
914 GstRTCPPacket packet;
915 GstRTCPBuffer buffer = GST_RTCP_BUFFER_INIT;
917 gst_rtcp_buffer_map (gstbuf, GST_MAP_READWRITE, &buffer);
919 fail_unless (gst_rtcp_buffer_add_packet (&buffer, GST_RTCP_TYPE_SDES,
921 fail_unless (gst_rtcp_packet_sdes_add_item (&packet, ssrc) == TRUE);
922 fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME,
923 strlen (cname), (const guint8 *) cname));
925 gst_rtcp_buffer_unmap (&buffer);
928 GST_START_TEST (test_ssrc_collision_when_sending)
930 SessionHarness *h = session_harness_new ();
931 GstBuffer *buf = gst_rtcp_buffer_new (1400);
933 /* Push SDES with identical SSRC as what we will use for sending RTP,
934 establishing this as a non-internal SSRC */
935 add_rtcp_sdes_packet (buf, 0x12345678, "test@foo.bar");
936 session_harness_recv_rtcp (h, buf);
938 /* Push RTP buffer making our internal SSRC=0x12345678 */
939 fail_unless_equals_int (GST_FLOW_OK,
940 session_harness_send_rtp (h, generate_test_buffer (0, 0x12345678)));
942 /* Verify the packet we just sent is not being boomeranged back to us
943 as a received packet! */
944 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
946 /* FIXME: verify a Collision event coming upstream! */
948 session_harness_free (h);
953 GST_START_TEST (test_request_fir)
955 SessionHarness *h = session_harness_new ();
957 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
958 GstRTCPPacket rtcp_packet;
961 /* add FIR-capabilites to our caps */
962 gst_caps_set_simple (h->caps, "rtcp-fb-ccm-fir", G_TYPE_BOOLEAN, TRUE, NULL);
963 /* clear pt-map to removed the cached caps without fir */
964 g_signal_emit_by_name (h->session, "clear-pt-map");
966 g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
968 /* Receive a RTP buffer from the wire from 2 different ssrcs */
969 fail_unless_equals_int (GST_FLOW_OK,
970 session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
971 fail_unless_equals_int (GST_FLOW_OK,
972 session_harness_recv_rtp (h, generate_test_buffer (0, 0x87654321)));
974 /* fix to make the test deterministic: We need to wait for the RTCP-thread
975 to have settled to ensure the key-unit will considered once released */
976 gst_test_clock_wait_for_next_pending_id (h->testclock, NULL);
978 /* request FIR for both SSRCs */
979 session_harness_force_key_unit (h, 0, 0x12345678, TEST_BUF_PT, NULL, NULL);
980 session_harness_force_key_unit (h, 0, 0x87654321, TEST_BUF_PT, NULL, NULL);
982 session_harness_produce_rtcp (h, 1);
983 buf = session_harness_pull_rtcp (h);
985 fail_unless (gst_rtcp_buffer_validate (buf));
986 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
987 fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
988 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
990 /* first a Receiver Report */
991 fail_unless_equals_int (GST_RTCP_TYPE_RR,
992 gst_rtcp_packet_get_type (&rtcp_packet));
993 fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
996 fail_unless_equals_int (GST_RTCP_TYPE_SDES,
997 gst_rtcp_packet_get_type (&rtcp_packet));
998 fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1000 /* and then our FIR */
1001 fail_unless_equals_int (GST_RTCP_TYPE_PSFB,
1002 gst_rtcp_packet_get_type (&rtcp_packet));
1003 fail_unless_equals_int (GST_RTCP_PSFB_TYPE_FIR,
1004 gst_rtcp_packet_fb_get_type (&rtcp_packet));
1006 /* FIR has sender-ssrc as normal, but media-ssrc set to 0, because
1007 it can have multiple media-ssrcs in its fci-data */
1008 fail_unless_equals_int (0xDEADBEEF,
1009 gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
1010 fail_unless_equals_int (0, gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
1011 fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
1013 fail_unless_equals_int (16,
1014 gst_rtcp_packet_fb_get_fci_length (&rtcp_packet) * sizeof (guint32));
1016 /* verify the FIR contains both SSRCs */
1017 fail_unless_equals_int (0x87654321, GST_READ_UINT32_BE (fci_data));
1018 fail_unless_equals_int (1, fci_data[4]);
1019 fail_unless_equals_int (0, fci_data[5]);
1020 fail_unless_equals_int (0, fci_data[6]);
1021 fail_unless_equals_int (0, fci_data[7]);
1024 fail_unless_equals_int (0x12345678, GST_READ_UINT32_BE (fci_data));
1025 fail_unless_equals_int (1, fci_data[4]);
1026 fail_unless_equals_int (0, fci_data[5]);
1027 fail_unless_equals_int (0, fci_data[6]);
1028 fail_unless_equals_int (0, fci_data[7]);
1030 gst_rtcp_buffer_unmap (&rtcp);
1031 gst_buffer_unref (buf);
1032 session_harness_free (h);
1037 GST_START_TEST (test_request_pli)
1039 SessionHarness *h = session_harness_new ();
1041 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1042 GstRTCPPacket rtcp_packet;
1044 /* add PLI-capabilites to our caps */
1045 gst_caps_set_simple (h->caps, "rtcp-fb-nack-pli", G_TYPE_BOOLEAN, TRUE, NULL);
1046 /* clear pt-map to removed the cached caps without PLI */
1047 g_signal_emit_by_name (h->session, "clear-pt-map");
1049 g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1051 /* Receive a RTP buffer from the wire */
1052 fail_unless_equals_int (GST_FLOW_OK,
1053 session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
1055 /* fix to make the test deterministic: We need to wait for the RTCP-thread
1056 to have settled to ensure the key-unit will considered once released */
1057 gst_test_clock_wait_for_next_pending_id (h->testclock, NULL);
1060 session_harness_force_key_unit (h, 0, 0x12345678, TEST_BUF_PT, NULL, NULL);
1062 session_harness_produce_rtcp (h, 1);
1063 buf = session_harness_pull_rtcp (h);
1065 fail_unless (gst_rtcp_buffer_validate (buf));
1066 gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
1067 fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
1068 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
1070 /* first a Receiver Report */
1071 fail_unless_equals_int (GST_RTCP_TYPE_RR,
1072 gst_rtcp_packet_get_type (&rtcp_packet));
1073 fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1076 fail_unless_equals_int (GST_RTCP_TYPE_SDES,
1077 gst_rtcp_packet_get_type (&rtcp_packet));
1078 fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1080 /* and then our PLI */
1081 fail_unless_equals_int (GST_RTCP_TYPE_PSFB,
1082 gst_rtcp_packet_get_type (&rtcp_packet));
1083 fail_unless_equals_int (GST_RTCP_PSFB_TYPE_PLI,
1084 gst_rtcp_packet_fb_get_type (&rtcp_packet));
1086 fail_unless_equals_int (0xDEADBEEF,
1087 gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
1088 fail_unless_equals_int (0x12345678,
1089 gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
1090 fail_unless_equals_int (0, gst_rtcp_packet_fb_get_fci_length (&rtcp_packet));
1092 gst_rtcp_buffer_unmap (&rtcp);
1093 gst_buffer_unref (buf);
1094 session_harness_free (h);
1099 GST_START_TEST (test_illegal_rtcp_fb_packet)
1101 SessionHarness *h = session_harness_new ();
1103 /* Zero length RTCP feedback packet (reduced size) */
1104 const guint8 rtcp_zero_fb_pkt[] = { 0x8f, 0xce, 0x00, 0x00 };
1106 g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1108 buf = gst_buffer_new_and_alloc (sizeof (rtcp_zero_fb_pkt));
1109 gst_buffer_fill (buf, 0, rtcp_zero_fb_pkt, sizeof (rtcp_zero_fb_pkt));
1110 GST_BUFFER_DTS (buf) = GST_BUFFER_PTS (buf) = G_GUINT64_CONSTANT (0);
1112 /* Push the packet, this did previously crash because length of packet was
1113 * never validated. */
1114 fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
1116 session_harness_free (h);
1126 } FeedbackRTCPCallbackData;
1129 feedback_rtcp_cb (GstElement * element, guint fbtype, guint fmt,
1130 guint sender_ssrc, guint media_ssrc, GstBuffer * fci,
1131 FeedbackRTCPCallbackData * cb_data)
1133 g_mutex_lock (cb_data->mutex);
1134 cb_data->fired = TRUE;
1135 g_cond_wait (cb_data->cond, cb_data->mutex);
1136 g_mutex_unlock (cb_data->mutex);
1140 send_feedback_rtcp (SessionHarness * h)
1142 GstRTCPPacket packet;
1143 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1144 GstBuffer *buffer = gst_rtcp_buffer_new (1000);
1146 fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
1147 fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_PSFB, &packet));
1148 gst_rtcp_packet_fb_set_type (&packet, GST_RTCP_PSFB_TYPE_PLI);
1149 gst_rtcp_packet_fb_set_fci_length (&packet, 0);
1150 gst_rtcp_packet_fb_set_media_ssrc (&packet, 0xABE2B0B);
1151 gst_rtcp_packet_fb_set_media_ssrc (&packet, 0xDEADBEEF);
1152 gst_rtcp_buffer_unmap (&rtcp);
1153 fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buffer));
1158 GST_START_TEST (test_feedback_rtcp_race)
1160 SessionHarness *h = session_harness_new ();
1164 FeedbackRTCPCallbackData cb_data;
1165 GThread *send_rtcp_thread;
1167 g_cond_init (&cond);
1168 g_mutex_init (&mutex);
1169 cb_data.cond = &cond;
1170 cb_data.mutex = &mutex;
1171 cb_data.fired = FALSE;
1172 g_signal_connect (h->internal_session, "on-feedback-rtcp",
1173 G_CALLBACK (feedback_rtcp_cb), &cb_data);
1175 /* Push RTP buffer making external source with SSRC=0xDEADBEEF */
1176 fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtp (h,
1177 generate_test_buffer (0, 0xDEADBEEF)));
1179 /* Push feedback RTCP with media SSRC=0xDEADBEEF */
1180 send_rtcp_thread = g_thread_new (NULL, (GThreadFunc) send_feedback_rtcp, h);
1182 /* Waiting for feedback RTCP callback to fire */
1183 while (!cb_data.fired)
1184 g_usleep (G_USEC_PER_SEC / 100);
1186 /* While send_rtcp_thread thread is waiting for our signal
1187 advance the clock by 30sec triggering removal of 0xDEADBEEF,
1188 as if the source was inactive for too long */
1189 session_harness_advance_and_crank (h, GST_SECOND * 30);
1190 gst_buffer_unref (session_harness_pull_rtcp (h));
1192 /* Let send_rtcp_thread finish */
1193 g_mutex_lock (&mutex);
1194 g_cond_signal (&cond);
1195 g_mutex_unlock (&mutex);
1196 g_thread_join (send_rtcp_thread);
1198 session_harness_free (h);
1203 GST_START_TEST (test_dont_send_rtcp_while_idle)
1205 SessionHarness *h = session_harness_new ();
1207 /* verify the RTCP thread has not started */
1208 fail_unless_equals_int (0, gst_test_clock_peek_id_count (h->testclock));
1209 /* and that no RTCP has been pushed */
1210 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->rtcp_h));
1212 session_harness_free (h);
1217 GST_START_TEST (test_send_rtcp_when_signalled)
1219 SessionHarness *h = session_harness_new ();
1222 /* verify the RTCP thread has not started */
1223 fail_unless_equals_int (0, gst_test_clock_peek_id_count (h->testclock));
1224 /* and that no RTCP has been pushed */
1225 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->rtcp_h));
1227 /* then ask explicitly to send RTCP */
1228 g_signal_emit_by_name (h->internal_session,
1229 "send-rtcp-full", GST_SECOND, &ret);
1230 /* this is FALSE due to no next RTCP check time */
1231 fail_unless (ret == FALSE);
1233 /* "crank" and verify RTCP now was sent */
1234 session_harness_crank_clock (h);
1235 gst_buffer_unref (session_harness_pull_rtcp (h));
1237 session_harness_free (h);
1243 validate_sdes_priv (GstBuffer * buf, const char *name_ref, const char *value)
1245 GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1248 fail_unless (gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp));
1250 fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &pkt));
1253 if (gst_rtcp_packet_get_type (&pkt) == GST_RTCP_TYPE_SDES) {
1254 fail_unless (gst_rtcp_packet_sdes_first_entry (&pkt));
1257 GstRTCPSDESType type;
1261 fail_unless (gst_rtcp_packet_sdes_get_entry (&pkt, &type, &len, &data));
1263 if (type == GST_RTCP_SDES_PRIV) {
1264 char *name = g_strndup ((const gchar *) &data[1], data[0]);
1266 data += data[0] + 1;
1268 fail_unless_equals_int (len, strlen (value));
1269 fail_unless (!strncmp (value, (char *) data, len));
1270 fail_unless_equals_string (name, name_ref);
1274 } while (gst_rtcp_packet_sdes_next_entry (&pkt));
1276 g_assert_not_reached ();
1278 } while (gst_rtcp_packet_move_to_next (&pkt));
1280 g_assert_not_reached ();
1284 fail_unless (gst_rtcp_buffer_unmap (&rtcp));
1288 GST_START_TEST (test_change_sent_sdes)
1290 SessionHarness *h = session_harness_new ();
1296 /* verify the RTCP thread has not started */
1297 fail_unless_equals_int (0, gst_test_clock_peek_id_count (h->testclock));
1298 /* and that no RTCP has been pushed */
1299 fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->rtcp_h));
1301 s = gst_structure_new ("application/x-rtp-source-sdes",
1302 "other", G_TYPE_STRING, "first", NULL);
1303 g_object_set (h->internal_session, "sdes", s, NULL);
1304 gst_structure_free (s);
1306 /* then ask explicitly to send RTCP */
1307 g_signal_emit_by_name (h->internal_session,
1308 "send-rtcp-full", GST_SECOND, &ret);
1309 /* this is FALSE due to no next RTCP check time */
1310 fail_unless (ret == FALSE);
1312 /* "crank" and verify RTCP now was sent */
1313 session_harness_crank_clock (h);
1314 buf = session_harness_pull_rtcp (h);
1316 validate_sdes_priv (buf, "other", "first");
1317 gst_buffer_unref (buf);
1319 /* Change the SDES */
1320 s = gst_structure_new ("application/x-rtp-source-sdes",
1321 "other", G_TYPE_STRING, "second", NULL);
1322 g_object_set (h->internal_session, "sdes", s, NULL);
1323 gst_structure_free (s);
1325 /* Send an RTP packet */
1326 buf = generate_test_buffer (22, 10000);
1327 res = session_harness_send_rtp (h, buf);
1328 fail_unless_equals_int (GST_FLOW_OK, res);
1330 /* "crank" enough to ensure a RTCP packet has been produced ! */
1331 session_harness_crank_clock (h);
1332 session_harness_crank_clock (h);
1333 session_harness_crank_clock (h);
1334 session_harness_crank_clock (h);
1335 session_harness_crank_clock (h);
1336 session_harness_crank_clock (h);
1337 session_harness_crank_clock (h);
1338 session_harness_crank_clock (h);
1339 session_harness_crank_clock (h);
1340 session_harness_crank_clock (h);
1342 /* and verify RTCP now was sent with new SDES */
1343 buf = session_harness_pull_rtcp (h);
1344 validate_sdes_priv (buf, "other", "second");
1345 gst_buffer_unref (buf);
1347 session_harness_free (h);
1353 rtpsession_suite (void)
1355 Suite *s = suite_create ("rtpsession");
1356 TCase *tc_chain = tcase_create ("general");
1358 suite_add_tcase (s, tc_chain);
1359 tcase_add_test (tc_chain, test_multiple_ssrc_rr);
1360 tcase_add_test (tc_chain, test_multiple_senders_roundrobin_rbs);
1361 tcase_add_test (tc_chain, test_no_rbs_for_internal_senders);
1362 tcase_add_test (tc_chain, test_internal_sources_timeout);
1363 tcase_add_test (tc_chain, test_receive_rtcp_app_packet);
1364 tcase_add_test (tc_chain, test_dont_lock_on_stats);
1365 tcase_add_test (tc_chain, test_ignore_suspicious_bye);
1366 tcase_add_test (tc_chain, test_ssrc_collision_when_sending);
1367 tcase_add_test (tc_chain, test_request_fir);
1368 tcase_add_test (tc_chain, test_request_pli);
1369 tcase_add_test (tc_chain, test_illegal_rtcp_fb_packet);
1370 tcase_add_test (tc_chain, test_feedback_rtcp_race);
1371 tcase_add_test (tc_chain, test_receive_regular_pli);
1372 tcase_add_test (tc_chain, test_receive_pli_no_sender_ssrc);
1373 tcase_add_test (tc_chain, test_dont_send_rtcp_while_idle);
1374 tcase_add_test (tc_chain, test_send_rtcp_when_signalled);
1375 tcase_add_test (tc_chain, test_change_sent_sdes);
1379 GST_CHECK_MAIN (rtpsession);