ebabc8fc498c9ff3b5a5e968e3acae1bdfc9ae6d
[platform/upstream/gstreamer.git] / tests / check / elements / rtpsession.c
1 /* GStreamer
2  *
3  * unit test for gstrtpsession
4  *
5  * Copyright (C) <2009> Wim Taymans <wim.taymans@gmail.com>
6  * Copyright (C) 2013 Collabora Ltd.
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 #define GLIB_DISABLE_DEPRECATION_WARNINGS
24
25 #include <gst/check/gstharness.h>
26 #include <gst/check/gstcheck.h>
27 #include <gst/check/gsttestclock.h>
28 #include <gst/check/gstharness.h>
29
30 #include <gst/rtp/gstrtpbuffer.h>
31 #include <gst/rtp/gstrtcpbuffer.h>
32 #include <gst/net/gstnetaddressmeta.h>
33 #include <gst/video/video.h>
34
35 #define TEST_BUF_CLOCK_RATE 8000
36 #define TEST_BUF_PT 0
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)
42
43 static GstCaps *
44 generate_caps (void)
45 {
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);
49 }
50
51 static GstBuffer *
52 generate_test_buffer_full (GstClockTime dts,
53     guint seq_num, guint32 rtp_ts, guint ssrc)
54 {
55   GstBuffer *buf;
56   guint8 *payload;
57   guint i;
58   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
59
60   buf = gst_rtp_buffer_new_allocate (TEST_BUF_SIZE, 0, 0);
61   GST_BUFFER_DTS (buf) = dts;
62
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);
68
69   payload = gst_rtp_buffer_get_payload (&rtp);
70   for (i = 0; i < TEST_BUF_SIZE; i++)
71     payload[i] = 0xff;
72
73   gst_rtp_buffer_unmap (&rtp);
74
75   return buf;
76 }
77
78 static GstBuffer *
79 generate_test_buffer (guint seq_num, guint ssrc)
80 {
81   return generate_test_buffer_full (seq_num * TEST_BUF_DURATION,
82       seq_num, seq_num * TEST_RTP_TS_DURATION, ssrc);
83 }
84
85 typedef struct
86 {
87   GstHarness *send_rtp_h;
88   GstHarness *recv_rtp_h;
89   GstHarness *rtcp_h;
90
91   GstElement *session;
92   GObject *internal_session;
93   GstTestClock *testclock;
94   GstCaps *caps;
95 } SessionHarness;
96
97 static GstCaps *
98 _pt_map_requested (GstElement * element, guint pt, gpointer data)
99 {
100   SessionHarness *h = data;
101   return gst_caps_copy (h->caps);
102 }
103
104 static SessionHarness *
105 session_harness_new (void)
106 {
107   SessionHarness *h = g_new0 (SessionHarness, 1);
108   h->caps = generate_caps ();
109
110   h->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
111   gst_system_clock_set_default (GST_CLOCK_CAST (h->testclock));
112
113   h->session = gst_element_factory_make ("rtpsession", NULL);
114   gst_element_set_clock (h->session, GST_CLOCK_CAST (h->testclock));
115
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));
119
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));
123
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");
127
128   g_signal_connect (h->session, "request-pt-map",
129       (GCallback) _pt_map_requested, h);
130
131   g_object_get (h->session, "internal-session", &h->internal_session, NULL);
132
133   return h;
134 }
135
136 static void
137 session_harness_free (SessionHarness * h)
138 {
139   gst_system_clock_set_default (NULL);
140
141   gst_caps_unref (h->caps);
142   gst_object_unref (h->testclock);
143
144   gst_harness_teardown (h->rtcp_h);
145   gst_harness_teardown (h->recv_rtp_h);
146   gst_harness_teardown (h->send_rtp_h);
147
148   g_object_unref (h->internal_session);
149   gst_object_unref (h->session);
150   g_free (h);
151 }
152
153 static GstFlowReturn
154 session_harness_send_rtp (SessionHarness * h, GstBuffer * buf)
155 {
156   return gst_harness_push (h->send_rtp_h, buf);
157 }
158
159 static GstFlowReturn
160 session_harness_recv_rtp (SessionHarness * h, GstBuffer * buf)
161 {
162   return gst_harness_push (h->recv_rtp_h, buf);
163 }
164
165 static GstFlowReturn
166 session_harness_recv_rtcp (SessionHarness * h, GstBuffer * buf)
167 {
168   return gst_harness_push (h->rtcp_h, buf);
169 }
170
171 static GstBuffer *
172 session_harness_pull_rtcp (SessionHarness * h)
173 {
174   return gst_harness_pull (h->rtcp_h);
175 }
176
177 static void
178 session_harness_crank_clock (SessionHarness * h)
179 {
180   gst_test_clock_crank (h->testclock);
181 }
182
183 static gboolean
184 session_harness_advance_and_crank (SessionHarness * h, GstClockTime delta)
185 {
186   GstClockID res, pending;
187   gboolean result;
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);
191   if (res == pending)
192     result = TRUE;
193   else
194     result = FALSE;
195   if (res)
196     gst_clock_id_unref (res);
197   gst_clock_id_unref (pending);
198   return result;
199 }
200
201 static void
202 session_harness_produce_rtcp (SessionHarness * h, gint num_rtcp_packets)
203 {
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);
208 }
209
210 static void
211 session_harness_force_key_unit (SessionHarness * h,
212     guint count, guint ssrc, guint payload, gint * reqid, guint64 * sfr)
213 {
214   GstClockTime running_time = GST_CLOCK_TIME_NONE;
215   gboolean all_headers = TRUE;
216
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,
223       NULL);
224
225   if (reqid)
226     gst_structure_set (s, "reqid", G_TYPE_INT, *reqid, NULL);
227   if (sfr)
228     gst_structure_set (s, "sfr", G_TYPE_UINT64, *sfr, NULL);
229
230   gst_harness_push_upstream_event (h->recv_rtp_h,
231       gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s));
232 }
233
234 GST_START_TEST (test_multiple_ssrc_rr)
235 {
236   SessionHarness *h = session_harness_new ();
237   GstFlowReturn res;
238   GstBuffer *in_buf, *out_buf;
239   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
240   GstRTCPPacket rtcp_packet;
241   gint i, j;
242   guint ssrc_match;
243
244   guint ssrcs[] = {
245     0x01BADBAD,
246     0xDEADBEEF,
247   };
248
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);
255     }
256   }
257
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);
261
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));
269
270   fail_unless_equals_int (G_N_ELEMENTS (ssrcs),
271       gst_rtcp_packet_get_rb_count (&rtcp_packet));
272
273   ssrc_match = 0;
274   for (i = 0; i < G_N_ELEMENTS (ssrcs); i++) {
275     guint32 ssrc;
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)
280         ssrc_match++;
281     }
282   }
283   fail_unless_equals_int (G_N_ELEMENTS (ssrcs), ssrc_match);
284
285   gst_rtcp_buffer_unmap (&rtcp);
286   gst_buffer_unref (out_buf);
287
288   session_harness_free (h);
289 }
290
291 GST_END_TEST;
292
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)
297 {
298   SessionHarness *h = session_harness_new ();
299   GstFlowReturn res;
300   GstBuffer *buf;
301   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
302   GstRTCPPacket rtcp_packet;
303   gint i, j, k;
304   guint32 ssrc;
305   GHashTable *rb_ssrcs, *tmp_set;
306
307   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
308
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);
316       }
317     }
318   }
319
320   rb_ssrcs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
321       (GDestroyNotify) g_hash_table_unref);
322
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);
327
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));
332
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));
337
338     ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
339     fail_unless_equals_int (0xDEADBEEF, ssrc);
340
341     /* inspect the RBs */
342     fail_unless_equals_int (expected_rb_count,
343         gst_rtcp_packet_get_rb_count (&rtcp_packet));
344
345     if (i == 0) {
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);
348     } else {
349       tmp_set = g_hash_table_lookup (rb_ssrcs, GUINT_TO_POINTER (ssrc));
350       g_assert (tmp_set);
351     }
352
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));
359     }
360
361     gst_rtcp_buffer_unmap (&rtcp);
362     gst_buffer_unref (buf);
363   }
364
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));
368   g_assert (tmp_set);
369   fail_unless_equals_int (35, g_hash_table_size (tmp_set));
370
371   g_hash_table_unref (rb_ssrcs);
372   session_harness_free (h);
373 }
374
375 GST_END_TEST;
376
377 GST_START_TEST (test_no_rbs_for_internal_senders)
378 {
379   SessionHarness *h = session_harness_new ();
380   GstFlowReturn res;
381   GstBuffer *buf;
382   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
383   GstRTCPPacket rtcp_packet;
384   gint i, j, k;
385   guint32 ssrc;
386   GHashTable *sr_ssrcs;
387   GHashTable *rb_ssrcs, *tmp_set;
388
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);
395     }
396   }
397
398   /* crank the RTCP pad thread */
399   session_harness_crank_clock (h);
400
401   sr_ssrcs = g_hash_table_new (g_direct_hash, g_direct_equal);
402
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));
408
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));
413
414     gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL,
415         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));
419
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));
422
423     gst_rtcp_buffer_unmap (&rtcp);
424     gst_buffer_unref (buf);
425   }
426
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);
430
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);
437     }
438   }
439
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);
443
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));
450
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));
455
456     gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL,
457         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));
461
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));
464
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);
467
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));
474     }
475
476     gst_rtcp_buffer_unmap (&rtcp);
477     gst_buffer_unref (buf);
478   }
479
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));
485     g_assert (tmp_set);
486     fail_unless_equals_int (2, g_hash_table_size (tmp_set));
487   }
488
489   g_hash_table_unref (rb_ssrcs);
490   g_hash_table_unref (sr_ssrcs);
491
492   session_harness_free (h);
493 }
494
495 GST_END_TEST;
496
497 GST_START_TEST (test_internal_sources_timeout)
498 {
499   SessionHarness *h = session_harness_new ();
500   guint internal_ssrc;
501   guint32 ssrc;
502   GstBuffer *buf;
503   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
504   GstRTCPPacket rtcp_packet;
505   GstRTCPType rtcp_type;
506   GstFlowReturn res;
507   gint i, j;
508   GstCaps *caps;
509   gboolean seen_bye;
510
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);
514
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);
519   }
520
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);
525
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);
536
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);
541
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);
546   }
547
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);
552
553   /* verify SR and RR */
554   j = 0;
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);
563
564     if (rtcp_type == GST_RTCP_TYPE_SR) {
565       gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL, NULL,
566           NULL);
567       fail_unless_equals_int (internal_ssrc, ssrc);
568       fail_unless_equals_int (0x01BADBAD, ssrc);
569       j |= 0x1;
570     } else if (rtcp_type == GST_RTCP_TYPE_RR) {
571       ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
572       if (internal_ssrc != ssrc)
573         j |= 0x2;
574     }
575     gst_rtcp_buffer_unmap (&rtcp);
576     gst_buffer_unref (buf);
577   }
578   fail_unless_equals_int (0x3, j);      /* verify we got both SR and RR */
579
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));
583
584   /* verify BYE and RR */
585   j = 0;
586   seen_bye = FALSE;
587   while (!seen_bye) {
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);
595
596     if (rtcp_type == GST_RTCP_TYPE_RR) {
597       ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
598       if (ssrc == 0x01BADBAD) {
599         j |= 0x1;
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) {
604         j |= 0x2;
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));
612           seen_bye = TRUE;
613         }
614       }
615     }
616     gst_rtcp_buffer_unmap (&rtcp);
617     gst_buffer_unref (buf);
618   }
619   fail_unless_equals_int (0x3, j);      /* verify we got both BYE and RR */
620
621   session_harness_free (h);
622 }
623
624 GST_END_TEST;
625
626 typedef struct
627 {
628   guint8 subtype;
629   guint32 ssrc;
630   gchar *name;
631   GstBuffer *data;
632 } RTCPAppResult;
633
634 static void
635 on_app_rtcp_cb (GObject * session, guint subtype, guint ssrc,
636     const gchar * name, GstBuffer * data, RTCPAppResult * result)
637 {
638   result->subtype = subtype;
639   result->ssrc = ssrc;
640   result->name = g_strdup (name);
641   result->data = data ? gst_buffer_ref (data) : NULL;
642 }
643
644 GST_START_TEST (test_receive_rtcp_app_packet)
645 {
646   SessionHarness *h = session_harness_new ();
647   GstBuffer *buf;
648   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
649   GstRTCPPacket packet;
650   RTCPAppResult result = { 0 };
651   guint8 data[] = { 0x11, 0x22, 0x33, 0x44 };
652
653   g_signal_connect (h->internal_session, "on-app-rtcp",
654       G_CALLBACK (on_app_rtcp_cb), &result);
655
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);
664
665   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
666
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);
671
672   g_free (result.name);
673
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);
685
686   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
687
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);
692
693   g_free (result.name);
694   gst_buffer_unref (result.data);
695
696   session_harness_free (h);
697 }
698
699 GST_END_TEST;
700
701 static void
702 stats_test_cb (GObject * object, GParamSpec * spec, gpointer data)
703 {
704   guint num_sources = 0;
705   gboolean *cb_called = data;
706   g_assert (*cb_called == FALSE);
707
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);
711
712   *cb_called = TRUE;
713 }
714
715 GST_START_TEST (test_dont_lock_on_stats)
716 {
717   SessionHarness *h = session_harness_new ();
718   gboolean cb_called = FALSE;
719
720   /* connect to the stats-reporting */
721   g_signal_connect (h->session, "notify::stats",
722       G_CALLBACK (stats_test_cb), &cb_called);
723
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)));
727
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);
732
733   session_harness_free (h);
734 }
735
736 GST_END_TEST;
737
738 static void
739 suspicious_bye_cb (GObject * object, GParamSpec * spec, gpointer data)
740 {
741   GValueArray *stats_arr;
742   GstStructure *stats, *internal_stats;
743   gboolean *cb_called = data;
744   gboolean internal = FALSE, sent_bye = TRUE;
745   guint ssrc = 0;
746   guint i;
747
748   g_assert (*cb_called == FALSE);
749   *cb_called = TRUE;
750
751   g_object_get (object, "stats", &stats, NULL);
752   stats_arr =
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);
756
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);
760
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);
765
766     if (ssrc == 0xDEADBEEF) {
767       fail_unless (internal);
768       fail_unless (!sent_bye);
769       break;
770     }
771   }
772   fail_unless_equals_int (ssrc, 0xDEADBEEF);
773
774   gst_structure_free (stats);
775 }
776
777 static GstBuffer *
778 create_bye_rtcp (guint32 ssrc)
779 {
780   GstRTCPPacket packet;
781   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
782   GSocketAddress *saddr;
783   GstBuffer *buffer = gst_rtcp_buffer_new (1000);
784
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);
789
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);
794   return buffer;
795 }
796
797 GST_START_TEST (test_ignore_suspicious_bye)
798 {
799   SessionHarness *h = session_harness_new ();
800   gboolean cb_called = FALSE;
801
802   /* connect to the stats-reporting */
803   g_signal_connect (h->session, "notify::stats",
804       G_CALLBACK (suspicious_bye_cb), &cb_called);
805
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)));
809
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)));
813
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);
818
819   session_harness_free (h);
820 }
821
822 GST_END_TEST;
823
824 static GstBuffer *
825 create_buffer (guint8 * data, gsize size)
826 {
827   return gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
828       data, size, 0, size, NULL, NULL);
829 }
830
831 GST_START_TEST (test_receive_regular_pli)
832 {
833   SessionHarness *h = session_harness_new ();
834   GstEvent *ev;
835
836   /* PLI packet */
837   guint8 rtcp_pkt[] = {
838     0x81,                       /* PLI */
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 */
843   };
844
845   fail_unless_equals_int (GST_FLOW_OK,
846       session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
847
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));
851
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);
859
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);
865
866   session_harness_free (h);
867 }
868
869 GST_END_TEST;
870
871 GST_START_TEST (test_receive_pli_no_sender_ssrc)
872 {
873   SessionHarness *h = session_harness_new ();
874   GstEvent *ev;
875
876   /* PLI packet */
877   guint8 rtcp_pkt[] = {
878     0x81,                       /* PLI */
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 */
883   };
884
885   fail_unless_equals_int (GST_FLOW_OK,
886       session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
887
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));
891
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);
899
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);
905
906   session_harness_free (h);
907 }
908
909 GST_END_TEST;
910
911 static void
912 add_rtcp_sdes_packet (GstBuffer * gstbuf, guint32 ssrc, const char *cname)
913 {
914   GstRTCPPacket packet;
915   GstRTCPBuffer buffer = GST_RTCP_BUFFER_INIT;
916
917   gst_rtcp_buffer_map (gstbuf, GST_MAP_READWRITE, &buffer);
918
919   fail_unless (gst_rtcp_buffer_add_packet (&buffer, GST_RTCP_TYPE_SDES,
920           &packet) == TRUE);
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));
924
925   gst_rtcp_buffer_unmap (&buffer);
926 }
927
928 GST_START_TEST (test_ssrc_collision_when_sending)
929 {
930   SessionHarness *h = session_harness_new ();
931   GstBuffer *buf = gst_rtcp_buffer_new (1400);
932
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);
937
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)));
941
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));
945
946   /* FIXME: verify a Collision event coming upstream! */
947
948   session_harness_free (h);
949 }
950
951 GST_END_TEST;
952
953 GST_START_TEST (test_request_fir)
954 {
955   SessionHarness *h = session_harness_new ();
956   GstBuffer *buf;
957   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
958   GstRTCPPacket rtcp_packet;
959   guint8 *fci_data;
960
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");
965
966   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
967
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)));
973
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);
977
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);
981
982   session_harness_produce_rtcp (h, 1);
983   buf = session_harness_pull_rtcp (h);
984
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));
989
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));
994
995   /* then a SDES */
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));
999
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));
1005
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);
1012
1013   fail_unless_equals_int (16,
1014       gst_rtcp_packet_fb_get_fci_length (&rtcp_packet) * sizeof (guint32));
1015
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]);
1022   fci_data += 8;
1023
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]);
1029
1030   gst_rtcp_buffer_unmap (&rtcp);
1031   gst_buffer_unref (buf);
1032   session_harness_free (h);
1033 }
1034
1035 GST_END_TEST;
1036
1037 GST_START_TEST (test_request_pli)
1038 {
1039   SessionHarness *h = session_harness_new ();
1040   GstBuffer *buf;
1041   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1042   GstRTCPPacket rtcp_packet;
1043
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");
1048
1049   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1050
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)));
1054
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);
1058
1059   /* request PLI */
1060   session_harness_force_key_unit (h, 0, 0x12345678, TEST_BUF_PT, NULL, NULL);
1061
1062   session_harness_produce_rtcp (h, 1);
1063   buf = session_harness_pull_rtcp (h);
1064
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));
1069
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));
1074
1075   /* then a SDES */
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));
1079
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));
1085
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));
1091
1092   gst_rtcp_buffer_unmap (&rtcp);
1093   gst_buffer_unref (buf);
1094   session_harness_free (h);
1095 }
1096
1097 GST_END_TEST;
1098
1099 GST_START_TEST (test_illegal_rtcp_fb_packet)
1100 {
1101   SessionHarness *h = session_harness_new ();
1102   GstBuffer *buf;
1103   /* Zero length RTCP feedback packet (reduced size) */
1104   const guint8 rtcp_zero_fb_pkt[] = { 0x8f, 0xce, 0x00, 0x00 };
1105
1106   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1107
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);
1111
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));
1115
1116   session_harness_free (h);
1117 }
1118
1119 GST_END_TEST;
1120
1121 typedef struct
1122 {
1123   GCond *cond;
1124   GMutex *mutex;
1125   gboolean fired;
1126 } FeedbackRTCPCallbackData;
1127
1128 static void
1129 feedback_rtcp_cb (GstElement * element, guint fbtype, guint fmt,
1130     guint sender_ssrc, guint media_ssrc, GstBuffer * fci,
1131     FeedbackRTCPCallbackData * cb_data)
1132 {
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);
1137 }
1138
1139 static void *
1140 send_feedback_rtcp (SessionHarness * h)
1141 {
1142   GstRTCPPacket packet;
1143   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1144   GstBuffer *buffer = gst_rtcp_buffer_new (1000);
1145
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));
1154
1155   return NULL;
1156 }
1157
1158 GST_START_TEST (test_feedback_rtcp_race)
1159 {
1160   SessionHarness *h = session_harness_new ();
1161
1162   GCond cond;
1163   GMutex mutex;
1164   FeedbackRTCPCallbackData cb_data;
1165   GThread *send_rtcp_thread;
1166
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);
1174
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)));
1178
1179   /* Push feedback RTCP with media SSRC=0xDEADBEEF */
1180   send_rtcp_thread = g_thread_new (NULL, (GThreadFunc) send_feedback_rtcp, h);
1181
1182   /* Waiting for feedback RTCP callback to fire */
1183   while (!cb_data.fired)
1184     g_usleep (G_USEC_PER_SEC / 100);
1185
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));
1191
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);
1197
1198   session_harness_free (h);
1199 }
1200
1201 GST_END_TEST;
1202
1203 GST_START_TEST (test_dont_send_rtcp_while_idle)
1204 {
1205   SessionHarness *h = session_harness_new ();
1206
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));
1211
1212   session_harness_free (h);
1213 }
1214
1215 GST_END_TEST;
1216
1217 GST_START_TEST (test_send_rtcp_when_signalled)
1218 {
1219   SessionHarness *h = session_harness_new ();
1220   gboolean ret;
1221
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));
1226
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);
1232
1233   /* "crank" and verify RTCP now was sent */
1234   session_harness_crank_clock (h);
1235   gst_buffer_unref (session_harness_pull_rtcp (h));
1236
1237   session_harness_free (h);
1238 }
1239
1240 GST_END_TEST;
1241
1242 static void
1243 validate_sdes_priv (GstBuffer * buf, const char *name_ref, const char *value)
1244 {
1245   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1246   GstRTCPPacket pkt;
1247
1248   fail_unless (gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp));
1249
1250   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &pkt));
1251
1252   do {
1253     if (gst_rtcp_packet_get_type (&pkt) == GST_RTCP_TYPE_SDES) {
1254       fail_unless (gst_rtcp_packet_sdes_first_entry (&pkt));
1255
1256       do {
1257         GstRTCPSDESType type;
1258         guint8 len;
1259         guint8 *data;
1260
1261         fail_unless (gst_rtcp_packet_sdes_get_entry (&pkt, &type, &len, &data));
1262
1263         if (type == GST_RTCP_SDES_PRIV) {
1264           char *name = g_strndup ((const gchar *) &data[1], data[0]);
1265           len -= data[0] + 1;
1266           data += data[0] + 1;
1267
1268           fail_unless_equals_int (len, strlen (value));
1269           fail_unless (!strncmp (value, (char *) data, len));
1270           fail_unless_equals_string (name, name_ref);
1271           g_free (name);
1272           goto sdes_done;
1273         }
1274       } while (gst_rtcp_packet_sdes_next_entry (&pkt));
1275
1276       g_assert_not_reached ();
1277     }
1278   } while (gst_rtcp_packet_move_to_next (&pkt));
1279
1280   g_assert_not_reached ();
1281
1282 sdes_done:
1283
1284   fail_unless (gst_rtcp_buffer_unmap (&rtcp));
1285
1286 }
1287
1288 GST_START_TEST (test_change_sent_sdes)
1289 {
1290   SessionHarness *h = session_harness_new ();
1291   GstStructure *s;
1292   GstBuffer *buf;
1293   gboolean ret;
1294   GstFlowReturn res;
1295
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));
1300
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);
1305
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);
1311
1312   /* "crank" and verify RTCP now was sent */
1313   session_harness_crank_clock (h);
1314   buf = session_harness_pull_rtcp (h);
1315   fail_unless (buf);
1316   validate_sdes_priv (buf, "other", "first");
1317   gst_buffer_unref (buf);
1318
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);
1324
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);
1329
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);
1341
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);
1346
1347   session_harness_free (h);
1348 }
1349
1350 GST_END_TEST;
1351
1352 static Suite *
1353 rtpsession_suite (void)
1354 {
1355   Suite *s = suite_create ("rtpsession");
1356   TCase *tc_chain = tcase_create ("general");
1357
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);
1376   return s;
1377 }
1378
1379 GST_CHECK_MAIN (rtpsession);