• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_BPS 512000
41 #define TEST_BUF_SIZE (TEST_BUF_BPS * TEST_BUF_MS / (1000 * 8))
42 #define TEST_RTP_TS_DURATION (TEST_BUF_CLOCK_RATE * TEST_BUF_MS / 1000)
43 
44 #define TEST_TWCC_EXT_ID 5
45 #define TWCC_EXTMAP_STR "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
46 
47 static GstCaps *
generate_caps(void)48 generate_caps (void)
49 {
50   return gst_caps_new_simple ("application/x-rtp",
51       "clock-rate", G_TYPE_INT, TEST_BUF_CLOCK_RATE,
52       "payload", G_TYPE_INT, TEST_BUF_PT, NULL);
53 }
54 
55 static GstBuffer *
generate_test_buffer_full(GstClockTime ts,guint seqnum,guint32 rtp_ts,guint ssrc,gboolean marker_bit,guint8 payload_type,guint8 twcc_ext_id,guint16 twcc_seqnum)56 generate_test_buffer_full (GstClockTime ts,
57     guint seqnum, guint32 rtp_ts, guint ssrc,
58     gboolean marker_bit, guint8 payload_type, guint8 twcc_ext_id,
59     guint16 twcc_seqnum)
60 {
61   GstBuffer *buf;
62   guint8 *payload;
63   guint i;
64   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
65 
66   buf = gst_rtp_buffer_new_allocate (TEST_BUF_SIZE, 0, 0);
67   GST_BUFFER_PTS (buf) = ts;
68   GST_BUFFER_DTS (buf) = ts;
69 
70   gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp);
71   gst_rtp_buffer_set_payload_type (&rtp, payload_type);
72   gst_rtp_buffer_set_seq (&rtp, seqnum);
73   gst_rtp_buffer_set_timestamp (&rtp, rtp_ts);
74   gst_rtp_buffer_set_ssrc (&rtp, ssrc);
75   gst_rtp_buffer_set_marker (&rtp, marker_bit);
76 
77   payload = gst_rtp_buffer_get_payload (&rtp);
78   for (i = 0; i < TEST_BUF_SIZE; i++)
79     payload[i] = 0xff;
80 
81   if (twcc_ext_id > 0) {
82     guint8 twcc_seqnum_be[2];
83     GST_WRITE_UINT16_BE (twcc_seqnum_be, twcc_seqnum);
84     gst_rtp_buffer_add_extension_onebyte_header (&rtp, twcc_ext_id,
85         twcc_seqnum_be, sizeof (twcc_seqnum_be));
86   }
87 
88   gst_rtp_buffer_unmap (&rtp);
89 
90   return buf;
91 }
92 
93 static GstBuffer *
generate_test_buffer(guint seqnum,guint ssrc)94 generate_test_buffer (guint seqnum, guint ssrc)
95 {
96   return generate_test_buffer_full (seqnum * TEST_BUF_DURATION,
97       seqnum, seqnum * TEST_RTP_TS_DURATION, ssrc, FALSE, TEST_BUF_PT, 0, 0);
98 }
99 
100 static GstBuffer *
generate_twcc_recv_buffer(guint seqnum,GstClockTime arrival_time,gboolean marker_bit)101 generate_twcc_recv_buffer (guint seqnum,
102     GstClockTime arrival_time, gboolean marker_bit)
103 {
104   return generate_test_buffer_full (arrival_time, seqnum,
105       seqnum * TEST_RTP_TS_DURATION, TEST_BUF_SSRC, marker_bit, TEST_BUF_PT,
106       TEST_TWCC_EXT_ID, seqnum);
107 }
108 
109 static GstBuffer *
generate_twcc_send_buffer_full(guint seqnum,gboolean marker_bit,guint ssrc,guint8 payload_type)110 generate_twcc_send_buffer_full (guint seqnum, gboolean marker_bit,
111     guint ssrc, guint8 payload_type)
112 {
113   return generate_test_buffer_full (seqnum * TEST_BUF_DURATION,
114       seqnum, seqnum * TEST_RTP_TS_DURATION, ssrc, marker_bit,
115       payload_type, TEST_TWCC_EXT_ID, seqnum);
116 }
117 
118 static GstBuffer *
generate_twcc_send_buffer(guint seqnum,gboolean marker_bit)119 generate_twcc_send_buffer (guint seqnum, gboolean marker_bit)
120 {
121   return generate_twcc_send_buffer_full (seqnum, marker_bit, TEST_BUF_SSRC,
122       TEST_BUF_PT);
123 }
124 
125 typedef struct
126 {
127   GstHarness *send_rtp_h;
128   GstHarness *recv_rtp_h;
129   GstHarness *rtcp_h;
130 
131   GstElement *session;
132   GObject *internal_session;
133   GstTestClock *testclock;
134   GstCaps *caps;
135 
136   gboolean running;
137   GMutex lock;
138   GstStructure *last_twcc_stats;
139 } SessionHarness;
140 
141 static GstCaps *
_pt_map_requested(GstElement * element,guint pt,gpointer data)142 _pt_map_requested (GstElement * element, guint pt, gpointer data)
143 {
144   SessionHarness *h = data;
145   return gst_caps_copy (h->caps);
146 }
147 
148 static void
_notify_twcc_stats(GParamSpec * spec G_GNUC_UNUSED,GObject * object G_GNUC_UNUSED,gpointer data)149 _notify_twcc_stats (GParamSpec * spec G_GNUC_UNUSED,
150     GObject * object G_GNUC_UNUSED, gpointer data)
151 {
152   SessionHarness *h = data;
153   GstStructure *stats;
154   g_object_get (h->session, "twcc-stats", &stats, NULL);
155 
156   g_mutex_lock (&h->lock);
157   if (h->last_twcc_stats)
158     gst_structure_free (h->last_twcc_stats);
159   h->last_twcc_stats = stats;
160   g_mutex_unlock (&h->lock);
161 }
162 
163 static GstStructure *
session_harness_get_last_twcc_stats(SessionHarness * h)164 session_harness_get_last_twcc_stats (SessionHarness * h)
165 {
166   GstStructure *ret = NULL;
167   g_mutex_lock (&h->lock);
168   if (h->last_twcc_stats)
169     ret = gst_structure_copy (h->last_twcc_stats);
170   g_mutex_unlock (&h->lock);
171   return ret;
172 }
173 
174 static SessionHarness *
session_harness_new(void)175 session_harness_new (void)
176 {
177   SessionHarness *h = g_new0 (SessionHarness, 1);
178   h->caps = generate_caps ();
179   g_mutex_init (&h->lock);
180 
181   h->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
182   gst_system_clock_set_default (GST_CLOCK_CAST (h->testclock));
183 
184   h->session = gst_element_factory_make ("rtpsession", NULL);
185   gst_element_set_clock (h->session, GST_CLOCK_CAST (h->testclock));
186 
187   h->send_rtp_h = gst_harness_new_with_element (h->session,
188       "send_rtp_sink", "send_rtp_src");
189   gst_harness_set_src_caps (h->send_rtp_h, gst_caps_copy (h->caps));
190 
191   h->recv_rtp_h = gst_harness_new_with_element (h->session,
192       "recv_rtp_sink", "recv_rtp_src");
193   gst_harness_set_src_caps (h->recv_rtp_h, gst_caps_copy (h->caps));
194 
195   h->rtcp_h = gst_harness_new_with_element (h->session,
196       "recv_rtcp_sink", "send_rtcp_src");
197   gst_harness_set_src_caps_str (h->rtcp_h, "application/x-rtcp");
198 
199   g_signal_connect (h->session, "request-pt-map",
200       (GCallback) _pt_map_requested, h);
201 
202   g_signal_connect (h->session, "notify::twcc-stats",
203       (GCallback) _notify_twcc_stats, h);
204 
205   g_object_get (h->session, "internal-session", &h->internal_session, NULL);
206 
207   return h;
208 }
209 
210 static void
session_harness_free(SessionHarness * h)211 session_harness_free (SessionHarness * h)
212 {
213   gst_system_clock_set_default (NULL);
214 
215   gst_caps_unref (h->caps);
216   gst_object_unref (h->testclock);
217 
218   gst_harness_teardown (h->rtcp_h);
219   gst_harness_teardown (h->recv_rtp_h);
220   gst_harness_teardown (h->send_rtp_h);
221 
222   g_mutex_clear (&h->lock);
223 
224   if (h->last_twcc_stats)
225     gst_structure_free (h->last_twcc_stats);
226 
227   g_object_unref (h->internal_session);
228   gst_object_unref (h->session);
229   g_free (h);
230 }
231 
232 static GstFlowReturn
session_harness_send_rtp(SessionHarness * h,GstBuffer * buf)233 session_harness_send_rtp (SessionHarness * h, GstBuffer * buf)
234 {
235   return gst_harness_push (h->send_rtp_h, buf);
236 }
237 
238 static GstBuffer *
session_harness_pull_send_rtp(SessionHarness * h)239 session_harness_pull_send_rtp (SessionHarness * h)
240 {
241   return gst_harness_pull (h->send_rtp_h);
242 }
243 
244 static GstFlowReturn
session_harness_recv_rtp(SessionHarness * h,GstBuffer * buf)245 session_harness_recv_rtp (SessionHarness * h, GstBuffer * buf)
246 {
247   return gst_harness_push (h->recv_rtp_h, buf);
248 }
249 
250 static GstFlowReturn
session_harness_recv_rtcp(SessionHarness * h,GstBuffer * buf)251 session_harness_recv_rtcp (SessionHarness * h, GstBuffer * buf)
252 {
253   return gst_harness_push (h->rtcp_h, buf);
254 }
255 
256 static GstBuffer *
session_harness_pull_rtcp(SessionHarness * h)257 session_harness_pull_rtcp (SessionHarness * h)
258 {
259   return gst_harness_pull (h->rtcp_h);
260 }
261 
262 static void
session_harness_crank_clock(SessionHarness * h)263 session_harness_crank_clock (SessionHarness * h)
264 {
265   gst_test_clock_crank (h->testclock);
266 }
267 
268 static gboolean
session_harness_advance_and_crank(SessionHarness * h,GstClockTime delta)269 session_harness_advance_and_crank (SessionHarness * h, GstClockTime delta)
270 {
271   GstClockID res, pending;
272   gboolean result;
273   gst_test_clock_wait_for_next_pending_id (h->testclock, &pending);
274   gst_test_clock_advance_time (h->testclock, delta);
275   res = gst_test_clock_process_next_clock_id (h->testclock);
276   if (res == pending)
277     result = TRUE;
278   else
279     result = FALSE;
280   if (res)
281     gst_clock_id_unref (res);
282   gst_clock_id_unref (pending);
283   return result;
284 }
285 
286 static void
session_harness_produce_rtcp(SessionHarness * h,gint num_rtcp_packets)287 session_harness_produce_rtcp (SessionHarness * h, gint num_rtcp_packets)
288 {
289   /* due to randomness in rescheduling of RTCP timeout, we need to
290      keep cranking until we have the desired amount of packets */
291   while (gst_harness_buffers_in_queue (h->rtcp_h) < num_rtcp_packets) {
292     session_harness_crank_clock (h);
293     /* allow the rtcp-thread to settle before checking the queue */
294     gst_test_clock_wait_for_next_pending_id (h->testclock, NULL);
295   }
296 }
297 
298 static void
session_harness_force_key_unit(SessionHarness * h,guint count,guint ssrc,guint payload,gint * reqid,guint64 * sfr)299 session_harness_force_key_unit (SessionHarness * h,
300     guint count, guint ssrc, guint payload, gint * reqid, guint64 * sfr)
301 {
302   GstClockTime running_time = GST_CLOCK_TIME_NONE;
303   gboolean all_headers = TRUE;
304 
305   GstStructure *s = gst_structure_new ("GstForceKeyUnit",
306       "running-time", GST_TYPE_CLOCK_TIME, running_time,
307       "all-headers", G_TYPE_BOOLEAN, all_headers,
308       "count", G_TYPE_UINT, count,
309       "ssrc", G_TYPE_UINT, ssrc,
310       "payload", G_TYPE_UINT, payload,
311       NULL);
312 
313   if (reqid)
314     gst_structure_set (s, "reqid", G_TYPE_INT, *reqid, NULL);
315   if (sfr)
316     gst_structure_set (s, "sfr", G_TYPE_UINT64, *sfr, NULL);
317 
318   gst_harness_push_upstream_event (h->recv_rtp_h,
319       gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s));
320 }
321 
322 static void
session_harness_rtp_retransmission_request(SessionHarness * h,guint ssrc,guint seqnum,guint delay,guint deadline,guint avg_rtt)323 session_harness_rtp_retransmission_request (SessionHarness * h,
324     guint ssrc, guint seqnum, guint delay, guint deadline, guint avg_rtt)
325 {
326   GstClockTime running_time = GST_CLOCK_TIME_NONE;
327 
328   GstStructure *s = gst_structure_new ("GstRTPRetransmissionRequest",
329       "running-time", GST_TYPE_CLOCK_TIME, running_time,
330       "ssrc", G_TYPE_UINT, ssrc,
331       "seqnum", G_TYPE_UINT, seqnum,
332       "delay", G_TYPE_UINT, delay,
333       "deadline", G_TYPE_UINT, deadline,
334       "avg-rtt", G_TYPE_UINT, avg_rtt,
335       NULL);
336   gst_harness_push_upstream_event (h->recv_rtp_h,
337       gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s));
338 }
339 
340 static void
_add_twcc_field_to_caps(GstCaps * caps,guint8 ext_id)341 _add_twcc_field_to_caps (GstCaps * caps, guint8 ext_id)
342 {
343   gchar *name = g_strdup_printf ("extmap-%u", ext_id);
344   gst_caps_set_simple (caps, name, G_TYPE_STRING, TWCC_EXTMAP_STR, NULL);
345   g_free (name);
346 }
347 
348 static void
session_harness_set_twcc_recv_ext_id(SessionHarness * h,guint8 ext_id)349 session_harness_set_twcc_recv_ext_id (SessionHarness * h, guint8 ext_id)
350 {
351   _add_twcc_field_to_caps (h->caps, ext_id);
352   g_signal_emit_by_name (h->session, "clear-pt-map");
353 }
354 
355 static void
session_harness_set_twcc_send_ext_id(SessionHarness * h,guint8 ext_id)356 session_harness_set_twcc_send_ext_id (SessionHarness * h, guint8 ext_id)
357 {
358   GstCaps *caps = gst_caps_copy (h->caps);
359   _add_twcc_field_to_caps (caps, ext_id);
360   gst_harness_set_src_caps (h->send_rtp_h, caps);
361 }
362 
GST_START_TEST(test_multiple_ssrc_rr)363 GST_START_TEST (test_multiple_ssrc_rr)
364 {
365   SessionHarness *h = session_harness_new ();
366   GstFlowReturn res;
367   GstBuffer *in_buf, *out_buf;
368   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
369   GstRTCPPacket rtcp_packet;
370   gint i, j;
371   guint ssrc_match;
372 
373   guint ssrcs[] = {
374     0x01BADBAD,
375     0xDEADBEEF,
376   };
377 
378   /* receive buffers with multiple ssrcs */
379   for (i = 0; i < 2; i++) {
380     for (j = 0; j < G_N_ELEMENTS (ssrcs); j++) {
381       in_buf = generate_test_buffer (i, ssrcs[j]);
382       res = session_harness_recv_rtp (h, in_buf);
383       fail_unless_equals_int (GST_FLOW_OK, res);
384     }
385   }
386 
387   /* crank the rtcp-thread and pull out the rtcp-packet we have generated */
388   session_harness_crank_clock (h);
389   out_buf = session_harness_pull_rtcp (h);
390 
391   /* verify we have report blocks for both ssrcs */
392   g_assert (out_buf != NULL);
393   fail_unless (gst_rtcp_buffer_validate (out_buf));
394   gst_rtcp_buffer_map (out_buf, GST_MAP_READ, &rtcp);
395   g_assert (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
396   fail_unless_equals_int (GST_RTCP_TYPE_RR,
397       gst_rtcp_packet_get_type (&rtcp_packet));
398 
399   fail_unless_equals_int (G_N_ELEMENTS (ssrcs),
400       gst_rtcp_packet_get_rb_count (&rtcp_packet));
401 
402   ssrc_match = 0;
403   for (i = 0; i < G_N_ELEMENTS (ssrcs); i++) {
404     guint32 ssrc;
405     gst_rtcp_packet_get_rb (&rtcp_packet, i, &ssrc,
406         NULL, NULL, NULL, NULL, NULL, NULL);
407     for (j = 0; j < G_N_ELEMENTS (ssrcs); j++) {
408       if (ssrcs[j] == ssrc)
409         ssrc_match++;
410     }
411   }
412   fail_unless_equals_int (G_N_ELEMENTS (ssrcs), ssrc_match);
413 
414   gst_rtcp_buffer_unmap (&rtcp);
415   gst_buffer_unref (out_buf);
416 
417   session_harness_free (h);
418 }
419 
420 GST_END_TEST;
421 
422 /* This verifies that rtpsession will correctly place RBs round-robin
423  * across multiple RRs when there are too many senders that their RBs
424  * do not fit in one RR */
GST_START_TEST(test_multiple_senders_roundrobin_rbs)425 GST_START_TEST (test_multiple_senders_roundrobin_rbs)
426 {
427   SessionHarness *h = session_harness_new ();
428   GstFlowReturn res;
429   GstBuffer *buf;
430   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
431   GstRTCPPacket rtcp_packet;
432   gint i, j, k;
433   guint32 ssrc;
434   GHashTable *rb_ssrcs, *tmp_set;
435 
436   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
437 
438   /* this is a hack to prevent the sources from timing out when cranking and
439      hence messing with RTCP-generation, making the test fail 1/1000 times */
440   g_object_set (h->session, "rtcp-min-interval", 20 * GST_SECOND, NULL);
441 
442   for (i = 0; i < 2; i++) {     /* cycles between RR reports */
443     for (j = 0; j < 5; j++) {   /* packets per ssrc */
444       gint seq = (i * 5) + j;
445       for (k = 0; k < 35; k++) {        /* number of ssrcs */
446         buf = generate_test_buffer (seq, 10000 + k);
447         res = session_harness_recv_rtp (h, buf);
448         fail_unless_equals_int (GST_FLOW_OK, res);
449       }
450     }
451   }
452 
453   rb_ssrcs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
454       (GDestroyNotify) g_hash_table_unref);
455 
456   /* verify the rtcp packets */
457   for (i = 0; i < 2; i++) {
458     guint expected_rb_count = (i < 1) ? GST_RTCP_MAX_RB_COUNT :
459         (35 - GST_RTCP_MAX_RB_COUNT);
460 
461     session_harness_produce_rtcp (h, 1);
462     buf = session_harness_pull_rtcp (h);
463     g_assert (buf != NULL);
464     fail_unless (gst_rtcp_buffer_validate (buf));
465 
466     gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
467     fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
468     fail_unless_equals_int (GST_RTCP_TYPE_RR,
469         gst_rtcp_packet_get_type (&rtcp_packet));
470 
471     ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
472     fail_unless_equals_int (0xDEADBEEF, ssrc);
473 
474     /* inspect the RBs */
475     fail_unless_equals_int (expected_rb_count,
476         gst_rtcp_packet_get_rb_count (&rtcp_packet));
477 
478     if (i == 0) {
479       tmp_set = g_hash_table_new (g_direct_hash, g_direct_equal);
480       g_hash_table_insert (rb_ssrcs, GUINT_TO_POINTER (ssrc), tmp_set);
481     } else {
482       tmp_set = g_hash_table_lookup (rb_ssrcs, GUINT_TO_POINTER (ssrc));
483       g_assert (tmp_set);
484     }
485 
486     for (j = 0; j < expected_rb_count; j++) {
487       gst_rtcp_packet_get_rb (&rtcp_packet, j, &ssrc, NULL, NULL,
488           NULL, NULL, NULL, NULL);
489       g_assert_cmpint (ssrc, >=, 10000);
490       g_assert_cmpint (ssrc, <=, 10035);
491       g_hash_table_add (tmp_set, GUINT_TO_POINTER (ssrc));
492     }
493 
494     gst_rtcp_buffer_unmap (&rtcp);
495     gst_buffer_unref (buf);
496   }
497 
498   /* now verify all received ssrcs have been reported */
499   fail_unless_equals_int (1, g_hash_table_size (rb_ssrcs));
500   tmp_set = g_hash_table_lookup (rb_ssrcs, GUINT_TO_POINTER (0xDEADBEEF));
501   g_assert (tmp_set);
502   fail_unless_equals_int (35, g_hash_table_size (tmp_set));
503 
504   g_hash_table_unref (rb_ssrcs);
505   session_harness_free (h);
506 }
507 
508 GST_END_TEST;
509 
GST_START_TEST(test_no_rbs_for_internal_senders)510 GST_START_TEST (test_no_rbs_for_internal_senders)
511 {
512   SessionHarness *h = session_harness_new ();
513   GstFlowReturn res;
514   GstBuffer *buf;
515   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
516   GstRTCPPacket rtcp_packet;
517   gint i, j, k;
518   guint32 ssrc;
519   GHashTable *sr_ssrcs;
520   GHashTable *rb_ssrcs, *tmp_set;
521 
522   /* Push RTP from our send SSRCs */
523   for (j = 0; j < 5; j++) {     /* packets per ssrc */
524     for (k = 0; k < 2; k++) {   /* number of ssrcs */
525       buf = generate_test_buffer (j, 10000 + k);
526       res = session_harness_send_rtp (h, buf);
527       fail_unless_equals_int (GST_FLOW_OK, res);
528     }
529   }
530 
531   /* crank the RTCP pad thread */
532   session_harness_crank_clock (h);
533 
534   sr_ssrcs = g_hash_table_new (g_direct_hash, g_direct_equal);
535 
536   /* verify the rtcp packets */
537   for (i = 0; i < 2; i++) {
538     buf = session_harness_pull_rtcp (h);
539     g_assert (buf != NULL);
540     g_assert (gst_rtcp_buffer_validate (buf));
541 
542     gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
543     g_assert (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
544     fail_unless_equals_int (GST_RTCP_TYPE_SR,
545         gst_rtcp_packet_get_type (&rtcp_packet));
546 
547     gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL,
548         NULL, NULL);
549     g_assert_cmpint (ssrc, >=, 10000);
550     g_assert_cmpint (ssrc, <=, 10001);
551     g_hash_table_add (sr_ssrcs, GUINT_TO_POINTER (ssrc));
552 
553     /* There should be no RBs as there are no remote senders */
554     fail_unless_equals_int (0, gst_rtcp_packet_get_rb_count (&rtcp_packet));
555 
556     gst_rtcp_buffer_unmap (&rtcp);
557     gst_buffer_unref (buf);
558   }
559 
560   /* Ensure both internal senders generated RTCP */
561   fail_unless_equals_int (2, g_hash_table_size (sr_ssrcs));
562   g_hash_table_unref (sr_ssrcs);
563 
564   /* Generate RTP from remote side */
565   for (j = 0; j < 5; j++) {     /* packets per ssrc */
566     for (k = 0; k < 2; k++) {   /* number of ssrcs */
567       buf = generate_test_buffer (j, 20000 + k);
568       res = session_harness_recv_rtp (h, buf);
569       fail_unless_equals_int (GST_FLOW_OK, res);
570     }
571   }
572 
573   sr_ssrcs = g_hash_table_new (g_direct_hash, g_direct_equal);
574   rb_ssrcs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
575       (GDestroyNotify) g_hash_table_unref);
576 
577   /* verify the rtcp packets */
578   for (i = 0; i < 2; i++) {
579     session_harness_produce_rtcp (h, 1);
580     buf = session_harness_pull_rtcp (h);
581     g_assert (buf != NULL);
582     g_assert (gst_rtcp_buffer_validate (buf));
583 
584     gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
585     g_assert (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
586     fail_unless_equals_int (GST_RTCP_TYPE_SR,
587         gst_rtcp_packet_get_type (&rtcp_packet));
588 
589     gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL,
590         NULL, NULL);
591     g_assert_cmpint (ssrc, >=, 10000);
592     g_assert_cmpint (ssrc, <=, 10001);
593     g_hash_table_add (sr_ssrcs, GUINT_TO_POINTER (ssrc));
594 
595     /* There should be 2 RBs: one for each remote sender */
596     fail_unless_equals_int (2, gst_rtcp_packet_get_rb_count (&rtcp_packet));
597 
598     tmp_set = g_hash_table_new (g_direct_hash, g_direct_equal);
599     g_hash_table_insert (rb_ssrcs, GUINT_TO_POINTER (ssrc), tmp_set);
600 
601     for (j = 0; j < 2; j++) {
602       gst_rtcp_packet_get_rb (&rtcp_packet, j, &ssrc, NULL, NULL,
603           NULL, NULL, NULL, NULL);
604       g_assert_cmpint (ssrc, >=, 20000);
605       g_assert_cmpint (ssrc, <=, 20001);
606       g_hash_table_add (tmp_set, GUINT_TO_POINTER (ssrc));
607     }
608 
609     gst_rtcp_buffer_unmap (&rtcp);
610     gst_buffer_unref (buf);
611   }
612 
613   /* now verify all received ssrcs have been reported */
614   fail_unless_equals_int (2, g_hash_table_size (sr_ssrcs));
615   fail_unless_equals_int (2, g_hash_table_size (rb_ssrcs));
616   for (i = 10000; i < 10002; i++) {
617     tmp_set = g_hash_table_lookup (rb_ssrcs, GUINT_TO_POINTER (i));
618     g_assert (tmp_set);
619     fail_unless_equals_int (2, g_hash_table_size (tmp_set));
620   }
621 
622   g_hash_table_unref (rb_ssrcs);
623   g_hash_table_unref (sr_ssrcs);
624 
625   session_harness_free (h);
626 }
627 
628 GST_END_TEST;
629 
GST_START_TEST(test_internal_sources_timeout)630 GST_START_TEST (test_internal_sources_timeout)
631 {
632   SessionHarness *h = session_harness_new ();
633   guint internal_ssrc;
634   guint32 ssrc;
635   GstBuffer *buf;
636   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
637   GstRTCPPacket rtcp_packet;
638   GstRTCPType rtcp_type;
639   GstFlowReturn res;
640   gint i, j;
641   GstCaps *caps;
642   gboolean seen_bye;
643 
644   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
645   g_object_get (h->internal_session, "internal-ssrc", &internal_ssrc, NULL);
646   fail_unless_equals_int (0xDEADBEEF, internal_ssrc);
647 
648   /* this is a hack to prevent the sources from timing out when cranking and
649      hence messing with RTCP-generation, making the test fail 1/100 times */
650   g_object_set (h->session, "rtcp-min-interval", 20 * GST_SECOND, NULL);
651 
652   for (i = 1; i < 4; i++) {
653     buf = generate_test_buffer (i, 0xBEEFDEAD);
654     res = session_harness_recv_rtp (h, buf);
655     fail_unless_equals_int (GST_FLOW_OK, res);
656   }
657 
658   /* verify that rtpsession has sent RR for an internally-created
659    * RTPSource that is using the internal-ssrc */
660   session_harness_produce_rtcp (h, 1);
661   buf = session_harness_pull_rtcp (h);
662 
663   fail_unless (buf != NULL);
664   fail_unless (gst_rtcp_buffer_validate (buf));
665   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
666   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
667   fail_unless_equals_int (GST_RTCP_TYPE_RR,
668       gst_rtcp_packet_get_type (&rtcp_packet));
669   ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
670   fail_unless_equals_int (ssrc, internal_ssrc);
671   gst_rtcp_buffer_unmap (&rtcp);
672   gst_buffer_unref (buf);
673 
674   /* ok, now let's push some RTP packets */
675   caps = gst_caps_new_simple ("application/x-rtp",
676       "ssrc", G_TYPE_UINT, 0x01BADBAD, NULL);
677   gst_harness_set_src_caps (h->send_rtp_h, caps);
678 
679   for (i = 1; i < 4; i++) {
680     buf = generate_test_buffer (i, 0x01BADBAD);
681     res = session_harness_send_rtp (h, buf);
682     fail_unless_equals_int (GST_FLOW_OK, res);
683   }
684 
685   /* internal ssrc must have changed already */
686   g_object_get (h->internal_session, "internal-ssrc", &internal_ssrc, NULL);
687   fail_unless (internal_ssrc != ssrc);
688   fail_unless_equals_int (0x01BADBAD, internal_ssrc);
689 
690   /* verify SR and RR */
691   j = 0;
692   for (i = 0; i < 5; i++) {
693     session_harness_produce_rtcp (h, 1);
694     buf = session_harness_pull_rtcp (h);
695     g_assert (buf != NULL);
696     fail_unless (gst_rtcp_buffer_validate (buf));
697     gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
698     fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
699     rtcp_type = gst_rtcp_packet_get_type (&rtcp_packet);
700 
701     if (rtcp_type == GST_RTCP_TYPE_SR) {
702       gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, &ssrc, NULL, NULL, NULL,
703           NULL);
704       fail_unless_equals_int (internal_ssrc, ssrc);
705       fail_unless_equals_int (0x01BADBAD, ssrc);
706       j |= 0x1;
707     } else if (rtcp_type == GST_RTCP_TYPE_RR) {
708       ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
709       if (internal_ssrc != ssrc)
710         j |= 0x2;
711     }
712     gst_rtcp_buffer_unmap (&rtcp);
713     gst_buffer_unref (buf);
714   }
715   fail_unless_equals_int (0x3, j);      /* verify we got both SR and RR */
716 
717   /* go 30 seconds in the future and observe both sources timing out:
718    * 0xDEADBEEF -> BYE, 0x01BADBAD -> becomes receiver only */
719   fail_unless (session_harness_advance_and_crank (h, 30 * GST_SECOND));
720 
721   /* verify BYE and RR */
722   j = 0;
723   seen_bye = FALSE;
724   while (!seen_bye) {
725     session_harness_produce_rtcp (h, 1);
726     buf = session_harness_pull_rtcp (h);
727     fail_unless (buf != NULL);
728     fail_unless (gst_rtcp_buffer_validate (buf));
729     gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
730     fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
731     rtcp_type = gst_rtcp_packet_get_type (&rtcp_packet);
732 
733     if (rtcp_type == GST_RTCP_TYPE_RR) {
734       ssrc = gst_rtcp_packet_rr_get_ssrc (&rtcp_packet);
735       if (ssrc == 0x01BADBAD) {
736         j |= 0x1;
737         fail_unless_equals_int (internal_ssrc, ssrc);
738         /* 2 => RR, SDES. There is no BYE here */
739         fail_unless_equals_int (2, gst_rtcp_buffer_get_packet_count (&rtcp));
740       } else if (ssrc == 0xDEADBEEF) {
741         j |= 0x2;
742         g_assert_cmpint (ssrc, !=, internal_ssrc);
743         /* 3 => RR, SDES, BYE */
744         if (gst_rtcp_buffer_get_packet_count (&rtcp) == 3) {
745           fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
746           fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
747           fail_unless_equals_int (GST_RTCP_TYPE_BYE,
748               gst_rtcp_packet_get_type (&rtcp_packet));
749           seen_bye = TRUE;
750         }
751       }
752     }
753     gst_rtcp_buffer_unmap (&rtcp);
754     gst_buffer_unref (buf);
755   }
756   fail_unless_equals_int (0x3, j);      /* verify we got both BYE and RR */
757 
758   session_harness_free (h);
759 }
760 
761 GST_END_TEST;
762 
763 typedef struct
764 {
765   guint8 subtype;
766   guint32 ssrc;
767   gchar *name;
768   GstBuffer *data;
769 } RTCPAppResult;
770 
771 static void
on_app_rtcp_cb(GObject * session,guint subtype,guint ssrc,const gchar * name,GstBuffer * data,RTCPAppResult * result)772 on_app_rtcp_cb (GObject * session, guint subtype, guint ssrc,
773     const gchar * name, GstBuffer * data, RTCPAppResult * result)
774 {
775   result->subtype = subtype;
776   result->ssrc = ssrc;
777   result->name = g_strdup (name);
778   result->data = data ? gst_buffer_ref (data) : NULL;
779 }
780 
GST_START_TEST(test_receive_rtcp_app_packet)781 GST_START_TEST (test_receive_rtcp_app_packet)
782 {
783   SessionHarness *h = session_harness_new ();
784   GstBuffer *buf;
785   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
786   GstRTCPPacket packet;
787   RTCPAppResult result = { 0 };
788   guint8 data[] = { 0x11, 0x22, 0x33, 0x44 };
789 
790   g_signal_connect (h->internal_session, "on-app-rtcp",
791       G_CALLBACK (on_app_rtcp_cb), &result);
792 
793   /* Push APP buffer with no data */
794   buf = gst_rtcp_buffer_new (1000);
795   fail_unless (gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcp));
796   fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_APP, &packet));
797   gst_rtcp_packet_app_set_subtype (&packet, 21);
798   gst_rtcp_packet_app_set_ssrc (&packet, 0x11111111);
799   gst_rtcp_packet_app_set_name (&packet, "Test");
800   gst_rtcp_buffer_unmap (&rtcp);
801 
802   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
803 
804   fail_unless_equals_int (21, result.subtype);
805   fail_unless_equals_int (0x11111111, result.ssrc);
806   fail_unless_equals_string ("Test", result.name);
807   fail_unless_equals_pointer (NULL, result.data);
808 
809   g_free (result.name);
810 
811   /* Push APP buffer with data */
812   memset (&result, 0, sizeof (result));
813   buf = gst_rtcp_buffer_new (1000);
814   fail_unless (gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcp));
815   fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_APP, &packet));
816   gst_rtcp_packet_app_set_subtype (&packet, 22);
817   gst_rtcp_packet_app_set_ssrc (&packet, 0x22222222);
818   gst_rtcp_packet_app_set_name (&packet, "Test");
819   gst_rtcp_packet_app_set_data_length (&packet, sizeof (data) / 4);
820   memcpy (gst_rtcp_packet_app_get_data (&packet), data, sizeof (data));
821   gst_rtcp_buffer_unmap (&rtcp);
822 
823   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
824 
825   fail_unless_equals_int (22, result.subtype);
826   fail_unless_equals_int (0x22222222, result.ssrc);
827   fail_unless_equals_string ("Test", result.name);
828   fail_unless (gst_buffer_memcmp (result.data, 0, data, sizeof (data)) == 0);
829 
830   g_free (result.name);
831   gst_buffer_unref (result.data);
832 
833   session_harness_free (h);
834 }
835 
836 GST_END_TEST;
837 
838 static void
stats_test_cb(GObject * object,GParamSpec * spec,gpointer data)839 stats_test_cb (GObject * object, GParamSpec * spec, gpointer data)
840 {
841   guint num_sources = 0;
842   gboolean *cb_called = data;
843   g_assert (*cb_called == FALSE);
844 
845   /* We should be able to get a rtpsession property
846      without introducing the deadlock */
847   g_object_get (object, "num-sources", &num_sources, NULL);
848 
849   *cb_called = TRUE;
850 }
851 
GST_START_TEST(test_dont_lock_on_stats)852 GST_START_TEST (test_dont_lock_on_stats)
853 {
854   SessionHarness *h = session_harness_new ();
855   gboolean cb_called = FALSE;
856 
857   /* connect to the stats-reporting */
858   g_signal_connect (h->session, "notify::stats",
859       G_CALLBACK (stats_test_cb), &cb_called);
860 
861   /* Push RTP buffer to make sure RTCP-thread have started */
862   fail_unless_equals_int (GST_FLOW_OK,
863       session_harness_send_rtp (h, generate_test_buffer (0, 0xDEADBEEF)));
864 
865   /* crank the RTCP-thread and pull out rtcp, generating a stats-callback */
866   session_harness_crank_clock (h);
867   gst_buffer_unref (session_harness_pull_rtcp (h));
868   fail_unless (cb_called);
869 
870   session_harness_free (h);
871 }
872 
873 GST_END_TEST;
874 
875 static void
suspicious_bye_cb(GObject * object,GParamSpec * spec,gpointer data)876 suspicious_bye_cb (GObject * object, GParamSpec * spec, gpointer data)
877 {
878   GValueArray *stats_arr;
879   GstStructure *stats, *internal_stats;
880   gboolean *cb_called = data;
881   gboolean internal = FALSE, sent_bye = TRUE;
882   guint ssrc = 0;
883   guint i;
884 
885   g_assert (*cb_called == FALSE);
886   *cb_called = TRUE;
887 
888   g_object_get (object, "stats", &stats, NULL);
889   stats_arr =
890       g_value_get_boxed (gst_structure_get_value (stats, "source-stats"));
891   g_assert (stats_arr != NULL);
892   fail_unless (stats_arr->n_values >= 1);
893 
894   for (i = 0; i < stats_arr->n_values; i++) {
895     internal_stats = g_value_get_boxed (g_value_array_get_nth (stats_arr, i));
896     g_assert (internal_stats != NULL);
897 
898     gst_structure_get (internal_stats,
899         "ssrc", G_TYPE_UINT, &ssrc,
900         "internal", G_TYPE_BOOLEAN, &internal,
901         "received-bye", G_TYPE_BOOLEAN, &sent_bye, NULL);
902 
903     if (ssrc == 0xDEADBEEF) {
904       fail_unless (internal);
905       fail_unless (!sent_bye);
906       break;
907     }
908   }
909   fail_unless_equals_int (ssrc, 0xDEADBEEF);
910 
911   gst_structure_free (stats);
912 }
913 
914 static GstBuffer *
create_bye_rtcp(guint32 ssrc)915 create_bye_rtcp (guint32 ssrc)
916 {
917   GstRTCPPacket packet;
918   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
919   GSocketAddress *saddr;
920   GstBuffer *buffer = gst_rtcp_buffer_new (1000);
921 
922   fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
923   fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_BYE, &packet));
924   gst_rtcp_packet_bye_add_ssrc (&packet, ssrc);
925   gst_rtcp_buffer_unmap (&rtcp);
926 
927   /* Need to add meta to trigger collision detection */
928   saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 3490);
929   gst_buffer_add_net_address_meta (buffer, saddr);
930   g_object_unref (saddr);
931   return buffer;
932 }
933 
GST_START_TEST(test_ignore_suspicious_bye)934 GST_START_TEST (test_ignore_suspicious_bye)
935 {
936   SessionHarness *h = session_harness_new ();
937   gboolean cb_called = FALSE;
938 
939   /* connect to the stats-reporting */
940   g_signal_connect (h->session, "notify::stats",
941       G_CALLBACK (suspicious_bye_cb), &cb_called);
942 
943   /* Push RTP buffer making our internal SSRC=0xDEADBEEF */
944   fail_unless_equals_int (GST_FLOW_OK,
945       session_harness_send_rtp (h, generate_test_buffer (0, 0xDEADBEEF)));
946 
947   /* Receive BYE RTCP referencing our internal SSRC(!?!) (0xDEADBEEF) */
948   fail_unless_equals_int (GST_FLOW_OK,
949       session_harness_recv_rtcp (h, create_bye_rtcp (0xDEADBEEF)));
950 
951   /* "crank" and check the stats */
952   session_harness_crank_clock (h);
953   gst_buffer_unref (session_harness_pull_rtcp (h));
954   fail_unless (cb_called);
955 
956   session_harness_free (h);
957 }
958 
959 GST_END_TEST;
960 
961 static GstBuffer *
create_buffer(guint8 * data,gsize size)962 create_buffer (guint8 * data, gsize size)
963 {
964   return gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
965       data, size, 0, size, NULL, NULL);
966 }
967 
GST_START_TEST(test_receive_regular_pli)968 GST_START_TEST (test_receive_regular_pli)
969 {
970   SessionHarness *h = session_harness_new ();
971   GstEvent *ev;
972 
973   /* PLI packet */
974   guint8 rtcp_pkt[] = {
975     0x81,                       /* PLI */
976     0xce,                       /* Type 206 Application layer feedback */
977     0x00, 0x02,                 /* Length */
978     0x37, 0x56, 0x93, 0xed,     /* Sender SSRC */
979     0x37, 0x56, 0x93, 0xed      /* Media SSRC */
980   };
981 
982   fail_unless_equals_int (GST_FLOW_OK,
983       session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
984 
985   session_harness_recv_rtcp (h, create_buffer (rtcp_pkt, sizeof (rtcp_pkt)));
986   fail_unless_equals_int (3,
987       gst_harness_upstream_events_received (h->send_rtp_h));
988 
989   /* Remove the first 2 reconfigure events */
990   fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
991   fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
992   gst_event_unref (ev);
993   fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
994   fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
995   gst_event_unref (ev);
996 
997   /* Then pull and check the force key-unit event */
998   fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
999   fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
1000   fail_unless (gst_video_event_is_force_key_unit (ev));
1001   gst_event_unref (ev);
1002 
1003   session_harness_free (h);
1004 }
1005 
1006 GST_END_TEST;
1007 
GST_START_TEST(test_receive_pli_no_sender_ssrc)1008 GST_START_TEST (test_receive_pli_no_sender_ssrc)
1009 {
1010   SessionHarness *h = session_harness_new ();
1011   GstEvent *ev;
1012 
1013   /* PLI packet */
1014   guint8 rtcp_pkt[] = {
1015     0x81,                       /* PLI */
1016     0xce,                       /* Type 206 Application layer feedback */
1017     0x00, 0x02,                 /* Length */
1018     0x00, 0x00, 0x00, 0x00,     /* Sender SSRC */
1019     0x37, 0x56, 0x93, 0xed      /* Media SSRC */
1020   };
1021 
1022   fail_unless_equals_int (GST_FLOW_OK,
1023       session_harness_send_rtp (h, generate_test_buffer (0, 928420845)));
1024 
1025   session_harness_recv_rtcp (h, create_buffer (rtcp_pkt, sizeof (rtcp_pkt)));
1026   fail_unless_equals_int (3,
1027       gst_harness_upstream_events_received (h->send_rtp_h));
1028 
1029   /* Remove the first 2 reconfigure events */
1030   fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
1031   fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
1032   gst_event_unref (ev);
1033   fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
1034   fail_unless_equals_int (GST_EVENT_RECONFIGURE, GST_EVENT_TYPE (ev));
1035   gst_event_unref (ev);
1036 
1037   /* Then pull and check the force key-unit event */
1038   fail_unless ((ev = gst_harness_pull_upstream_event (h->send_rtp_h)) != NULL);
1039   fail_unless_equals_int (GST_EVENT_CUSTOM_UPSTREAM, GST_EVENT_TYPE (ev));
1040   fail_unless (gst_video_event_is_force_key_unit (ev));
1041   gst_event_unref (ev);
1042 
1043   session_harness_free (h);
1044 }
1045 
1046 GST_END_TEST;
1047 
1048 static void
add_rtcp_sdes_packet(GstBuffer * gstbuf,guint32 ssrc,const char * cname)1049 add_rtcp_sdes_packet (GstBuffer * gstbuf, guint32 ssrc, const char *cname)
1050 {
1051   GstRTCPPacket packet;
1052   GstRTCPBuffer buffer = GST_RTCP_BUFFER_INIT;
1053 
1054   gst_rtcp_buffer_map (gstbuf, GST_MAP_READWRITE, &buffer);
1055 
1056   fail_unless (gst_rtcp_buffer_add_packet (&buffer, GST_RTCP_TYPE_SDES,
1057           &packet) == TRUE);
1058   fail_unless (gst_rtcp_packet_sdes_add_item (&packet, ssrc) == TRUE);
1059   fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME,
1060           strlen (cname), (const guint8 *) cname));
1061 
1062   gst_rtcp_buffer_unmap (&buffer);
1063 }
1064 
1065 
1066 static void
on_ssrc_collision_cb(GstElement * rtpsession,guint ssrc,gpointer user_data)1067 on_ssrc_collision_cb (GstElement * rtpsession, guint ssrc, gpointer user_data)
1068 {
1069   gboolean *had_collision = user_data;
1070 
1071   *had_collision = TRUE;
1072 }
1073 
GST_START_TEST(test_ssrc_collision_when_sending)1074 GST_START_TEST (test_ssrc_collision_when_sending)
1075 {
1076   SessionHarness *h = session_harness_new ();
1077   GstBuffer *buf;
1078   GstEvent *ev;
1079   GSocketAddress *saddr;
1080   gboolean had_collision = FALSE;
1081 
1082   g_signal_connect (h->internal_session, "on-ssrc-collision",
1083       G_CALLBACK (on_ssrc_collision_cb), &had_collision);
1084 
1085 
1086   /* Push SDES with identical SSRC as what we will use for sending RTP,
1087      establishing this as a non-internal SSRC */
1088   buf = gst_rtcp_buffer_new (1400);
1089   add_rtcp_sdes_packet (buf, 0x12345678, "test@foo.bar");
1090   saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1091   gst_buffer_add_net_address_meta (buf, saddr);
1092   g_object_unref (saddr);
1093   session_harness_recv_rtcp (h, buf);
1094 
1095   fail_unless (had_collision == FALSE);
1096 
1097   /* Push RTP buffer making our internal SSRC=0x12345678 */
1098   buf = generate_test_buffer (0, 0x12345678);
1099   fail_unless_equals_int (GST_FLOW_OK, session_harness_send_rtp (h, buf));
1100 
1101   fail_unless (had_collision == TRUE);
1102 
1103   /* Verify the packet we just sent is not being boomeranged back to us
1104      as a received packet! */
1105   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
1106 
1107   while ((ev = gst_harness_try_pull_upstream_event (h->send_rtp_h)) != NULL) {
1108     if (GST_EVENT_CUSTOM_UPSTREAM == GST_EVENT_TYPE (ev) &&
1109         gst_event_has_name (ev, "GstRTPCollision"))
1110       break;
1111     gst_event_unref (ev);
1112   }
1113   fail_unless (ev != NULL);
1114   gst_event_unref (ev);
1115 
1116   session_harness_free (h);
1117 }
1118 
1119 GST_END_TEST;
1120 
GST_START_TEST(test_ssrc_collision_when_sending_loopback)1121 GST_START_TEST (test_ssrc_collision_when_sending_loopback)
1122 {
1123   SessionHarness *h = session_harness_new ();
1124   GstBuffer *buf;
1125   GstEvent *ev;
1126   GSocketAddress *saddr;
1127   gboolean had_collision = FALSE;
1128   guint new_ssrc;
1129   const GstStructure *s;
1130 
1131   g_signal_connect (h->internal_session, "on-ssrc-collision",
1132       G_CALLBACK (on_ssrc_collision_cb), &had_collision);
1133 
1134   /* Push SDES with identical SSRC as what we will use for sending RTP,
1135      establishing this as a non-internal SSRC */
1136   buf = gst_rtcp_buffer_new (1400);
1137   add_rtcp_sdes_packet (buf, 0x12345678, "test@foo.bar");
1138   saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1139   gst_buffer_add_net_address_meta (buf, saddr);
1140   g_object_unref (saddr);
1141   session_harness_recv_rtcp (h, buf);
1142 
1143   fail_unless (had_collision == FALSE);
1144 
1145   /* Push RTP buffer making our internal SSRC=0x12345678 */
1146   buf = generate_test_buffer (0, 0x12345678);
1147   fail_unless_equals_int (GST_FLOW_OK, session_harness_send_rtp (h, buf));
1148 
1149   fail_unless (had_collision == TRUE);
1150 
1151   /* Verify the packet we just sent is not being boomeranged back to us
1152      as a received packet! */
1153   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
1154 
1155   while ((ev = gst_harness_try_pull_upstream_event (h->send_rtp_h)) != NULL) {
1156     if (GST_EVENT_CUSTOM_UPSTREAM == GST_EVENT_TYPE (ev) &&
1157         gst_event_has_name (ev, "GstRTPCollision"))
1158       break;
1159     gst_event_unref (ev);
1160   }
1161   fail_unless (ev != NULL);
1162 
1163   s = gst_event_get_structure (ev);
1164   fail_unless (gst_structure_get_uint (s, "ssrc", &new_ssrc));
1165   gst_event_unref (ev);
1166 
1167   /* reset collision detection */
1168   had_collision = FALSE;
1169 
1170   /* Push SDES from same address but with the new SSRC, as if someone
1171    * was looping back our packets to us */
1172   buf = gst_rtcp_buffer_new (1400);
1173   add_rtcp_sdes_packet (buf, new_ssrc, "test@foo.bar");
1174   saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1175   gst_buffer_add_net_address_meta (buf, saddr);
1176   g_object_unref (saddr);
1177   session_harness_recv_rtcp (h, buf);
1178 
1179   /* Make sure we didn't detect a collision */
1180   fail_unless (had_collision == FALSE);
1181 
1182   /* Make sure there is no collision event either */
1183   while ((ev = gst_harness_try_pull_upstream_event (h->send_rtp_h)) != NULL) {
1184     fail_if (GST_EVENT_CUSTOM_UPSTREAM == GST_EVENT_TYPE (ev) &&
1185         gst_event_has_name (ev, "GstRTPCollision"));
1186     gst_event_unref (ev);
1187   }
1188 
1189   session_harness_free (h);
1190 }
1191 
1192 GST_END_TEST;
1193 
GST_START_TEST(test_ssrc_collision_when_receiving)1194 GST_START_TEST (test_ssrc_collision_when_receiving)
1195 {
1196   SessionHarness *h = session_harness_new ();
1197   GstBuffer *buf;
1198   GstEvent *ev;
1199   GSocketAddress *saddr;
1200   gboolean had_collision = FALSE;
1201 
1202   g_signal_connect (h->internal_session, "on-ssrc-collision",
1203       G_CALLBACK (on_ssrc_collision_cb), &had_collision);
1204 
1205   /* Push RTP buffer making our internal SSRC=0x12345678 */
1206   buf = generate_test_buffer (0, 0x12345678);
1207   fail_unless_equals_int (GST_FLOW_OK, session_harness_send_rtp (h, buf));
1208 
1209   fail_unless (had_collision == FALSE);
1210 
1211   /* Push SDES with identical SSRC as what we used to send RTP,
1212      to create a collision */
1213   buf = gst_rtcp_buffer_new (1400);
1214   add_rtcp_sdes_packet (buf, 0x12345678, "test@foo.bar");
1215   saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1216   gst_buffer_add_net_address_meta (buf, saddr);
1217   g_object_unref (saddr);
1218   session_harness_recv_rtcp (h, buf);
1219 
1220   fail_unless (had_collision == TRUE);
1221 
1222   /* Verify the packet we just sent is not being boomeranged back to us
1223      as a received packet! */
1224   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
1225 
1226   while ((ev = gst_harness_try_pull_upstream_event (h->send_rtp_h)) != NULL) {
1227     if (GST_EVENT_CUSTOM_UPSTREAM == GST_EVENT_TYPE (ev))
1228       break;
1229     gst_event_unref (ev);
1230   }
1231   fail_unless (ev != NULL);
1232   gst_event_unref (ev);
1233 
1234   session_harness_free (h);
1235 }
1236 
1237 GST_END_TEST;
1238 
1239 
GST_START_TEST(test_ssrc_collision_third_party)1240 GST_START_TEST (test_ssrc_collision_third_party)
1241 {
1242   SessionHarness *h = session_harness_new ();
1243   GstBuffer *buf;
1244   GSocketAddress *saddr;
1245   gboolean had_collision = FALSE;
1246   guint i;
1247 
1248   g_signal_connect (h->internal_session, "on-ssrc-collision",
1249       G_CALLBACK (on_ssrc_collision_cb), &had_collision);
1250 
1251   for (i = 0; i < 4; i++) {
1252     /* Receive 4 buffers SSRC=0x12345678 from 127.0.0.1 to pass probation */
1253     buf = generate_test_buffer (i, 0x12345678);
1254     saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1255     gst_buffer_add_net_address_meta (buf, saddr);
1256     g_object_unref (saddr);
1257     fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtp (h, buf));
1258   }
1259 
1260   /* Check that we received the first 4 buffer */
1261   for (i = 0; i < 4; i++) {
1262     buf = gst_harness_pull (h->recv_rtp_h);
1263     fail_unless (buf);
1264     gst_buffer_unref (buf);
1265   }
1266   fail_unless (had_collision == FALSE);
1267 
1268   /* Receive buffer SSRC=0x12345678 from 127.0.0.2 */
1269   buf = generate_test_buffer (0, 0x12345678);
1270   saddr = g_inet_socket_address_new_from_string ("127.0.0.2", 8080);
1271   gst_buffer_add_net_address_meta (buf, saddr);
1272   g_object_unref (saddr);
1273   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtp (h, buf));
1274 
1275   /* Verify the packet we just sent has been dropped */
1276   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
1277 
1278   /* Receive another buffer SSRC=0x12345678 from 127.0.0.1 */
1279   buf = generate_test_buffer (0, 0x12345678);
1280   saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1281   gst_buffer_add_net_address_meta (buf, saddr);
1282   g_object_unref (saddr);
1283   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtp (h, buf));
1284 
1285 
1286   /* Check that we received the other buffer */
1287   buf = gst_harness_pull (h->recv_rtp_h);
1288   fail_unless (buf);
1289   gst_buffer_unref (buf);
1290   fail_unless (had_collision == FALSE);
1291 
1292   session_harness_free (h);
1293 }
1294 
1295 GST_END_TEST;
1296 
1297 
GST_START_TEST(test_ssrc_collision_third_party_favor_new)1298 GST_START_TEST (test_ssrc_collision_third_party_favor_new)
1299 {
1300   SessionHarness *h = session_harness_new ();
1301   GstBuffer *buf;
1302   GSocketAddress *saddr;
1303   gboolean had_collision = FALSE;
1304   guint i;
1305 
1306   g_object_set (h->internal_session, "favor-new", TRUE, NULL);
1307   g_signal_connect (h->internal_session, "on-ssrc-collision",
1308       G_CALLBACK (on_ssrc_collision_cb), &had_collision);
1309 
1310   for (i = 0; i < 4; i++) {
1311     /* Receive 4 buffers SSRC=0x12345678 from 127.0.0.1 to pass probation */
1312     buf = generate_test_buffer (i, 0x12345678);
1313     saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1314     gst_buffer_add_net_address_meta (buf, saddr);
1315     g_object_unref (saddr);
1316     fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtp (h, buf));
1317   }
1318 
1319   /* Check that we received the first 4 buffer */
1320   for (i = 0; i < 4; i++) {
1321     buf = gst_harness_pull (h->recv_rtp_h);
1322     fail_unless (buf);
1323     gst_buffer_unref (buf);
1324   }
1325   fail_unless (had_collision == FALSE);
1326 
1327   /* Receive buffer SSRC=0x12345678 from 127.0.0.2 */
1328   buf = generate_test_buffer (0, 0x12345678);
1329   saddr = g_inet_socket_address_new_from_string ("127.0.0.2", 8080);
1330   gst_buffer_add_net_address_meta (buf, saddr);
1331   g_object_unref (saddr);
1332   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtp (h, buf));
1333 
1334   /* Check that we received the other buffer */
1335   buf = gst_harness_pull (h->recv_rtp_h);
1336   fail_unless (buf);
1337   gst_buffer_unref (buf);
1338   fail_unless (had_collision == FALSE);
1339 
1340   session_harness_free (h);
1341 }
1342 
1343 GST_END_TEST;
1344 
GST_START_TEST(test_ssrc_collision_never_send_on_non_internal_source)1345 GST_START_TEST (test_ssrc_collision_never_send_on_non_internal_source)
1346 {
1347   SessionHarness *h = session_harness_new ();
1348   GstBuffer *buf;
1349   GstEvent *ev;
1350   GSocketAddress *saddr;
1351   gboolean had_collision = FALSE;
1352 
1353   g_signal_connect (h->internal_session, "on-ssrc-collision",
1354       G_CALLBACK (on_ssrc_collision_cb), &had_collision);
1355 
1356   /* Push SDES with identical SSRC as what we will use for sending RTP,
1357      establishing this as a non-internal SSRC */
1358   buf = gst_rtcp_buffer_new (1400);
1359   add_rtcp_sdes_packet (buf, 0xdeadbeef, "test@foo.bar");
1360   saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080);
1361   gst_buffer_add_net_address_meta (buf, saddr);
1362   session_harness_recv_rtcp (h, buf);
1363   g_object_unref (saddr);
1364 
1365   fail_unless (had_collision == FALSE);
1366 
1367   /* Push RTP buffer making our internal SSRC=0xdeadbeef */
1368   buf = generate_test_buffer (0, 0xdeadbeef);
1369   fail_unless_equals_int (GST_FLOW_OK, session_harness_send_rtp (h, buf));
1370 
1371   fail_unless (had_collision == TRUE);
1372 
1373   /* verify we drop this packet because of SSRC collision */
1374   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->send_rtp_h));
1375   /* Verify the packet we just sent is not being boomeranged back to us
1376      as a received packet! */
1377   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
1378 
1379   /* verify we get an upstream GstRTPCollision event */
1380   while ((ev = gst_harness_try_pull_upstream_event (h->send_rtp_h)) != NULL) {
1381     if (GST_EVENT_CUSTOM_UPSTREAM == GST_EVENT_TYPE (ev) &&
1382         gst_event_has_name (ev, "GstRTPCollision"))
1383       break;
1384     gst_event_unref (ev);
1385   }
1386   fail_unless (ev != NULL);
1387   gst_event_unref (ev);
1388 
1389   /* Push another RTP buffer and verify that one is not send or "received" as well */
1390   buf = generate_test_buffer (1, 0xdeadbeef);
1391   fail_unless_equals_int (GST_FLOW_OK, session_harness_send_rtp (h, buf));
1392   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->send_rtp_h));
1393   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
1394 
1395   /* now generate a BYE to the non-internal SSRC */
1396   session_harness_produce_rtcp (h, 1);
1397 
1398   /* and verify we can now send using that SSRC */
1399   buf = generate_test_buffer (2, 0xdeadbeef);
1400   fail_unless_equals_int (GST_FLOW_OK, session_harness_send_rtp (h, buf));
1401   fail_unless_equals_int (1, gst_harness_buffers_in_queue (h->send_rtp_h));
1402   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h));
1403 
1404   session_harness_free (h);
1405 }
1406 
1407 GST_END_TEST;
1408 
GST_START_TEST(test_request_fir)1409 GST_START_TEST (test_request_fir)
1410 {
1411   SessionHarness *h = session_harness_new ();
1412   GstBuffer *buf;
1413   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1414   GstRTCPPacket rtcp_packet;
1415   guint8 *fci_data;
1416 
1417   /* add FIR-capabilites to our caps */
1418   gst_caps_set_simple (h->caps, "rtcp-fb-ccm-fir", G_TYPE_BOOLEAN, TRUE, NULL);
1419   /* clear pt-map to removed the cached caps without fir */
1420   g_signal_emit_by_name (h->session, "clear-pt-map");
1421 
1422   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1423 
1424   /* Receive a RTP buffer from the wire from 2 different ssrcs */
1425   fail_unless_equals_int (GST_FLOW_OK,
1426       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
1427   fail_unless_equals_int (GST_FLOW_OK,
1428       session_harness_recv_rtp (h, generate_test_buffer (0, 0x87654321)));
1429 
1430   /* fix to make the test deterministic: We need to wait for the RTCP-thread
1431      to have settled to ensure the key-unit will considered once released */
1432   gst_test_clock_wait_for_next_pending_id (h->testclock, NULL);
1433 
1434   /* request FIR for both SSRCs */
1435   session_harness_force_key_unit (h, 0, 0x12345678, TEST_BUF_PT, NULL, NULL);
1436   session_harness_force_key_unit (h, 0, 0x87654321, TEST_BUF_PT, NULL, NULL);
1437 
1438   session_harness_produce_rtcp (h, 1);
1439   buf = session_harness_pull_rtcp (h);
1440 
1441   fail_unless (gst_rtcp_buffer_validate (buf));
1442   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
1443   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
1444   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
1445 
1446   /* first a Receiver Report */
1447   fail_unless_equals_int (GST_RTCP_TYPE_RR,
1448       gst_rtcp_packet_get_type (&rtcp_packet));
1449   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1450 
1451   /* then a SDES */
1452   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
1453       gst_rtcp_packet_get_type (&rtcp_packet));
1454   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1455 
1456   /* and then our FIR */
1457   fail_unless_equals_int (GST_RTCP_TYPE_PSFB,
1458       gst_rtcp_packet_get_type (&rtcp_packet));
1459   fail_unless_equals_int (GST_RTCP_PSFB_TYPE_FIR,
1460       gst_rtcp_packet_fb_get_type (&rtcp_packet));
1461 
1462   /* FIR has sender-ssrc as normal, but media-ssrc set to 0, because
1463      it can have multiple media-ssrcs in its fci-data */
1464   fail_unless_equals_int (0xDEADBEEF,
1465       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
1466   fail_unless_equals_int (0, gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
1467   fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
1468 
1469   fail_unless_equals_int (16,
1470       gst_rtcp_packet_fb_get_fci_length (&rtcp_packet) * sizeof (guint32));
1471 
1472   /* verify the FIR contains both SSRCs */
1473   fail_unless_equals_int (0x87654321, GST_READ_UINT32_BE (fci_data));
1474   fail_unless_equals_int (1, fci_data[4]);
1475   fail_unless_equals_int (0, fci_data[5]);
1476   fail_unless_equals_int (0, fci_data[6]);
1477   fail_unless_equals_int (0, fci_data[7]);
1478   fci_data += 8;
1479 
1480   fail_unless_equals_int (0x12345678, GST_READ_UINT32_BE (fci_data));
1481   fail_unless_equals_int (1, fci_data[4]);
1482   fail_unless_equals_int (0, fci_data[5]);
1483   fail_unless_equals_int (0, fci_data[6]);
1484   fail_unless_equals_int (0, fci_data[7]);
1485 
1486   gst_rtcp_buffer_unmap (&rtcp);
1487   gst_buffer_unref (buf);
1488   session_harness_free (h);
1489 }
1490 
1491 GST_END_TEST;
1492 
GST_START_TEST(test_request_pli)1493 GST_START_TEST (test_request_pli)
1494 {
1495   SessionHarness *h = session_harness_new ();
1496   GstBuffer *buf;
1497   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1498   GstRTCPPacket rtcp_packet;
1499 
1500   /* add PLI-capabilites to our caps */
1501   gst_caps_set_simple (h->caps, "rtcp-fb-nack-pli", G_TYPE_BOOLEAN, TRUE, NULL);
1502   /* clear pt-map to removed the cached caps without PLI */
1503   g_signal_emit_by_name (h->session, "clear-pt-map");
1504 
1505   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1506 
1507   /* Receive a RTP buffer from the wire */
1508   fail_unless_equals_int (GST_FLOW_OK,
1509       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
1510 
1511   /* Wait for first regular RTCP to be sent so that we are clear to send early RTCP */
1512   session_harness_produce_rtcp (h, 1);
1513   gst_buffer_unref (session_harness_pull_rtcp (h));
1514 
1515   /* request PLI */
1516   session_harness_force_key_unit (h, 0, 0x12345678, TEST_BUF_PT, NULL, NULL);
1517 
1518   /* PLI should be produced immediately as early RTCP is allowed. Pull buffer
1519      without advancing the clock to ensure this is the case */
1520   buf = session_harness_pull_rtcp (h);
1521   fail_unless (gst_rtcp_buffer_validate (buf));
1522   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
1523   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
1524   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
1525 
1526   /* first a Receiver Report */
1527   fail_unless_equals_int (GST_RTCP_TYPE_RR,
1528       gst_rtcp_packet_get_type (&rtcp_packet));
1529   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1530 
1531   /* then a SDES */
1532   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
1533       gst_rtcp_packet_get_type (&rtcp_packet));
1534   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1535 
1536   /* and then our PLI */
1537   fail_unless_equals_int (GST_RTCP_TYPE_PSFB,
1538       gst_rtcp_packet_get_type (&rtcp_packet));
1539   fail_unless_equals_int (GST_RTCP_PSFB_TYPE_PLI,
1540       gst_rtcp_packet_fb_get_type (&rtcp_packet));
1541 
1542   fail_unless_equals_int (0xDEADBEEF,
1543       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
1544   fail_unless_equals_int (0x12345678,
1545       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
1546   fail_unless_equals_int (0, gst_rtcp_packet_fb_get_fci_length (&rtcp_packet));
1547 
1548   gst_rtcp_buffer_unmap (&rtcp);
1549   gst_buffer_unref (buf);
1550   session_harness_free (h);
1551 }
1552 
1553 GST_END_TEST;
1554 
GST_START_TEST(test_request_fir_after_pli_in_caps)1555 GST_START_TEST (test_request_fir_after_pli_in_caps)
1556 {
1557   SessionHarness *h = session_harness_new ();
1558   GstBuffer *buf;
1559   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1560   GstRTCPPacket rtcp_packet;
1561   guint8 *fci_data;
1562 
1563   /* add PLI-capabilites to our caps */
1564   gst_caps_set_simple (h->caps, "rtcp-fb-nack-pli", G_TYPE_BOOLEAN, TRUE, NULL);
1565   /* clear pt-map to removed the cached caps without PLI */
1566   g_signal_emit_by_name (h->session, "clear-pt-map");
1567 
1568   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1569 
1570   /* Receive a RTP buffer from the wire */
1571   fail_unless_equals_int (GST_FLOW_OK,
1572       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
1573 
1574   /* Wait for first regular RTCP to be sent so that we are clear to send early RTCP */
1575   session_harness_produce_rtcp (h, 1);
1576   gst_buffer_unref (session_harness_pull_rtcp (h));
1577 
1578   /* request PLI */
1579   session_harness_force_key_unit (h, 0, 0x12345678, TEST_BUF_PT, NULL, NULL);
1580 
1581   /* PLI should be produced immediately as early RTCP is allowed. Pull buffer
1582      without advancing the clock to ensure this is the case */
1583   buf = session_harness_pull_rtcp (h);
1584   fail_unless (gst_rtcp_buffer_validate (buf));
1585   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
1586   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
1587   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
1588 
1589   /* first a Receiver Report */
1590   fail_unless_equals_int (GST_RTCP_TYPE_RR,
1591       gst_rtcp_packet_get_type (&rtcp_packet));
1592   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1593 
1594   /* then a SDES */
1595   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
1596       gst_rtcp_packet_get_type (&rtcp_packet));
1597   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1598 
1599   /* and then our PLI */
1600   fail_unless_equals_int (GST_RTCP_TYPE_PSFB,
1601       gst_rtcp_packet_get_type (&rtcp_packet));
1602   fail_unless_equals_int (GST_RTCP_PSFB_TYPE_PLI,
1603       gst_rtcp_packet_fb_get_type (&rtcp_packet));
1604 
1605   fail_unless_equals_int (0xDEADBEEF,
1606       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
1607   fail_unless_equals_int (0x12345678,
1608       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
1609   fail_unless_equals_int (0, gst_rtcp_packet_fb_get_fci_length (&rtcp_packet));
1610 
1611   gst_rtcp_buffer_unmap (&rtcp);
1612   gst_buffer_unref (buf);
1613 
1614   /* Rebuild the caps */
1615   gst_caps_unref (h->caps);
1616   h->caps = generate_caps ();
1617 
1618   /* add FIR-capabilites to our caps */
1619   gst_caps_set_simple (h->caps, "rtcp-fb-ccm-fir", G_TYPE_BOOLEAN, TRUE, NULL);
1620   /* clear pt-map to removed the cached caps without fir */
1621   g_signal_emit_by_name (h->session, "clear-pt-map");
1622 
1623   /* Receive a RTP buffer from the wire */
1624   fail_unless_equals_int (GST_FLOW_OK,
1625       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
1626 
1627   /* fix to make the test deterministic: We need to wait for the RTCP-thread
1628      to have settled to ensure the key-unit will considered once released */
1629   gst_test_clock_wait_for_next_pending_id (h->testclock, NULL);
1630 
1631   /* request FIR */
1632   session_harness_force_key_unit (h, 0, 0x12345678, TEST_BUF_PT, NULL, NULL);
1633 
1634   session_harness_produce_rtcp (h, 1);
1635   buf = session_harness_pull_rtcp (h);
1636 
1637   fail_unless (gst_rtcp_buffer_validate (buf));
1638   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
1639   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
1640   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
1641 
1642   /* first a Receiver Report */
1643   fail_unless_equals_int (GST_RTCP_TYPE_RR,
1644       gst_rtcp_packet_get_type (&rtcp_packet));
1645   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1646 
1647   /* then a SDES */
1648   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
1649       gst_rtcp_packet_get_type (&rtcp_packet));
1650   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1651 
1652   /* and then our FIR */
1653   fail_unless_equals_int (GST_RTCP_TYPE_PSFB,
1654       gst_rtcp_packet_get_type (&rtcp_packet));
1655   fail_unless_equals_int (GST_RTCP_PSFB_TYPE_FIR,
1656       gst_rtcp_packet_fb_get_type (&rtcp_packet));
1657 
1658   /* FIR has sender-ssrc as normal, but media-ssrc set to 0, because
1659      it can have multiple media-ssrcs in its fci-data */
1660   fail_unless_equals_int (0xDEADBEEF,
1661       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
1662   fail_unless_equals_int (0, gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
1663   fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
1664 
1665   fail_unless_equals_int (8,
1666       gst_rtcp_packet_fb_get_fci_length (&rtcp_packet) * sizeof (guint32));
1667 
1668   /* verify the FIR contains the SSRC */
1669   fail_unless_equals_int (0x12345678, GST_READ_UINT32_BE (fci_data));
1670   fail_unless_equals_int (1, fci_data[4]);
1671   fail_unless_equals_int (0, fci_data[5]);
1672   fail_unless_equals_int (0, fci_data[6]);
1673   fail_unless_equals_int (0, fci_data[7]);
1674   fail_unless_equals_int (0, fci_data[7]);
1675 
1676   gst_rtcp_buffer_unmap (&rtcp);
1677   gst_buffer_unref (buf);
1678   session_harness_free (h);
1679 }
1680 
1681 GST_END_TEST;
1682 
GST_START_TEST(test_illegal_rtcp_fb_packet)1683 GST_START_TEST (test_illegal_rtcp_fb_packet)
1684 {
1685   SessionHarness *h = session_harness_new ();
1686   GstBuffer *buf;
1687   /* Zero length RTCP feedback packet (reduced size) */
1688   const guint8 rtcp_zero_fb_pkt[] = { 0x8f, 0xce, 0x00, 0x00 };
1689 
1690   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1691 
1692   buf = gst_buffer_new_and_alloc (sizeof (rtcp_zero_fb_pkt));
1693   gst_buffer_fill (buf, 0, rtcp_zero_fb_pkt, sizeof (rtcp_zero_fb_pkt));
1694   GST_BUFFER_DTS (buf) = GST_BUFFER_PTS (buf) = G_GUINT64_CONSTANT (0);
1695 
1696   /* Push the packet, this did previously crash because length of packet was
1697    * never validated. */
1698   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buf));
1699 
1700   session_harness_free (h);
1701 }
1702 
1703 GST_END_TEST;
1704 
1705 typedef struct
1706 {
1707   GCond *cond;
1708   GMutex *mutex;
1709   gboolean fired;
1710 } FeedbackRTCPCallbackData;
1711 
1712 static void
feedback_rtcp_cb(GstElement * element,guint fbtype,guint fmt,guint sender_ssrc,guint media_ssrc,GstBuffer * fci,FeedbackRTCPCallbackData * cb_data)1713 feedback_rtcp_cb (GstElement * element, guint fbtype, guint fmt,
1714     guint sender_ssrc, guint media_ssrc, GstBuffer * fci,
1715     FeedbackRTCPCallbackData * cb_data)
1716 {
1717   g_mutex_lock (cb_data->mutex);
1718   cb_data->fired = TRUE;
1719   g_cond_wait (cb_data->cond, cb_data->mutex);
1720   g_mutex_unlock (cb_data->mutex);
1721 }
1722 
1723 static void *
send_feedback_rtcp(SessionHarness * h)1724 send_feedback_rtcp (SessionHarness * h)
1725 {
1726   GstRTCPPacket packet;
1727   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1728   GstBuffer *buffer = gst_rtcp_buffer_new (1000);
1729 
1730   fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
1731   fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_PSFB, &packet));
1732   gst_rtcp_packet_fb_set_type (&packet, GST_RTCP_PSFB_TYPE_PLI);
1733   gst_rtcp_packet_fb_set_fci_length (&packet, 0);
1734   gst_rtcp_packet_fb_set_media_ssrc (&packet, 0xABE2B0B);
1735   gst_rtcp_packet_fb_set_media_ssrc (&packet, 0xDEADBEEF);
1736   gst_rtcp_buffer_unmap (&rtcp);
1737   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtcp (h, buffer));
1738 
1739   return NULL;
1740 }
1741 
GST_START_TEST(test_feedback_rtcp_race)1742 GST_START_TEST (test_feedback_rtcp_race)
1743 {
1744   SessionHarness *h = session_harness_new ();
1745 
1746   GCond cond;
1747   GMutex mutex;
1748   FeedbackRTCPCallbackData cb_data;
1749   GThread *send_rtcp_thread;
1750 
1751   g_cond_init (&cond);
1752   g_mutex_init (&mutex);
1753   cb_data.cond = &cond;
1754   cb_data.mutex = &mutex;
1755   cb_data.fired = FALSE;
1756   g_signal_connect (h->internal_session, "on-feedback-rtcp",
1757       G_CALLBACK (feedback_rtcp_cb), &cb_data);
1758 
1759   /* Push RTP buffer making external source with SSRC=0xDEADBEEF */
1760   fail_unless_equals_int (GST_FLOW_OK, session_harness_recv_rtp (h,
1761           generate_test_buffer (0, 0xDEADBEEF)));
1762 
1763   /* Push feedback RTCP with media SSRC=0xDEADBEEF */
1764   send_rtcp_thread = g_thread_new (NULL, (GThreadFunc) send_feedback_rtcp, h);
1765 
1766   /* Waiting for feedback RTCP callback to fire */
1767   while (!cb_data.fired)
1768     g_usleep (G_USEC_PER_SEC / 100);
1769 
1770   /* While send_rtcp_thread thread is waiting for our signal
1771      advance the clock by 30sec triggering removal of 0xDEADBEEF,
1772      as if the source was inactive for too long */
1773   session_harness_advance_and_crank (h, GST_SECOND * 30);
1774   gst_buffer_unref (session_harness_pull_rtcp (h));
1775 
1776   /* Let send_rtcp_thread finish */
1777   g_mutex_lock (&mutex);
1778   g_cond_signal (&cond);
1779   g_mutex_unlock (&mutex);
1780   g_thread_join (send_rtcp_thread);
1781 
1782   session_harness_free (h);
1783 }
1784 
1785 GST_END_TEST;
1786 
GST_START_TEST(test_dont_send_rtcp_while_idle)1787 GST_START_TEST (test_dont_send_rtcp_while_idle)
1788 {
1789   SessionHarness *h = session_harness_new ();
1790 
1791   /* verify the RTCP thread has not started */
1792   fail_unless_equals_int (0, gst_test_clock_peek_id_count (h->testclock));
1793   /* and that no RTCP has been pushed */
1794   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->rtcp_h));
1795 
1796   session_harness_free (h);
1797 }
1798 
1799 GST_END_TEST;
1800 
GST_START_TEST(test_send_rtcp_when_signalled)1801 GST_START_TEST (test_send_rtcp_when_signalled)
1802 {
1803   SessionHarness *h = session_harness_new ();
1804   gboolean ret;
1805 
1806   /* verify the RTCP thread has not started */
1807   fail_unless_equals_int (0, gst_test_clock_peek_id_count (h->testclock));
1808   /* and that no RTCP has been pushed */
1809   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->rtcp_h));
1810 
1811   /* then ask explicitly to send RTCP */
1812   g_signal_emit_by_name (h->internal_session,
1813       "send-rtcp-full", GST_SECOND, &ret);
1814   /* this is FALSE due to no next RTCP check time */
1815   fail_unless (ret == FALSE);
1816 
1817   /* "crank" and verify RTCP now was sent */
1818   session_harness_crank_clock (h);
1819   gst_buffer_unref (session_harness_pull_rtcp (h));
1820 
1821   session_harness_free (h);
1822 }
1823 
1824 GST_END_TEST;
1825 
1826 static void
validate_sdes_priv(GstBuffer * buf,const char * name_ref,const char * value)1827 validate_sdes_priv (GstBuffer * buf, const char *name_ref, const char *value)
1828 {
1829   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1830   GstRTCPPacket pkt;
1831 
1832   fail_unless (gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp));
1833 
1834   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &pkt));
1835 
1836   do {
1837     if (gst_rtcp_packet_get_type (&pkt) == GST_RTCP_TYPE_SDES) {
1838       fail_unless (gst_rtcp_packet_sdes_first_entry (&pkt));
1839 
1840       do {
1841         GstRTCPSDESType type;
1842         guint8 len;
1843         guint8 *data;
1844 
1845         fail_unless (gst_rtcp_packet_sdes_get_entry (&pkt, &type, &len, &data));
1846 
1847         if (type == GST_RTCP_SDES_PRIV) {
1848           char *name = g_strndup ((const gchar *) &data[1], data[0]);
1849           len -= data[0] + 1;
1850           data += data[0] + 1;
1851 
1852           fail_unless_equals_int (len, strlen (value));
1853           fail_unless (!strncmp (value, (char *) data, len));
1854           fail_unless_equals_string (name, name_ref);
1855           g_free (name);
1856           goto sdes_done;
1857         }
1858       } while (gst_rtcp_packet_sdes_next_entry (&pkt));
1859 
1860       g_assert_not_reached ();
1861     }
1862   } while (gst_rtcp_packet_move_to_next (&pkt));
1863 
1864   g_assert_not_reached ();
1865 
1866 sdes_done:
1867 
1868   fail_unless (gst_rtcp_buffer_unmap (&rtcp));
1869 
1870 }
1871 
GST_START_TEST(test_change_sent_sdes)1872 GST_START_TEST (test_change_sent_sdes)
1873 {
1874   SessionHarness *h = session_harness_new ();
1875   GstStructure *s;
1876   GstBuffer *buf;
1877   gboolean ret;
1878   GstFlowReturn res;
1879 
1880   /* verify the RTCP thread has not started */
1881   fail_unless_equals_int (0, gst_test_clock_peek_id_count (h->testclock));
1882   /* and that no RTCP has been pushed */
1883   fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->rtcp_h));
1884 
1885   s = gst_structure_new ("application/x-rtp-source-sdes",
1886       "other", G_TYPE_STRING, "first", NULL);
1887   g_object_set (h->internal_session, "sdes", s, NULL);
1888   gst_structure_free (s);
1889 
1890   /* then ask explicitly to send RTCP */
1891   g_signal_emit_by_name (h->internal_session,
1892       "send-rtcp-full", GST_SECOND, &ret);
1893   /* this is FALSE due to no next RTCP check time */
1894   fail_unless (ret == FALSE);
1895 
1896   /* "crank" and verify RTCP now was sent */
1897   session_harness_crank_clock (h);
1898   buf = session_harness_pull_rtcp (h);
1899   fail_unless (buf);
1900   validate_sdes_priv (buf, "other", "first");
1901   gst_buffer_unref (buf);
1902 
1903   /* Change the SDES */
1904   s = gst_structure_new ("application/x-rtp-source-sdes",
1905       "other", G_TYPE_STRING, "second", NULL);
1906   g_object_set (h->internal_session, "sdes", s, NULL);
1907   gst_structure_free (s);
1908 
1909   /* Send an RTP packet */
1910   buf = generate_test_buffer (22, 10000);
1911   res = session_harness_send_rtp (h, buf);
1912   fail_unless_equals_int (GST_FLOW_OK, res);
1913 
1914   /* "crank" enough to ensure a RTCP packet has been produced ! */
1915   session_harness_crank_clock (h);
1916   session_harness_crank_clock (h);
1917   session_harness_crank_clock (h);
1918   session_harness_crank_clock (h);
1919   session_harness_crank_clock (h);
1920   session_harness_crank_clock (h);
1921   session_harness_crank_clock (h);
1922   session_harness_crank_clock (h);
1923   session_harness_crank_clock (h);
1924   session_harness_crank_clock (h);
1925 
1926   /* and verify RTCP now was sent with new SDES */
1927   buf = session_harness_pull_rtcp (h);
1928   validate_sdes_priv (buf, "other", "second");
1929   gst_buffer_unref (buf);
1930 
1931   session_harness_free (h);
1932 }
1933 
1934 GST_END_TEST;
1935 
GST_START_TEST(test_request_nack)1936 GST_START_TEST (test_request_nack)
1937 {
1938   SessionHarness *h = session_harness_new ();
1939   GstBuffer *buf;
1940   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
1941   GstRTCPPacket rtcp_packet;
1942   guint8 *fci_data;
1943   guint32 fci_length;
1944 
1945   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
1946 
1947   /* Receive a RTP buffer from the wire */
1948   fail_unless_equals_int (GST_FLOW_OK,
1949       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
1950 
1951   /* Wait for first regular RTCP to be sent so that we are clear to send early RTCP */
1952   session_harness_produce_rtcp (h, 1);
1953   gst_buffer_unref (session_harness_pull_rtcp (h));
1954 
1955   /* request NACK immediately */
1956   session_harness_rtp_retransmission_request (h, 0x12345678, 1234, 0, 0, 0);
1957 
1958   /* NACK should be produced immediately as early RTCP is allowed. Pull buffer
1959      without advancing the clock to ensure this is the case */
1960   buf = session_harness_pull_rtcp (h);
1961 
1962   fail_unless (gst_rtcp_buffer_validate (buf));
1963   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
1964   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
1965   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
1966 
1967   /* first a Receiver Report */
1968   fail_unless_equals_int (GST_RTCP_TYPE_RR,
1969       gst_rtcp_packet_get_type (&rtcp_packet));
1970   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1971 
1972   /* then a SDES */
1973   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
1974       gst_rtcp_packet_get_type (&rtcp_packet));
1975   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
1976 
1977   /* and then our NACK */
1978   fail_unless_equals_int (GST_RTCP_TYPE_RTPFB,
1979       gst_rtcp_packet_get_type (&rtcp_packet));
1980   fail_unless_equals_int (GST_RTCP_RTPFB_TYPE_NACK,
1981       gst_rtcp_packet_fb_get_type (&rtcp_packet));
1982 
1983   fail_unless_equals_int (0xDEADBEEF,
1984       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
1985   fail_unless_equals_int (0x12345678,
1986       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
1987 
1988   fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
1989   fci_length =
1990       gst_rtcp_packet_fb_get_fci_length (&rtcp_packet) * sizeof (guint32);
1991   fail_unless_equals_int (4, fci_length);
1992   fail_unless_equals_int (GST_READ_UINT32_BE (fci_data), 1234L << 16);
1993 
1994   gst_rtcp_buffer_unmap (&rtcp);
1995   gst_buffer_unref (buf);
1996 
1997   session_harness_free (h);
1998 }
1999 
2000 GST_END_TEST;
2001 
2002 typedef struct
2003 {
2004   gulong id;
2005   GstPad *pad;
2006   GMutex mutex;
2007   GCond cond;
2008   gboolean blocked;
2009 } BlockingProbeData;
2010 
2011 static GstPadProbeReturn
on_rtcp_pad_blocked(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)2012 on_rtcp_pad_blocked (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
2013 {
2014   BlockingProbeData *probe = user_data;
2015 
2016   g_mutex_lock (&probe->mutex);
2017   probe->blocked = TRUE;
2018   g_cond_signal (&probe->cond);
2019   g_mutex_unlock (&probe->mutex);
2020 
2021   return GST_PAD_PROBE_OK;
2022 }
2023 
2024 static void
session_harness_block_rtcp(SessionHarness * h,BlockingProbeData * probe)2025 session_harness_block_rtcp (SessionHarness * h, BlockingProbeData * probe)
2026 {
2027   probe->pad = gst_element_get_static_pad (h->session, "send_rtcp_src");
2028   fail_unless (probe->pad);
2029 
2030   g_mutex_init (&probe->mutex);
2031   g_cond_init (&probe->cond);
2032   probe->blocked = FALSE;
2033   probe->id = gst_pad_add_probe (probe->pad,
2034       GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER |
2035       GST_PAD_PROBE_TYPE_BUFFER_LIST, on_rtcp_pad_blocked, probe, NULL);
2036 
2037   g_mutex_lock (&probe->mutex);
2038   while (!probe->blocked) {
2039     session_harness_crank_clock (h);
2040     g_cond_wait (&probe->cond, &probe->mutex);
2041   }
2042   g_mutex_unlock (&probe->mutex);
2043 }
2044 
2045 static void
session_harness_unblock_rtcp(SessionHarness * h,BlockingProbeData * probe)2046 session_harness_unblock_rtcp (SessionHarness * h, BlockingProbeData * probe)
2047 {
2048   gst_pad_remove_probe (probe->pad, probe->id);
2049   gst_object_unref (probe->pad);
2050   g_mutex_clear (&probe->mutex);
2051 }
2052 
GST_START_TEST(test_request_nack_surplus)2053 GST_START_TEST (test_request_nack_surplus)
2054 {
2055   SessionHarness *h = session_harness_new ();
2056   GstRTCPPacket rtcp_packet;
2057   BlockingProbeData probe;
2058   GstBuffer *buf;
2059   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2060   guint8 *fci_data;
2061   gint i;
2062   GstStructure *sdes;
2063 
2064   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
2065 
2066   /* sdes cname has variable size, fix it */
2067   g_object_get (h->internal_session, "sdes", &sdes, NULL);
2068   gst_structure_set (sdes, "cname", G_TYPE_STRING, "user@test", NULL);
2069   g_object_set (h->internal_session, "sdes", sdes, NULL);
2070   gst_structure_free (sdes);
2071 
2072   /* Receive a RTP buffer from the wire */
2073   fail_unless_equals_int (GST_FLOW_OK,
2074       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
2075 
2076   /* Block on first regular RTCP so we can fill the nack list */
2077   session_harness_block_rtcp (h, &probe);
2078 
2079   /* request 400 NACK with 17 seqnum distance to optain the worst possible
2080    * packing  */
2081   for (i = 0; i < 350; i++)
2082     session_harness_rtp_retransmission_request (h, 0x12345678, 1234 + i * 17,
2083         0, 0, 0);
2084   /* and the last 50 with a 2s deadline */
2085   for (i = 350; i < 400; i++)
2086     session_harness_rtp_retransmission_request (h, 0x12345678, 1234 + i * 17,
2087         0, 2000, 0);
2088 
2089   /* Unblock and wait for the regular and first early packet */
2090   session_harness_unblock_rtcp (h, &probe);
2091   session_harness_produce_rtcp (h, 2);
2092 
2093   /* Move time forward, so that only the remaining 50 are still up to date */
2094   session_harness_advance_and_crank (h, GST_SECOND);
2095   session_harness_produce_rtcp (h, 3);
2096 
2097   /* ignore the regular RTCP packet */
2098   buf = session_harness_pull_rtcp (h);
2099   gst_buffer_unref (buf);
2100 
2101   /* validate the first early RTCP which should hold 335 Nack */
2102   buf = session_harness_pull_rtcp (h);
2103 
2104   fail_unless (gst_rtcp_buffer_validate (buf));
2105   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
2106   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
2107   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
2108 
2109   /* first a Receiver Report */
2110   fail_unless_equals_int (GST_RTCP_TYPE_RR,
2111       gst_rtcp_packet_get_type (&rtcp_packet));
2112   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2113 
2114   /* then a SDES */
2115   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
2116       gst_rtcp_packet_get_type (&rtcp_packet));
2117   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2118 
2119   /* and then our NACK */
2120   fail_unless_equals_int (GST_RTCP_TYPE_RTPFB,
2121       gst_rtcp_packet_get_type (&rtcp_packet));
2122   fail_unless_equals_int (GST_RTCP_RTPFB_TYPE_NACK,
2123       gst_rtcp_packet_fb_get_type (&rtcp_packet));
2124 
2125   fail_unless_equals_int (0xDEADBEEF,
2126       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
2127   fail_unless_equals_int (0x12345678,
2128       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
2129 
2130   fail_unless_equals_int (340,
2131       gst_rtcp_packet_fb_get_fci_length (&rtcp_packet));
2132   fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
2133   fail_unless_equals_int (GST_READ_UINT32_BE (fci_data), 1234L << 16);
2134 
2135   gst_rtcp_buffer_unmap (&rtcp);
2136   gst_buffer_unref (buf);
2137 
2138   /* validate the second early RTCP which should hold 50 Nack */
2139   buf = session_harness_pull_rtcp (h);
2140 
2141   fail_unless (gst_rtcp_buffer_validate (buf));
2142   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
2143   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
2144   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
2145 
2146   /* first a Receiver Report */
2147   fail_unless_equals_int (GST_RTCP_TYPE_RR,
2148       gst_rtcp_packet_get_type (&rtcp_packet));
2149   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2150 
2151   /* then a SDES */
2152   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
2153       gst_rtcp_packet_get_type (&rtcp_packet));
2154   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2155 
2156   /* and then our NACK */
2157   fail_unless_equals_int (GST_RTCP_TYPE_RTPFB,
2158       gst_rtcp_packet_get_type (&rtcp_packet));
2159   fail_unless_equals_int (GST_RTCP_RTPFB_TYPE_NACK,
2160       gst_rtcp_packet_fb_get_type (&rtcp_packet));
2161 
2162   fail_unless_equals_int (0xDEADBEEF,
2163       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
2164   fail_unless_equals_int (0x12345678,
2165       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
2166 
2167   fail_unless_equals_int (50, gst_rtcp_packet_fb_get_fci_length (&rtcp_packet));
2168   fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
2169   fail_unless_equals_int (GST_READ_UINT32_BE (fci_data),
2170       (guint16) (1234 + 350 * 17) << 16);
2171 
2172   gst_rtcp_buffer_unmap (&rtcp);
2173   gst_buffer_unref (buf);
2174 
2175   session_harness_free (h);
2176 }
2177 
2178 GST_END_TEST;
2179 
GST_START_TEST(test_request_nack_packing)2180 GST_START_TEST (test_request_nack_packing)
2181 {
2182   SessionHarness *h = session_harness_new ();
2183   GstRTCPPacket rtcp_packet;
2184   BlockingProbeData probe;
2185   GstBuffer *buf;
2186   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2187   guint8 *fci_data;
2188   gint i;
2189 
2190   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
2191 
2192   /* Receive a RTP buffer from the wire */
2193   fail_unless_equals_int (GST_FLOW_OK,
2194       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
2195 
2196   /* Block on first regular RTCP so we can fill the nack list */
2197   session_harness_block_rtcp (h, &probe);
2198 
2199   /* append 16 consecutive seqnum */
2200   for (i = 1; i < 17; i++)
2201     session_harness_rtp_retransmission_request (h, 0x12345678, 1234 + i,
2202         0, 0, 0);
2203   /* prepend one, still consecutive */
2204   session_harness_rtp_retransmission_request (h, 0x12345678, 1234, 0, 0, 0);
2205   /* update it */
2206   session_harness_rtp_retransmission_request (h, 0x12345678, 1234, 0, 0, 0);
2207 
2208   /* Unblock and wait for the regular and first early packet */
2209   session_harness_unblock_rtcp (h, &probe);
2210   session_harness_produce_rtcp (h, 2);
2211 
2212   /* ignore the regular RTCP packet */
2213   buf = session_harness_pull_rtcp (h);
2214   gst_buffer_unref (buf);
2215 
2216   /* validate the early RTCP which should hold 1 Nack */
2217   buf = session_harness_pull_rtcp (h);
2218 
2219   fail_unless (gst_rtcp_buffer_validate (buf));
2220   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
2221   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
2222   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
2223 
2224   /* first a Receiver Report */
2225   fail_unless_equals_int (GST_RTCP_TYPE_RR,
2226       gst_rtcp_packet_get_type (&rtcp_packet));
2227   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2228 
2229   /* then a SDES */
2230   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
2231       gst_rtcp_packet_get_type (&rtcp_packet));
2232   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2233 
2234   /* and then our NACK */
2235   fail_unless_equals_int (GST_RTCP_TYPE_RTPFB,
2236       gst_rtcp_packet_get_type (&rtcp_packet));
2237   fail_unless_equals_int (GST_RTCP_RTPFB_TYPE_NACK,
2238       gst_rtcp_packet_fb_get_type (&rtcp_packet));
2239 
2240   fail_unless_equals_int (0xDEADBEEF,
2241       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
2242   fail_unless_equals_int (0x12345678,
2243       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
2244 
2245   fail_unless_equals_int (1, gst_rtcp_packet_fb_get_fci_length (&rtcp_packet));
2246   fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
2247   fail_unless_equals_int (GST_READ_UINT32_BE (fci_data), 1234L << 16 | 0xFFFF);
2248 
2249   gst_rtcp_buffer_unmap (&rtcp);
2250   gst_buffer_unref (buf);
2251 
2252   session_harness_free (h);
2253 }
2254 
2255 GST_END_TEST;
2256 
GST_START_TEST(test_disable_sr_timestamp)2257 GST_START_TEST (test_disable_sr_timestamp)
2258 {
2259   SessionHarness *h = session_harness_new ();
2260   GstBuffer *buf;
2261   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2262   GstRTCPPacket rtcp_packet;
2263   guint64 ntptime;
2264   guint32 rtptime;
2265 
2266   g_object_set (h->internal_session, "disable-sr-timestamp", TRUE, NULL);
2267 
2268   /* Push RTP buffer to make sure RTCP-thread have started */
2269   fail_unless_equals_int (GST_FLOW_OK,
2270       session_harness_send_rtp (h, generate_test_buffer (0, 0xDEADBEEF)));
2271 
2272   /* crank the RTCP-thread and pull out rtcp, generating a stats-callback */
2273   session_harness_crank_clock (h);
2274   buf = session_harness_pull_rtcp (h);
2275 
2276   gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcp);
2277 
2278   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
2279 
2280   fail_unless_equals_int (GST_RTCP_TYPE_SR,
2281       gst_rtcp_packet_get_type (&rtcp_packet));
2282 
2283   gst_rtcp_packet_sr_get_sender_info (&rtcp_packet, NULL, &ntptime, &rtptime,
2284       NULL, NULL);
2285 
2286   fail_unless_equals_uint64 (ntptime, 0);
2287   fail_unless (rtptime == 0);
2288 
2289   gst_rtcp_buffer_unmap (&rtcp);
2290   gst_buffer_unref (buf);
2291 
2292   session_harness_free (h);
2293 }
2294 
2295 GST_END_TEST;
2296 
2297 static guint
on_sending_nacks(GObject * internal_session,guint sender_ssrc,guint media_ssrc,GArray * nacks,GstBuffer * buffer)2298 on_sending_nacks (GObject * internal_session, guint sender_ssrc,
2299     guint media_ssrc, GArray * nacks, GstBuffer * buffer)
2300 {
2301   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2302   GstRTCPPacket packet;
2303   guint16 seqnum = g_array_index (nacks, guint16, 0);
2304   guint8 *data;
2305 
2306   if (seqnum == 1235)
2307     return 0;
2308 
2309   fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
2310   fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_APP, &packet));
2311 
2312   gst_rtcp_packet_app_set_ssrc (&packet, media_ssrc);
2313   gst_rtcp_packet_app_set_name (&packet, "TEST");
2314 
2315   fail_unless (gst_rtcp_packet_app_set_data_length (&packet, 1));
2316   data = gst_rtcp_packet_app_get_data (&packet);
2317   GST_WRITE_UINT32_BE (data, seqnum);
2318 
2319   gst_rtcp_buffer_unmap (&rtcp);
2320   return 1;
2321 }
2322 
GST_START_TEST(test_on_sending_nacks)2323 GST_START_TEST (test_on_sending_nacks)
2324 {
2325   SessionHarness *h = session_harness_new ();
2326   BlockingProbeData probe;
2327   GstBuffer *buf;
2328   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2329   GstRTCPPacket rtcp_packet;
2330   guint8 *data;
2331 
2332   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
2333 
2334   /* Receive a RTP buffer from the wire */
2335   fail_unless_equals_int (GST_FLOW_OK,
2336       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
2337 
2338   /* Block on first regular RTCP so we can fill the nack list */
2339   session_harness_block_rtcp (h, &probe);
2340   g_signal_connect (h->internal_session, "on-sending-nacks",
2341       G_CALLBACK (on_sending_nacks), NULL);
2342 
2343   /* request NACK immediately */
2344   session_harness_rtp_retransmission_request (h, 0x12345678, 1234, 0, 0, 0);
2345   session_harness_rtp_retransmission_request (h, 0x12345678, 1235, 0, 0, 0);
2346 
2347   session_harness_unblock_rtcp (h, &probe);
2348   gst_buffer_unref (session_harness_pull_rtcp (h));
2349   session_harness_produce_rtcp (h, 2);
2350 
2351   /* first packet only includes seqnum 1234 in an APP FB */
2352   buf = session_harness_pull_rtcp (h);
2353 
2354   fail_unless (gst_rtcp_buffer_validate (buf));
2355   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
2356   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
2357   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
2358 
2359   /* first a Receiver Report */
2360   fail_unless_equals_int (GST_RTCP_TYPE_RR,
2361       gst_rtcp_packet_get_type (&rtcp_packet));
2362   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2363 
2364   /* then a SDES */
2365   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
2366       gst_rtcp_packet_get_type (&rtcp_packet));
2367   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2368 
2369   /* and then our NACK */
2370   fail_unless_equals_int (GST_RTCP_TYPE_APP,
2371       gst_rtcp_packet_get_type (&rtcp_packet));
2372   fail_unless_equals_string ("TEST",
2373       gst_rtcp_packet_app_get_name (&rtcp_packet));
2374 
2375   fail_unless_equals_int (0x12345678,
2376       gst_rtcp_packet_app_get_ssrc (&rtcp_packet));
2377 
2378   fail_unless_equals_int (1,
2379       gst_rtcp_packet_app_get_data_length (&rtcp_packet));
2380   data = gst_rtcp_packet_app_get_data (&rtcp_packet);
2381   fail_unless_equals_int (GST_READ_UINT32_BE (data), 1234L);
2382 
2383   gst_rtcp_buffer_unmap (&rtcp);
2384   gst_buffer_unref (buf);
2385 
2386   /* second will contain seqnum 1235 in a generic nack packet */
2387   buf = session_harness_pull_rtcp (h);
2388 
2389   fail_unless (gst_rtcp_buffer_validate (buf));
2390   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
2391   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
2392   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
2393 
2394   /* first a Receiver Report */
2395   fail_unless_equals_int (GST_RTCP_TYPE_RR,
2396       gst_rtcp_packet_get_type (&rtcp_packet));
2397   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2398 
2399   /* then a SDES */
2400   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
2401       gst_rtcp_packet_get_type (&rtcp_packet));
2402   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2403 
2404   /* and then our NACK */
2405   fail_unless_equals_int (GST_RTCP_TYPE_RTPFB,
2406       gst_rtcp_packet_get_type (&rtcp_packet));
2407   fail_unless_equals_int (GST_RTCP_RTPFB_TYPE_NACK,
2408       gst_rtcp_packet_fb_get_type (&rtcp_packet));
2409 
2410   fail_unless_equals_int (0xDEADBEEF,
2411       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
2412   fail_unless_equals_int (0x12345678,
2413       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
2414 
2415   fail_unless_equals_int (1, gst_rtcp_packet_fb_get_fci_length (&rtcp_packet));
2416   data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
2417   fail_unless_equals_int (GST_READ_UINT32_BE (data), 1235L << 16);
2418 
2419   gst_rtcp_buffer_unmap (&rtcp);
2420   gst_buffer_unref (buf);
2421 
2422   session_harness_free (h);
2423 }
2424 
2425 GST_END_TEST;
2426 
2427 static void
disable_probation_on_new_ssrc(GObject * session,GObject * source)2428 disable_probation_on_new_ssrc (GObject * session, GObject * source)
2429 {
2430   g_object_set (source, "probation", 0, NULL);
2431 }
2432 
GST_START_TEST(test_disable_probation)2433 GST_START_TEST (test_disable_probation)
2434 {
2435   SessionHarness *h = session_harness_new ();
2436 
2437   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
2438   g_signal_connect (h->internal_session, "on-new-ssrc",
2439       G_CALLBACK (disable_probation_on_new_ssrc), NULL);
2440 
2441   /* Receive a RTP buffer from the wire */
2442   fail_unless_equals_int (GST_FLOW_OK,
2443       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
2444 
2445   /* When probation is disabled, the packet should be produced immediately */
2446   fail_unless_equals_int (1, gst_harness_buffers_in_queue (h->recv_rtp_h));
2447 
2448   session_harness_free (h);
2449 }
2450 
2451 GST_END_TEST;
2452 
GST_START_TEST(test_request_late_nack)2453 GST_START_TEST (test_request_late_nack)
2454 {
2455   SessionHarness *h = session_harness_new ();
2456   GstBuffer *buf;
2457   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2458   GstRTCPPacket rtcp_packet;
2459   guint8 *fci_data;
2460   guint32 fci_length;
2461 
2462   g_object_set (h->internal_session, "internal-ssrc", 0xDEADBEEF, NULL);
2463 
2464   /* Receive a RTP buffer from the wire */
2465   fail_unless_equals_int (GST_FLOW_OK,
2466       session_harness_recv_rtp (h, generate_test_buffer (0, 0x12345678)));
2467 
2468   /* Wait for first regular RTCP to be sent so that we are clear to send early RTCP */
2469   session_harness_produce_rtcp (h, 1);
2470   gst_buffer_unref (session_harness_pull_rtcp (h));
2471 
2472   /* request NACK immediately, but also advance the clock, so the request is
2473    * now late, but it should be kept to avoid sending an early rtcp without
2474    * NACK. This would otherwise lead to a stall if the late packet was cause
2475    * by high RTT, we need to send some RTX in order to update that statistic. */
2476   session_harness_rtp_retransmission_request (h, 0x12345678, 1234, 0, 0, 0);
2477   gst_test_clock_advance_time (h->testclock, 100 * GST_USECOND);
2478 
2479   /* NACK should be produced immediately as early RTCP is allowed. Pull buffer
2480      without advancing the clock to ensure this is the case */
2481   buf = session_harness_pull_rtcp (h);
2482 
2483   fail_unless (gst_rtcp_buffer_validate (buf));
2484   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
2485   fail_unless_equals_int (3, gst_rtcp_buffer_get_packet_count (&rtcp));
2486   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &rtcp_packet));
2487 
2488   /* first a Receiver Report */
2489   fail_unless_equals_int (GST_RTCP_TYPE_RR,
2490       gst_rtcp_packet_get_type (&rtcp_packet));
2491   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2492 
2493   /* then a SDES */
2494   fail_unless_equals_int (GST_RTCP_TYPE_SDES,
2495       gst_rtcp_packet_get_type (&rtcp_packet));
2496   fail_unless (gst_rtcp_packet_move_to_next (&rtcp_packet));
2497 
2498   /* and then our NACK */
2499   fail_unless_equals_int (GST_RTCP_TYPE_RTPFB,
2500       gst_rtcp_packet_get_type (&rtcp_packet));
2501   fail_unless_equals_int (GST_RTCP_RTPFB_TYPE_NACK,
2502       gst_rtcp_packet_fb_get_type (&rtcp_packet));
2503 
2504   fail_unless_equals_int (0xDEADBEEF,
2505       gst_rtcp_packet_fb_get_sender_ssrc (&rtcp_packet));
2506   fail_unless_equals_int (0x12345678,
2507       gst_rtcp_packet_fb_get_media_ssrc (&rtcp_packet));
2508 
2509   fci_data = gst_rtcp_packet_fb_get_fci (&rtcp_packet);
2510   fci_length =
2511       gst_rtcp_packet_fb_get_fci_length (&rtcp_packet) * sizeof (guint32);
2512   fail_unless_equals_int (4, fci_length);
2513   fail_unless_equals_int (GST_READ_UINT32_BE (fci_data), 1234L << 16);
2514 
2515   gst_rtcp_buffer_unmap (&rtcp);
2516   gst_buffer_unref (buf);
2517 
2518   session_harness_free (h);
2519 }
2520 
2521 GST_END_TEST;
2522 
2523 static gpointer
_push_caps_events(gpointer user_data)2524 _push_caps_events (gpointer user_data)
2525 {
2526   SessionHarness *h = user_data;
2527   gint payload = 0;
2528   while (h->running) {
2529 
2530     GstCaps *caps = gst_caps_new_simple ("application/x-rtp",
2531         "payload", G_TYPE_INT, payload,
2532         NULL);
2533     gst_harness_set_src_caps (h->recv_rtp_h, caps);
2534     g_thread_yield ();
2535     payload++;
2536   }
2537 
2538   return NULL;
2539 }
2540 
GST_START_TEST(test_clear_pt_map_stress)2541 GST_START_TEST (test_clear_pt_map_stress)
2542 {
2543   SessionHarness *h = session_harness_new ();
2544   GThread *thread;
2545   guint i;
2546 
2547   h->running = TRUE;
2548   thread = g_thread_new (NULL, _push_caps_events, h);
2549 
2550   for (i = 0; i < 1000; i++) {
2551     g_signal_emit_by_name (h->session, "clear-pt-map");
2552     g_thread_yield ();
2553   }
2554 
2555   h->running = FALSE;
2556   g_thread_join (thread);
2557 
2558   session_harness_free (h);
2559 }
2560 
2561 GST_END_TEST;
2562 
2563 static GstBuffer *
generate_stepped_ts_buffer(guint i,gboolean stepped)2564 generate_stepped_ts_buffer (guint i, gboolean stepped)
2565 {
2566   GstBuffer *buf;
2567   guint ts = (TEST_BUF_CLOCK_RATE * i) / 1000;
2568 
2569   if (stepped) {
2570     const int TEST_BUF_CLOCK_STEP = TEST_BUF_CLOCK_RATE / 30;
2571 
2572     ts /= TEST_BUF_CLOCK_STEP;
2573     ts *= TEST_BUF_CLOCK_STEP;
2574   }
2575   GST_LOG ("ts: %" GST_TIME_FORMAT " rtp: %u (%" GST_TIME_FORMAT "), seq: %u\n",
2576       GST_TIME_ARGS (i * GST_MSECOND), ts,
2577       GST_TIME_ARGS (gst_util_uint64_scale_int (GST_SECOND, ts,
2578               TEST_BUF_CLOCK_RATE)), i);
2579 
2580   buf = generate_test_buffer_full (i * GST_MSECOND, i, ts, 0xAAAA, FALSE,
2581       TEST_BUF_PT, 0, 0);
2582   return buf;
2583 }
2584 
2585 static void
test_packet_rate_impl(gboolean stepped)2586 test_packet_rate_impl (gboolean stepped)
2587 {
2588   SessionHarness *h = session_harness_new ();
2589   GstBuffer *buf;
2590   guint i;
2591   const int PROBATION_CNT = 5;
2592   GstStructure *stats;
2593   GObject *source;
2594   guint pktrate;
2595 
2596   /* First do probation */
2597   for (i = 0; i < PROBATION_CNT; i++) {
2598     buf = generate_stepped_ts_buffer (i, stepped);
2599     fail_unless_equals_int (session_harness_recv_rtp (h, buf), GST_FLOW_OK);
2600   }
2601   for (i = 0; i < PROBATION_CNT; i++) {
2602     buf = gst_harness_pull (h->recv_rtp_h);
2603     fail_unless (buf);
2604     gst_buffer_unref (buf);
2605   }
2606 
2607   /* Now run the real test */
2608   for (i = PROBATION_CNT; i < 10000; i++) {
2609     buf = generate_stepped_ts_buffer (i, stepped);
2610     fail_unless_equals_int (session_harness_recv_rtp (h, buf), GST_FLOW_OK);
2611 
2612     buf = gst_harness_pull (h->recv_rtp_h);
2613     fail_unless (buf);
2614     gst_buffer_unref (buf);
2615   }
2616 
2617   g_signal_emit_by_name (h->internal_session, "get-source-by-ssrc", 0xAAAA,
2618       &source);
2619 
2620   g_object_get (source, "stats", &stats, NULL);
2621 
2622   fail_unless (gst_structure_get_uint (stats, "recv-packet-rate", &pktrate));
2623   fail_unless (pktrate > 900 && pktrate < 1100);        /* Allow 10% of error */
2624 
2625   gst_structure_free (stats);
2626   g_object_unref (source);
2627 
2628   session_harness_free (h);
2629 }
2630 
GST_START_TEST(test_packet_rate)2631 GST_START_TEST (test_packet_rate)
2632 {
2633   test_packet_rate_impl (FALSE);
2634 }
2635 
2636 GST_END_TEST;
2637 
GST_START_TEST(test_stepped_packet_rate)2638 GST_START_TEST (test_stepped_packet_rate)
2639 {
2640   test_packet_rate_impl (TRUE);
2641 }
2642 
2643 GST_END_TEST;
2644 
2645 
2646 /********************* TWCC-tests *********************/
2647 
2648 static GstRTCPFBType
_gst_buffer_get_rtcp_fbtype(GstBuffer * buf)2649 _gst_buffer_get_rtcp_fbtype (GstBuffer * buf)
2650 {
2651   GstRTCPFBType ret = GST_RTCP_FB_TYPE_INVALID;
2652   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2653   GstRTCPPacket packet;
2654 
2655   if (!gst_rtcp_buffer_validate_reduced (buf))
2656     return ret;
2657 
2658   if (!gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp))
2659     return ret;
2660 
2661   if (!gst_rtcp_buffer_get_first_packet (&rtcp, &packet))
2662     goto done;
2663 
2664   if (GST_RTCP_TYPE_RTPFB != gst_rtcp_packet_get_type (&packet))
2665     goto done;
2666 
2667   ret = gst_rtcp_packet_fb_get_type (&packet);
2668 
2669 done:
2670   gst_rtcp_buffer_unmap (&rtcp);
2671   return ret;
2672 }
2673 
2674 static GstBuffer *
session_harness_produce_twcc(SessionHarness * h)2675 session_harness_produce_twcc (SessionHarness * h)
2676 {
2677   GstBuffer *buf = NULL;
2678   while (TRUE) {
2679     session_harness_crank_clock (h);
2680     buf = session_harness_pull_rtcp (h);
2681     if (GST_RTCP_RTPFB_TYPE_TWCC == _gst_buffer_get_rtcp_fbtype (buf)) {
2682       break;
2683     } else {
2684       gst_buffer_unref (buf);
2685     }
2686     /* allow the rtcp-thread to settle before cranking again */
2687     gst_test_clock_wait_for_next_pending_id (h->testclock, NULL);
2688   }
2689   return buf;
2690 }
2691 
2692 typedef struct
2693 {
2694   guint16 base_seqnum;
2695   guint16 num_packets;
2696   GstClockTime base_time;
2697   GstClockTime duration;
2698 } TWCCTestData;
2699 
2700 static TWCCTestData twcc_header_and_run_length_test_data[] = {
2701   {0, 10, 0, 33 * GST_MSECOND},
2702   {65530, 12, 37 * 64 * GST_MSECOND, 10 * GST_MSECOND}, /* seqnum wrap */
2703   {99, 200, 1024 * 64 * GST_MSECOND, 10 * GST_MSECOND}, /* many packets */
2704   {20000, 23, 0, 250 * GST_USECOND},    /* minimal duration */
2705   {56000, 15, 1000 * 64 * GST_MSECOND, 10 * GST_MSECOND},       /* timestamp offset */
2706 };
2707 
GST_START_TEST(test_twcc_header_and_run_length)2708 GST_START_TEST (test_twcc_header_and_run_length)
2709 {
2710   SessionHarness *h = session_harness_new ();
2711   gint i;
2712   GstFlowReturn res;
2713   GstBuffer *buf;
2714   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
2715   GstRTCPPacket packet;
2716   guint8 *fci_data;
2717   guint16 run_length;
2718 
2719   TWCCTestData *td = &twcc_header_and_run_length_test_data[__i__];
2720 
2721   /* enable twcc */
2722   session_harness_set_twcc_recv_ext_id (h, TEST_TWCC_EXT_ID);
2723 
2724   /* receive some buffers */
2725   for (i = 0; i < td->num_packets; i++) {
2726     gboolean last_packet = i == (td->num_packets - 1);
2727 
2728     GstClockTime now = gst_clock_get_time (GST_CLOCK_CAST (h->testclock));
2729     GstClockTime ts = td->base_time + i * td->duration;
2730     if (ts > now)
2731       gst_test_clock_set_time (h->testclock, ts);
2732 
2733     buf = generate_twcc_recv_buffer (i + td->base_seqnum, ts, last_packet);
2734     res = session_harness_recv_rtp (h, buf);
2735     fail_unless_equals_int (GST_FLOW_OK, res);
2736   }
2737 
2738   buf = session_harness_produce_twcc (h);
2739   fail_unless (buf);
2740 
2741   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
2742   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
2743 
2744   fci_data = gst_rtcp_packet_fb_get_fci (&packet);
2745 
2746   /* base seqnum */
2747   fail_unless_equals_int (td->base_seqnum, GST_READ_UINT16_BE (&fci_data[0]));
2748 
2749   /*  packet count */
2750   fail_unless_equals_int (td->num_packets, GST_READ_UINT16_BE (&fci_data[2]));
2751 
2752   /* reference time (in 64ms units) */
2753   fail_unless_equals_int (td->base_time,
2754       GST_READ_UINT24_BE (&fci_data[4]) * 64 * GST_MSECOND);
2755 
2756   /* feedback packet number */
2757   fail_unless_equals_int (0, fci_data[7]);
2758 
2759   /* run-length coding */
2760   fail_unless_equals_int (0, fci_data[8] & 0x80);
2761 
2762   /* status: small-delta */
2763   fail_unless_equals_int (0x20, fci_data[8] & 0x60);
2764 
2765   /* packets in run_length */
2766   run_length = GST_READ_UINT16_BE (&fci_data[8]);
2767   run_length = run_length & ~0xE000;    /* mask out the upper 3 status bits */
2768   fail_unless_equals_int (td->num_packets, run_length);
2769 
2770   /* first recv-delta always 0 */
2771   fail_unless_equals_int (0, fci_data[10]);
2772 
2773   /* following recv-delta equal to duration (in 250us units) */
2774   fail_unless_equals_clocktime (td->duration, fci_data[11] * 250 * GST_USECOND);
2775 
2776   gst_rtcp_buffer_unmap (&rtcp);
2777   gst_buffer_unref (buf);
2778 
2779   session_harness_free (h);
2780 }
2781 
2782 GST_END_TEST;
2783 
2784 typedef struct
2785 {
2786   guint16 seqnum;
2787   GstClockTime timestamp;
2788   gboolean marker;
2789 } TWCCPacket;
2790 
2791 #define TWCC_DELTA_UNIT (250 * GST_USECOND)
2792 
2793 static void
fail_unless_equals_twcc_clocktime(GstClockTime twcc_packet_ts,GstClockTime pkt_ts)2794 fail_unless_equals_twcc_clocktime (GstClockTime twcc_packet_ts,
2795     GstClockTime pkt_ts)
2796 {
2797   fail_unless_equals_clocktime (
2798       (twcc_packet_ts / TWCC_DELTA_UNIT) * TWCC_DELTA_UNIT, pkt_ts);
2799 }
2800 
2801 #define twcc_push_packets(h, packets)                                          \
2802 G_STMT_START {                                                                 \
2803   guint i;                                                                     \
2804   session_harness_set_twcc_recv_ext_id ((h), TEST_TWCC_EXT_ID);                \
2805   for (i = 0; i < G_N_ELEMENTS ((packets)); i++) {                             \
2806     TWCCPacket *twcc_pkt = &(packets)[i];                                      \
2807     GstClockTime now = gst_clock_get_time (GST_CLOCK_CAST (h->testclock));     \
2808     if (twcc_pkt->timestamp > now)                                             \
2809       gst_test_clock_set_time ((h->testclock), twcc_pkt->timestamp);           \
2810     fail_unless_equals_int (GST_FLOW_OK,                                       \
2811         session_harness_recv_rtp ((h),                                         \
2812             generate_twcc_recv_buffer (twcc_pkt->seqnum,                       \
2813                 twcc_pkt->timestamp, twcc_pkt->marker)));                      \
2814   }                                                                            \
2815 } G_STMT_END
2816 
2817 #define twcc_verify_fci(buf, exp_fci)                                          \
2818 G_STMT_START {                                                                 \
2819   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;                                   \
2820   GstRTCPPacket packet;                                                        \
2821   guint8 *fci_data;                                                            \
2822   guint16 fci_length;                                                          \
2823   fail_unless (gst_rtcp_buffer_validate_reduced (buf));                        \
2824   gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);                              \
2825   fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));             \
2826   fail_unless_equals_int (GST_RTCP_TYPE_RTPFB,                                 \
2827       gst_rtcp_packet_get_type (&packet));                                     \
2828   fail_unless_equals_int (GST_RTCP_RTPFB_TYPE_TWCC,                            \
2829       gst_rtcp_packet_fb_get_type (&packet));                                  \
2830   fci_data = gst_rtcp_packet_fb_get_fci (&packet);                             \
2831   fci_length = gst_rtcp_packet_fb_get_fci_length (&packet) * sizeof (guint32); \
2832   GST_MEMDUMP ("fci:", fci_data, fci_length);                                  \
2833   fail_unless_equals_int (fci_length, sizeof (exp_fci));                       \
2834   fail_unless_equals_int (0, memcmp (fci_data, (exp_fci), fci_length));        \
2835   gst_rtcp_buffer_unmap (&rtcp);                                               \
2836 } G_STMT_END
2837 
2838 #define twcc_verify_packets_to_fci(h, packets, exp_fci)                        \
2839 G_STMT_START {                                                                 \
2840   GstBuffer *buf;                                                              \
2841   twcc_push_packets (h, packets);                                              \
2842   buf = session_harness_produce_twcc ((h));                                    \
2843   twcc_verify_fci (buf, exp_fci);                                              \
2844   gst_buffer_unref (buf);                                                      \
2845 } G_STMT_END
2846 
2847 #define twcc_verify_packets_to_event(packets, event)                           \
2848 G_STMT_START {                                                                 \
2849   guint i;                                                                     \
2850   guint j = 0;                                                                 \
2851   GValueArray *packets_array = g_value_get_boxed (                             \
2852       gst_structure_get_value (gst_event_get_structure ((event)), "packets")); \
2853   for (i = 0; i < packets_array->n_values; i++) {                              \
2854     TWCCPacket *twcc_pkt;                                                      \
2855     GstClockTime ts;                                                           \
2856     guint seqnum;                                                              \
2857     gboolean lost;                                                             \
2858     const GstStructure *pkt_s =                                                \
2859         gst_value_get_structure (g_value_array_get_nth (packets_array, i));    \
2860     fail_unless (gst_structure_get_boolean (pkt_s, "lost", &lost));            \
2861     if (lost)                                                                  \
2862       continue;                                                                \
2863     fail_unless (gst_structure_get_clock_time (pkt_s, "remote-ts", &ts));      \
2864     fail_unless (gst_structure_get_uint (pkt_s, "seqnum", &seqnum));           \
2865     twcc_pkt = &(packets)[j++];                                                \
2866     fail_unless_equals_int (twcc_pkt->seqnum, seqnum);                         \
2867     fail_unless_equals_twcc_clocktime (twcc_pkt->timestamp, ts);               \
2868   }                                                                            \
2869   gst_event_unref (event);                                                     \
2870 } G_STMT_END
2871 
2872 #define twcc_verify_packets_to_packets(send_h, recv_h, packets)                \
2873 G_STMT_START {                                                                 \
2874   guint i;                                                                     \
2875   GstEvent *event;                                                             \
2876   twcc_push_packets ((recv_h), packets);                                       \
2877   session_harness_recv_rtcp ((send_h),                                         \
2878       session_harness_produce_twcc ((recv_h)));                                \
2879   for (i = 0; i < 2; i++)                                                      \
2880     gst_event_unref (gst_harness_pull_upstream_event ((send_h)->send_rtp_h));  \
2881   event = gst_harness_pull_upstream_event ((send_h)->send_rtp_h);              \
2882   twcc_verify_packets_to_event (packets, event);                               \
2883 } G_STMT_END
2884 
2885 #define twcc_verify_stats(h, bitrate_sent, bitrate_recv, pkts_sent, pkts_recv, loss_pct, avg_dod)  \
2886 G_STMT_START {                                                                                     \
2887   GstStructure *twcc_stats;                                                                        \
2888   guint stats_bitrate_sent;                                                                        \
2889   guint stats_bitrate_recv;                                                                        \
2890   guint stats_packets_sent;                                                                        \
2891   guint stats_packets_recv;                                                                        \
2892   gdouble stats_loss_pct;                                                                          \
2893   GstClockTimeDiff stats_avg_dod;                                                                  \
2894   twcc_stats = session_harness_get_last_twcc_stats (h);                                            \
2895   fail_unless (gst_structure_get (twcc_stats,                                                      \
2896           "bitrate-sent", G_TYPE_UINT, &stats_bitrate_sent,                                        \
2897           "bitrate-recv", G_TYPE_UINT, &stats_bitrate_recv,                                        \
2898           "packets-sent", G_TYPE_UINT, &stats_packets_sent,                                        \
2899           "packets-recv", G_TYPE_UINT, &stats_packets_recv,                                        \
2900           "packet-loss-pct", G_TYPE_DOUBLE, &stats_loss_pct,                                       \
2901           "avg-delta-of-delta", G_TYPE_INT64, &stats_avg_dod, NULL));                              \
2902   fail_unless_equals_int (bitrate_sent, stats_bitrate_sent);                                       \
2903   fail_unless_equals_int (bitrate_recv, stats_bitrate_recv);                                       \
2904   fail_unless_equals_int (pkts_sent, stats_packets_sent);                                          \
2905   fail_unless_equals_int (pkts_recv, stats_packets_recv);                                          \
2906   fail_unless_equals_float (loss_pct, stats_loss_pct);                                             \
2907   fail_unless_equals_int64 (avg_dod, stats_avg_dod);                                               \
2908   gst_structure_free (twcc_stats);                                                                 \
2909 } G_STMT_END
2910 
GST_START_TEST(test_twcc_1_bit_status_vector)2911 GST_START_TEST (test_twcc_1_bit_status_vector)
2912 {
2913   SessionHarness *h0 = session_harness_new ();
2914   SessionHarness *h1 = session_harness_new ();
2915 
2916   TWCCPacket packets[] = {
2917     {10, 0 * GST_MSECOND, FALSE},
2918     {12, 12 * GST_MSECOND, FALSE},
2919     {14, 14 * GST_MSECOND, FALSE},
2920     {15, 15 * GST_MSECOND, FALSE},
2921     {17, 17 * GST_MSECOND, FALSE},
2922     {20, 20 * GST_MSECOND, FALSE},
2923     {21, 21 * GST_MSECOND, FALSE},
2924     {23, 23 * GST_MSECOND, TRUE},
2925   };
2926 
2927   guint8 exp_fci[] = {
2928     0x00, 0x0a,                 /* base sequence number: 10 */
2929     0x00, 0x0e,                 /* packet status count: 14 */
2930     0x00, 0x00, 0x00,           /* reference time: 0 */
2931     0x00,                       /* feedback packet count: 0 */
2932     0xab, 0x4d,                 /* packet chunk: 1 0 1 0 1 0 1 1 | 0 1 0 0 1 1 0 1 */
2933     0x00,                       /* recv delta: +0:00:00.000000000 */
2934     0x30,                       /* recv delta: +0:00:00.012000000 */
2935     0x08,                       /* recv delta: +0:00:00.002000000 */
2936     0x04,                       /* recv delta: +0:00:00.001000000 */
2937     0x08,                       /* recv delta: +0:00:00.002000000 */
2938     0x0c,                       /* recv delta: +0:00:00.003000000 */
2939     0x04,                       /* recv delta: +0:00:00.001000000 */
2940     0x08,                       /* recv delta: +0:00:00.002000000 */
2941     0x00, 0x00,                 /* padding */
2942   };
2943 
2944   /* check we get the expected fci */
2945   twcc_verify_packets_to_fci (h0, packets, exp_fci);
2946 
2947   /* and check we can parse this back to the original packets */
2948   twcc_verify_packets_to_packets (h1, h1, packets);
2949 
2950   session_harness_free (h0);
2951   session_harness_free (h1);
2952 }
2953 
2954 GST_END_TEST;
2955 
GST_START_TEST(test_twcc_status_vector_split_large_delta)2956 GST_START_TEST (test_twcc_status_vector_split_large_delta)
2957 {
2958   SessionHarness *h0 = session_harness_new ();
2959   SessionHarness *h1 = session_harness_new ();
2960 
2961   TWCCPacket packets[] = {
2962     {1, 1 * 60 * GST_MSECOND, FALSE},
2963     {2, 2 * 60 * GST_MSECOND, FALSE},
2964     {3, 3 * 60 * GST_MSECOND, FALSE},
2965     {4, 4 * 60 * GST_MSECOND, FALSE},
2966     {5, 5 * 60 * GST_MSECOND, FALSE},
2967     {6, 6 * 60 * GST_MSECOND, FALSE},
2968     {7, 7 * 60 * GST_MSECOND, FALSE},
2969     {8, 8 * 60 * GST_MSECOND, FALSE},
2970     {9, 9 * 60 * GST_MSECOND, FALSE},
2971     {10, 10 * 60 * GST_MSECOND, FALSE},
2972     {11, 11 * 60 * GST_MSECOND, FALSE},
2973     {12, 12 * 60 * GST_MSECOND, FALSE},
2974     {13, 13 * 60 * GST_MSECOND, FALSE},
2975     {14, 14 * 60 * GST_MSECOND, FALSE},
2976 
2977     {15, 60 * 60 * GST_MSECOND, TRUE},
2978   };
2979 
2980   guint8 exp_fci[] = {
2981     0x00, 0x01,                 /* base sequence number: 1 */
2982     0x00, 0x0f,                 /* packet status count: 15 */
2983     0x00, 0x00, 0x00,           /* reference time: 0 */
2984     0x00,                       /* feedback packet count: 0 */
2985     0x20, 0x0e,                 /* run-length chunk with small delta for #1 to #14:  0 0 1 0 0 0 0 0 | 0 0 0 0 1 1 1 0 */
2986     0x40, 0x01,                 /* rung-length with large delta for #15:             0 1 0 0 0 0 0 0 | 0 0 0 0 0 0 0 1 */
2987 
2988     /* recv deltas: */
2989     0xf0, 0xf0,                 /* 14 small deltas : +0:00:00.060000000 */
2990     0xf0, 0xf0,
2991     0xf0, 0xf0,
2992     0xf0, 0xf0,
2993     0xf0, 0xf0,
2994     0xf0, 0xf0,
2995     0xf0, 0xf0,
2996     0x2b, 0x20,                 /* large delta: +0:00:02.760000000 */
2997   };
2998 
2999   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3000   twcc_verify_packets_to_packets (h1, h1, packets);
3001 
3002   session_harness_free (h0);
3003   session_harness_free (h1);
3004 }
3005 
3006 GST_END_TEST;
3007 
GST_START_TEST(test_twcc_2_bit_status_vector)3008 GST_START_TEST (test_twcc_2_bit_status_vector)
3009 {
3010   SessionHarness *h0 = session_harness_new ();
3011   SessionHarness *h1 = session_harness_new ();
3012 
3013   TWCCPacket packets[] = {
3014     {5, 5 * 64 * GST_MSECOND, FALSE},
3015     {7, 7 * 64 * GST_MSECOND, FALSE},
3016     {8, 8 * 64 * GST_MSECOND, FALSE},
3017     {11, 12 * 64 * GST_MSECOND, TRUE},
3018   };
3019 
3020   guint8 exp_fci[] = {
3021     0x00, 0x05,                 /* base sequence number: 5 */
3022     0x00, 0x07,                 /* packet status count: 7 */
3023     0x00, 0x00, 0x05,           /* reference time: 5 */
3024     0x00,                       /* feedback packet count: 0 */
3025     0xd2, 0x82,                 /* packet chunk: 1 1 0 1 0 0 1 0 | 1 0 0 0 0 0 1 0 */
3026     /* normal, missing, large, large, missing, missing, large */
3027     0x00,                       /* recv delta: +0:00:00.000000000 */
3028     0x02, 0x00,                 /* recv delta: +0:00:00.128000000 */
3029     0x01, 0x00,                 /* recv delta: +0:00:00.064000000 */
3030     0x04, 0x00,                 /* recv delta: +0:00:00.256000000 */
3031     0x00, 0x00, 0x00,           /* padding */
3032   };
3033 
3034   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3035 
3036   twcc_verify_packets_to_packets (h1, h1, packets);
3037 
3038   session_harness_free (h0);
3039   session_harness_free (h1);
3040 }
3041 
3042 GST_END_TEST;
3043 
GST_START_TEST(test_twcc_2_bit_over_capacity)3044 GST_START_TEST (test_twcc_2_bit_over_capacity)
3045 {
3046   SessionHarness *h = session_harness_new ();
3047 
3048   TWCCPacket packets[] = {
3049     {0, 0 * GST_MSECOND, FALSE},
3050     {6, 250 * 250 + 250 * GST_MSECOND, TRUE},
3051   };
3052 
3053   guint8 exp_fci[] = {
3054     0x00, 0x00,                 /* base sequence number: 0 */
3055     0x00, 0x07,                 /* packet status count: 7 */
3056     0x00, 0x00, 0x00,           /* reference time: 0 */
3057     0x00,                       /* feedback packet count: 0 */
3058     0xd0, 0x02,                 /* packet chunk: 1 1 0 1 0 0 0 0 | 0 0 0 0 0 0 1 0 */
3059     0x00,                       /* recv delta: +0:00:00.000000000 */
3060     0x03, 0xe8,                 /* recv delta: +0:00:00.000000000 */
3061     0x00, 0x00, 0x00,           /* padding */
3062   };
3063 
3064   twcc_verify_packets_to_fci (h, packets, exp_fci);
3065 
3066   session_harness_free (h);
3067 }
3068 
3069 GST_END_TEST;
3070 
GST_START_TEST(test_twcc_status_vector_split_with_gap)3071 GST_START_TEST (test_twcc_status_vector_split_with_gap)
3072 {
3073   SessionHarness *h0 = session_harness_new ();
3074   SessionHarness *h1 = session_harness_new ();
3075 
3076   TWCCPacket packets[] = {
3077     {0, 0 * GST_MSECOND, FALSE},
3078     {7, (250 * 250) + 250 * GST_MSECOND, TRUE},
3079   };
3080 
3081   guint8 exp_fci[] = {
3082     0x00, 0x00,                 /* base sequence number: 0 */
3083     0x00, 0x08,                 /* packet status count: 8 */
3084     0x00, 0x00, 0x00,           /* reference time: 0 */
3085     0x00,                       /* feedback packet count: 0 */
3086     0xd0, 0x00,                 /* packet chunk: 1 1 0 1 0 0 0 0 | 0 0 0 0 0 0 0 0 */
3087     0xe0, 0x00,                 /* packet chunk: 1 1 1 0 0 0 0 0 | 0 0 0 0 0 0 1 0 */
3088     0x00,                       /* recv delta: +0:00:00.000000000 */
3089     0x03, 0xe8,                 /* recv delta: +0:00:00.250000000 */
3090     0x00,                       /* padding */
3091   };
3092 
3093   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3094   twcc_verify_packets_to_packets (h1, h1, packets);
3095 
3096   session_harness_free (h0);
3097   session_harness_free (h1);
3098 }
3099 
3100 GST_END_TEST;
3101 
GST_START_TEST(test_twcc_status_vector_split_into_three)3102 GST_START_TEST (test_twcc_status_vector_split_into_three)
3103 {
3104   SessionHarness *h0 = session_harness_new ();
3105   SessionHarness *h1 = session_harness_new ();
3106 
3107   TWCCPacket packets[] = {
3108     /* 7 packets with small deltas */
3109     {0, 0 * 250 * GST_USECOND, FALSE},
3110     {1, 1 * 250 * GST_USECOND, FALSE},
3111     {2, 2 * 250 * GST_USECOND, FALSE},
3112     {3, 3 * 250 * GST_USECOND, FALSE},
3113     {4, 4 * 250 * GST_USECOND, FALSE},
3114     {5, 5 * 250 * GST_USECOND, FALSE},
3115     {6, 6 * 250 * GST_USECOND, FALSE},
3116 
3117     /* 2 large delta, #8 will present a negative delta */
3118     {7, 7 * 250 * GST_MSECOND, FALSE},
3119     {8, 8 * 250 * GST_USECOND, FALSE},
3120 
3121     /* 13 packets with small deltas */
3122     {9, 9 * 250 * GST_USECOND, FALSE},
3123     {10, 10 * 250 * GST_USECOND, FALSE},
3124     {11, 11 * 250 * GST_USECOND, FALSE},
3125     {12, 12 * 250 * GST_USECOND, FALSE},
3126     {13, 13 * 250 * GST_USECOND, FALSE},
3127     {14, 14 * 250 * GST_USECOND, FALSE},
3128     {15, 15 * 250 * GST_USECOND, FALSE},
3129     {16, 16 * 250 * GST_USECOND, FALSE},
3130     {17, 17 * 250 * GST_USECOND, FALSE},
3131     {18, 18 * 250 * GST_USECOND, FALSE},
3132     {19, 19 * 250 * GST_USECOND, FALSE},
3133     {20, 20 * 250 * GST_USECOND, FALSE},
3134     {21, 21 * 250 * GST_USECOND, TRUE},
3135   };
3136 
3137   guint8 exp_fci[] = {
3138     0x00, 0x00,                 /* base sequence number: 0 */
3139     0x00, 0x16,                 /* packet status count: 22 */
3140     0x00, 0x00, 0x00,           /* reference time: 0 */
3141     0x00,                       /* feedback packet count: 0 */
3142     0x20, 0x07,                 /* run-length chunk (small deltas) for #0 to #6:   0 0 1 0 0 0 0 0 | 0 0 0 0 0 1 1 1 */
3143     0x40, 0x02,                 /* run-length chunk (large deltas) for #7 and #8   0 1 0 0 0 0 0 0 | 0 0 0 0 0 0 1 0 */
3144     0x20, 0x0d,                 /* run-length chunk (small deltas) for #9 and #21  0 1 0 0 0 0 0 0 | 0 0 0 0 1 1 0 1 */
3145 
3146     0x00,                       /* recv delta: +0:00:00.000000000 */
3147     0x01,                       /* recv delta: +0:00:00.000250000 */
3148     0x01,                       /* recv delta: +0:00:00.000250000 */
3149     0x01,                       /* recv delta: +0:00:00.000250000 */
3150     0x01,                       /* recv delta: +0:00:00.000250000 */
3151     0x01,                       /* recv delta: +0:00:00.000250000 */
3152     0x01,                       /* recv delta: +0:00:00.000250000 */
3153 
3154     0x1b, 0x52,                 /* recv delta: +0:00:01.748500000 */
3155     0xe4, 0xb0,                 /* recv delta: -0:00:01.748000000 */
3156 
3157     0x01,                       /* recv delta: +0:00:00.000250000 */
3158     0x01,                       /* recv delta: +0:00:00.000250000 */
3159     0x01,                       /* recv delta: +0:00:00.000250000 */
3160     0x01,                       /* recv delta: +0:00:00.000250000 */
3161     0x01,                       /* recv delta: +0:00:00.000250000 */
3162     0x01,                       /* recv delta: +0:00:00.000250000 */
3163     0x01,                       /* recv delta: +0:00:00.000250000 */
3164     0x01,                       /* recv delta: +0:00:00.000250000 */
3165     0x01,                       /* recv delta: +0:00:00.000250000 */
3166     0x01,                       /* recv delta: +0:00:00.000250000 */
3167     0x01,                       /* recv delta: +0:00:00.000250000 */
3168     0x01,                       /* recv delta: +0:00:00.000250000 */
3169     0x01,                       /* recv delta: +0:00:00.000250000 */
3170 
3171     0x00, 0x00,                 /* padding */
3172   };
3173 
3174   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3175   twcc_verify_packets_to_packets (h1, h1, packets);
3176 
3177   session_harness_free (h0);
3178   session_harness_free (h1);
3179 }
3180 
3181 GST_END_TEST;
3182 
GST_START_TEST(test_twcc_2_bit_full_status_vector)3183 GST_START_TEST (test_twcc_2_bit_full_status_vector)
3184 {
3185   SessionHarness *h0 = session_harness_new ();
3186   SessionHarness *h1 = session_harness_new ();
3187 
3188   TWCCPacket packets[] = {
3189     {1, 1 * 64 * GST_MSECOND, FALSE},
3190     {2, 2 * 64 * GST_MSECOND, FALSE},
3191     {6, 6 * 64 * GST_MSECOND, FALSE},
3192     {7, 7 * 64 * GST_MSECOND, TRUE},
3193   };
3194 
3195   guint8 exp_fci[] = {
3196     0x00, 0x01,                 /* base sequence number: 1 */
3197     0x00, 0x07,                 /* packet status count: 7 */
3198     0x00, 0x00, 0x01,           /* reference time: 1 */
3199     0x00,                       /* feedback packet count: 0 */
3200     0xd8, 0x0a,                 /* packet chunk: 1 1 0 1 1 0 0 0 | 0 0 0 0 1 0 1 0 */
3201     0x00, 0x01,                 /* recv delta: +0:00:00.064000000 */
3202     0x00, 0x04,                 /* recv delta: +0:00:00.256000000 */
3203     0x00, 0x01,                 /* recv delta: +0:00:00.064000000 */
3204     0x00, 0x00, 0x00, 0x00,     /* padding */
3205   };
3206 
3207   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3208   twcc_verify_packets_to_packets (h1, h1, packets);
3209 
3210   session_harness_free (h0);
3211   session_harness_free (h1);
3212 }
3213 
3214 GST_END_TEST;
3215 
GST_START_TEST(test_twcc_various_gaps)3216 GST_START_TEST (test_twcc_various_gaps)
3217 {
3218   SessionHarness *h = session_harness_new ();
3219   guint16 seq = 1 + __i__;
3220 
3221   TWCCPacket packets[] = {
3222     {0, 0 * 250 * GST_USECOND, FALSE},
3223     {seq, seq * 250 * GST_USECOND, TRUE},
3224   };
3225 
3226   twcc_verify_packets_to_packets (h, h, packets);
3227 
3228   session_harness_free (h);
3229 }
3230 
3231 GST_END_TEST;
3232 
GST_START_TEST(test_twcc_negative_delta)3233 GST_START_TEST (test_twcc_negative_delta)
3234 {
3235   SessionHarness *h0 = session_harness_new ();
3236   SessionHarness *h1 = session_harness_new ();
3237 
3238   TWCCPacket packets[] = {
3239     {0, 0 * 250 * GST_USECOND, FALSE},
3240     {1, 2 * 250 * GST_USECOND, FALSE},
3241     {2, 1 * 250 * GST_USECOND, FALSE},
3242     {3, 3 * 250 * GST_USECOND, TRUE},
3243   };
3244 
3245   guint8 exp_fci[] = {
3246     0x00, 0x00,                 /* base sequence number: 0 */
3247     0x00, 0x04,                 /* packet status count: 4 */
3248     0x00, 0x00, 0x00,           /* reference time: 0 */
3249     0x00,                       /* feedback packet count: 0 */
3250     0xd6, 0x40,                 /* packet chunk: 1 1 0 1 0 1 1 0 | 0 1 0 0 0 0 0 0 */
3251     0x00,                       /* recv delta: +0:00:00.000000000 */
3252     0x02,                       /* recv delta: +0:00:00.000500000 */
3253     0xff, 0xff,                 /* recv delta: -0:00:00.000250000 */
3254     0x02,                       /* recv delta: +0:00:00.000500000 */
3255     0x00,                       /* padding */
3256   };
3257 
3258   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3259 
3260   twcc_verify_packets_to_packets (h1, h1, packets);
3261 
3262   session_harness_free (h0);
3263   session_harness_free (h1);
3264 }
3265 
3266 GST_END_TEST;
3267 
GST_START_TEST(test_twcc_seqnum_wrap)3268 GST_START_TEST (test_twcc_seqnum_wrap)
3269 {
3270   SessionHarness *h0 = session_harness_new ();
3271   SessionHarness *h1 = session_harness_new ();
3272 
3273   TWCCPacket packets[] = {
3274     {65534, 0 * 250 * GST_USECOND, FALSE},
3275     {65535, 1 * 250 * GST_USECOND, FALSE},
3276     {0, 2 * 250 * GST_USECOND, FALSE},
3277     {1, 3 * 250 * GST_USECOND, TRUE},
3278   };
3279 
3280   guint8 exp_fci[] = {
3281     0xff, 0xfe,                 /* base sequence number: 65534 */
3282     0x00, 0x04,                 /* packet status count: 4 */
3283     0x00, 0x00, 0x00,           /* reference time: 0 */
3284     0x00,                       /* feedback packet count: 0 */
3285     0x20, 0x04,                 /* packet chunk: 0 0 1 0 0 0 0 0 | 0 0 0 0 0 1 0 0 */
3286     0x00,                       /* recv delta: +0:00:00.000000000 */
3287     0x01,                       /* recv delta: +0:00:00.000250000 */
3288     0x01,                       /* recv delta: +0:00:00.000250000 */
3289     0x01,                       /* recv delta: +0:00:00.000250000 */
3290     0x00, 0x00,                 /* padding */
3291   };
3292 
3293   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3294   twcc_verify_packets_to_packets (h1, h1, packets);
3295 
3296   session_harness_free (h0);
3297   session_harness_free (h1);
3298 }
3299 
3300 GST_END_TEST;
3301 
GST_START_TEST(test_twcc_seqnum_wrap_with_loss)3302 GST_START_TEST (test_twcc_seqnum_wrap_with_loss)
3303 {
3304   SessionHarness *h = session_harness_new ();
3305   GstBuffer *buf;
3306 
3307   TWCCPacket packets[] = {
3308     {65534, 0 * 250 * GST_USECOND, TRUE},
3309     {1, 3 * 250 * GST_USECOND, TRUE},
3310   };
3311 
3312   guint8 exp_fci0[] = {
3313     0xff, 0xfe,                 /* base sequence number: 65534 */
3314     0x00, 0x01,                 /* packet status count: 1 */
3315     0x00, 0x00, 0x00,           /* reference time: 0 */
3316     0x00,                       /* feedback packet count: 0 */
3317     0x20, 0x01,                 /* packet chunk: 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 1  */
3318     0x00,                       /* recv delta: +0:00:00.000000000 */
3319     0x00,                       /* padding */
3320   };
3321 
3322   guint8 exp_fci1[] = {
3323     0x00, 0x01,                 /* base sequence number: 1 */
3324     0x00, 0x01,                 /* packet status count: 1 */
3325     0x00, 0x00, 0x00,           /* reference time: 0 */
3326     0x01,                       /* feedback packet count: 1 */
3327     0x20, 0x01,                 /* packet chunk: 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 1  */
3328     0x03,                       /* recv delta: +0:00:00.000750000 */
3329     0x00,                       /* padding */
3330   };
3331 
3332   twcc_push_packets (h, packets);
3333 
3334   buf = session_harness_produce_twcc (h);
3335   twcc_verify_fci (buf, exp_fci0);
3336   gst_buffer_unref (buf);
3337 
3338   buf = session_harness_produce_twcc (h);
3339   twcc_verify_fci (buf, exp_fci1);
3340   gst_buffer_unref (buf);
3341 
3342   session_harness_free (h);
3343 }
3344 
3345 GST_END_TEST;
3346 
GST_START_TEST(test_twcc_double_packets)3347 GST_START_TEST (test_twcc_double_packets)
3348 {
3349   SessionHarness *h = session_harness_new ();
3350 
3351   TWCCPacket packets0[] = {
3352     {11, 11 * GST_MSECOND, FALSE},
3353     {12, 12 * GST_MSECOND, TRUE},
3354   };
3355 
3356   TWCCPacket packets1[] = {
3357     {13, 13 * GST_MSECOND, FALSE},
3358     {14, 14 * GST_MSECOND, FALSE},
3359     {15, 15 * GST_MSECOND, TRUE},
3360   };
3361 
3362   guint8 exp_fci0[] = {
3363     0x00, 0x0b,                 /* base sequence number: 11 */
3364     0x00, 0x02,                 /* packet status count: 2 */
3365     0x00, 0x00, 0x00,           /* reference time: 0 */
3366     0x00,                       /* feedback packet count: 0 */
3367     0x20, 0x02,                 /* packet chunk: 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 1 0 */
3368     0x2c, 0x04,                 /* recv deltas */
3369   };
3370 
3371   guint8 exp_fci1[] = {
3372     0x00, 0x0d,                 /* base sequence number: 13 */
3373     0x00, 0x03,                 /* packet status count: 3 */
3374     0x00, 0x00, 0x00,           /* reference time: 0 */
3375     0x01,                       /* feedback packet count: 1 */
3376     0x20, 0x03,                 /* packet chunk: 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 1 1 */
3377     0x34, 0x04, 0x04,           /* recv deltas */
3378     0x00, 0x00, 0x00,           /* padding */
3379   };
3380 
3381   twcc_verify_packets_to_fci (h, packets0, exp_fci0);
3382   twcc_verify_packets_to_fci (h, packets1, exp_fci1);
3383 
3384   session_harness_free (h);
3385 }
3386 
3387 GST_END_TEST;
3388 
GST_START_TEST(test_twcc_huge_seqnum_gap)3389 GST_START_TEST (test_twcc_huge_seqnum_gap)
3390 {
3391   SessionHarness *h0 = session_harness_new ();
3392   SessionHarness *h1 = session_harness_new ();
3393 
3394   TWCCPacket packets[] = {
3395     {9, 4 * 32 * GST_MSECOND, FALSE},
3396     {10, 5 * 32 * GST_MSECOND, FALSE},
3397     {30011, 6 * 32 * GST_MSECOND, FALSE},
3398     {30012, 7 * 32 * GST_MSECOND, FALSE},
3399     {30013, 8 * 32 * GST_MSECOND, TRUE},
3400   };
3401 
3402   guint8 exp_fci[] = {
3403     0x00, 0x09,                 /* base sequence number: 9 */
3404     0x75, 0x35,                 /* packet status count: 30005 */
3405     0x00, 0x00, 0x02,           /* reference time: 2 */
3406     0x00,                       /* feedback packet count: 0 */
3407     /* packet chunks: */
3408     0xb0, 0x00,                 /* run-length: 1 bit 2 there, 12 lost: 1 0 1 1 0 0 0 0 | 0 0 0 0 0 0 0 0 */
3409     0x1f, 0xff,                 /* run-length: 8191 lost:  0 0 0 1 1 1 1 1 | 1 1 1 1 1 1 1 1 */
3410     0x1f, 0xff,                 /* run-length: 8191 lost:  0 0 0 1 1 1 1 1 | 1 1 1 1 1 1 1 1 */
3411     0x1f, 0xff,                 /* run-length: 8191 lost:  0 0 0 1 1 1 1 1 | 1 1 1 1 1 1 1 1 */
3412     0x15, 0x27,                 /* run-length: 5415 lost:  0 0 0 1 0 1 0 1 | 0 0 1 0 0 1 1 1 */
3413     /* 12 + 8191 + 8191 + 8191 + 5415 = 30000 lost packets */
3414     0xb8, 0x00,                 /* 1 bit 3 there         : 1 0 1 1 1 0 0 0 | 0 0 0 0 0 0 0 0 */
3415 
3416     0x00, 0x80, 0x80, 0x80, 0x80,       /* recv deltas */
3417     0x00, 0x00, 0x00,           /* padding */
3418   };
3419 
3420   twcc_push_packets (h0, packets);
3421 
3422   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3423   twcc_verify_packets_to_packets (h1, h1, packets);
3424 
3425   session_harness_free (h0);
3426   session_harness_free (h1);
3427 }
3428 
3429 GST_END_TEST;
3430 
GST_START_TEST(test_twcc_duplicate_seqnums)3431 GST_START_TEST (test_twcc_duplicate_seqnums)
3432 {
3433   SessionHarness *h = session_harness_new ();
3434   GstBuffer *buf;
3435 
3436   /* A duplicate seqnum can be interpreted as a gap of 65536 packets.
3437      Whatever the cause might be, we will follow the behavior of reordered
3438      packets, and drop it */
3439   TWCCPacket packets[] = {
3440     {1, 4 * 32 * GST_MSECOND, FALSE},
3441     {2, 5 * 32 * GST_MSECOND, FALSE},
3442     {2, 6 * 32 * GST_MSECOND, FALSE},
3443     {3, 7 * 32 * GST_MSECOND, TRUE},
3444   };
3445 
3446   guint8 exp_fci[] = {
3447     0x00, 0x01,                 /* base sequence number: 1 */
3448     0x00, 0x03,                 /* packet status count: 2 */
3449     0x00, 0x00, 0x02,           /* reference time: 2 * 64ms */
3450     0x00,                       /* feedback packet count: 0 */
3451     /* packet chunks: */
3452     0xd6, 0x00,                 /* 1 1 0 1 0 1 1 0 | 0 0 0 0 0 0 0 0  */
3453     0x00, 0x80,                 /* recv deltas: +0, +32ms, + 64ms */
3454     0x01, 0x00,
3455     0x00, 0x00,                 /* padding */
3456   };
3457 
3458   twcc_push_packets (h, packets);
3459 
3460   buf = session_harness_produce_twcc (h);
3461   twcc_verify_fci (buf, exp_fci);
3462   gst_buffer_unref (buf);
3463 
3464   session_harness_free (h);
3465 }
3466 
3467 GST_END_TEST;
3468 
3469 
GST_START_TEST(test_twcc_multiple_markers)3470 GST_START_TEST (test_twcc_multiple_markers)
3471 {
3472   SessionHarness *h = session_harness_new ();
3473   GstBuffer *buf;
3474 
3475   /* for this test, notice how the first recv-delta should relate back to
3476      the reference-time, which is 0 in this case. The packets are incrementing
3477      in timestamps equal to the smallest unit for TWCC (250 microseconds) */
3478   TWCCPacket packets[] = {
3479     {1, 1 * 250 * GST_USECOND, FALSE},
3480     {2, 2 * 250 * GST_USECOND, FALSE},
3481     {3, 3 * 250 * GST_USECOND, TRUE},
3482     {4, 4 * 250 * GST_USECOND, FALSE},
3483     {5, 5 * 250 * GST_USECOND, TRUE},
3484     {6, 6 * 250 * GST_USECOND, FALSE},
3485     {7, 7 * 250 * GST_USECOND, FALSE},
3486     {8, 8 * 250 * GST_USECOND, FALSE},
3487     {9, 9 * 250 * GST_USECOND, TRUE},
3488   };
3489 
3490   guint8 exp_fci0[] = {
3491     0x00, 0x01,                 /* base sequence number: 1 */
3492     0x00, 0x03,                 /* packet status count: 3 */
3493     0x00, 0x00, 0x00,           /* reference time: 0 */
3494     0x00,                       /* feedback packet count: 0 */
3495     /* packet chunks: */
3496     0x20, 0x03,                 /* 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 1 1  */
3497     0x01, 0x01, 0x01,           /* recv deltas, +1, +1, +1 */
3498     0x00, 0x00, 0x00,           /* padding */
3499   };
3500 
3501   guint8 exp_fci1[] = {
3502     0x00, 0x04,                 /* base sequence number: 4 */
3503     0x00, 0x02,                 /* packet status count: 2 */
3504     0x00, 0x00, 0x00,           /* reference time: 0 */
3505     0x01,                       /* feedback packet count: 1 */
3506     /* packet chunks: */
3507     0x20, 0x02,                 /* 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 1 0 */
3508     0x04, 0x01,                 /* recv deltas, +4, +1, +1 */
3509   };
3510 
3511   guint8 exp_fci2[] = {
3512     0x00, 0x06,                 /* base sequence number: 6 */
3513     0x00, 0x04,                 /* packet status count: 4 */
3514     0x00, 0x00, 0x00,           /* reference time: 0 */
3515     0x02,                       /* feedback packet count: 2 */
3516     /* packet chunks: */
3517     0x20, 0x04,                 /* 0 0 1 0 0 0 0 0 | 0 0 0 0 0 1 0 0 */
3518     0x06, 0x01, 0x01, 0x01,     /* recv deltas, +6, +1, +1, +1 */
3519     0x00, 0x00,
3520   };
3521 
3522   twcc_push_packets (h, packets);
3523 
3524   /* we should get 1 SR/RR, and then 3x TWCC packets */
3525   buf = session_harness_produce_twcc (h);
3526   twcc_verify_fci (buf, exp_fci0);
3527   gst_buffer_unref (buf);
3528 
3529   buf = session_harness_produce_twcc (h);
3530   twcc_verify_fci (buf, exp_fci1);
3531   gst_buffer_unref (buf);
3532 
3533   buf = session_harness_produce_twcc (h);
3534   twcc_verify_fci (buf, exp_fci2);
3535   gst_buffer_unref (buf);
3536 
3537   session_harness_free (h);
3538 }
3539 
3540 GST_END_TEST;
3541 
GST_START_TEST(test_twcc_no_marker_and_gaps)3542 GST_START_TEST (test_twcc_no_marker_and_gaps)
3543 {
3544   SessionHarness *h = session_harness_new ();
3545   guint i;
3546 
3547   g_object_set (h->internal_session, "probation", 1, NULL);
3548 
3549   /* Push packets with gaps and no marker bit. This should not prevent
3550      the feedback packets from being sent at all. */
3551   for (i = 0; i < 100; i += 10) {
3552     TWCCPacket packets[] = { {i, i * 250 * GST_USECOND, FALSE}
3553     };
3554     twcc_push_packets (h, packets);
3555   }
3556 
3557   /* verify we did receive some feedback for these packets */
3558   gst_buffer_unref (session_harness_produce_twcc (h));
3559 
3560   session_harness_free (h);
3561 }
3562 
3563 GST_END_TEST;
3564 
3565 static GstBuffer *
generate_twcc_feedback_rtcp(guint8 * fci_data,guint16 fci_length)3566 generate_twcc_feedback_rtcp (guint8 * fci_data, guint16 fci_length)
3567 {
3568   GstRTCPPacket packet;
3569   GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
3570   GstBuffer *buffer = gst_rtcp_buffer_new (1000);
3571   guint8 *fci;
3572 
3573   fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
3574   fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_RTPFB,
3575           &packet));
3576   gst_rtcp_packet_fb_set_type (&packet, GST_RTCP_RTPFB_TYPE_TWCC);
3577   gst_rtcp_packet_fb_set_fci_length (&packet, fci_length);
3578   fci = gst_rtcp_packet_fb_get_fci (&packet);
3579   memcpy (fci, fci_data, fci_length);
3580   gst_rtcp_packet_fb_set_sender_ssrc (&packet, TEST_BUF_SSRC);
3581   gst_rtcp_packet_fb_set_media_ssrc (&packet, 0);
3582   gst_rtcp_buffer_unmap (&rtcp);
3583 
3584   return buffer;
3585 }
3586 
GST_START_TEST(test_twcc_bad_rtcp)3587 GST_START_TEST (test_twcc_bad_rtcp)
3588 {
3589   SessionHarness *h = session_harness_new ();
3590   guint i;
3591   GstBuffer *buf;
3592   GstEvent *event;
3593   GValueArray *packets_array;
3594 
3595   guint8 fci[] = {
3596     0xff, 0xff,                 /* base sequence number: max */
3597     0xff, 0xff,                 /* packet status count: max */
3598     0xff, 0xff, 0xff,           /* reference time: max */
3599     0xff,                       /* feedback packet count: max */
3600     0x3f, 0xff,                 /* packet chunk: run-length, max */
3601     0x00,                       /* only 1 recv-delta */
3602   };
3603 
3604   buf = generate_twcc_feedback_rtcp (fci, sizeof (fci));
3605   session_harness_recv_rtcp (h, buf);
3606 
3607   /* two reconfigure events */
3608   for (i = 0; i < 2; i++)
3609     gst_event_unref (gst_harness_pull_upstream_event (h->send_rtp_h));
3610 
3611   event = gst_harness_pull_upstream_event (h->send_rtp_h);
3612   packets_array =
3613       g_value_get_boxed (gst_structure_get_value (gst_event_get_structure
3614           (event), "packets"));
3615 
3616   /* this ends up with 0 packets, due to completely invalid data */
3617   fail_unless_equals_int (packets_array->n_values, 0);
3618 
3619   gst_event_unref (event);
3620   session_harness_free (h);
3621 }
3622 
3623 GST_END_TEST;
3624 
GST_START_TEST(test_twcc_delta_ts_rounding)3625 GST_START_TEST (test_twcc_delta_ts_rounding)
3626 {
3627   SessionHarness *h = session_harness_new ();
3628   guint i, j = 0;
3629   GstEvent *event;
3630   GstBuffer *buf;
3631   GValueArray *packets_array;
3632 
3633   TWCCPacket packets[] = {
3634     {2002, 9 * GST_SECOND + 366458177, FALSE}
3635     ,
3636     {2003, 9 * GST_SECOND + 366497068, FALSE}
3637     ,
3638     {2017, 9 * GST_SECOND + 366929482, FALSE}
3639     ,
3640     {2019, 9 * GST_SECOND + 391595309, FALSE}
3641     ,
3642     {2020, 9 * GST_SECOND + 426883507, FALSE}
3643     ,
3644     {2025, 9 * GST_SECOND + 427021638, TRUE}
3645     ,
3646   };
3647 
3648   TWCCPacket exp_packets[] = {
3649     {2002, 9 * GST_SECOND + 366250000, FALSE}
3650     ,
3651     {2003, 9 * GST_SECOND + 366250000, FALSE}
3652     ,
3653     {2017, 9 * GST_SECOND + 366750000, FALSE}
3654     ,
3655     {2019, 9 * GST_SECOND + 391500000, FALSE}
3656     ,
3657     {2020, 9 * GST_SECOND + 426750000, FALSE}
3658     ,
3659     {2025, 9 * GST_SECOND + 427000000, TRUE}
3660     ,
3661   };
3662 
3663   guint8 exp_fci[] = {
3664     0x07, 0xd2,                 /* base sequence number: 2002 */
3665     0x00, 0x18,                 /* packet status count: 24 */
3666     0x00, 0x00, 0x92,           /* reference time: 0:00:09.344000000 */
3667     0x00,                       /* feedback packet count: 0 */
3668     0xb0, 0x00,                 /* packet chunk: 1 0 1 1 0 0 0 0 | 0 0 0 0 0 0 0 0 */
3669     0x96, 0x10,                 /* packet chunk: 1 0 0 1 0 1 1 0 | 0 0 0 1 0 0 0 0 */
3670     0x59,                       /* recv delta: 0:00:00.022250000 abs: 0:00:09.366250000 */
3671     0x00,                       /* recv delta: 0:00:00.000000000 abs: 0:00:09.366250000 */
3672     0x02,                       /* recv delta: 0:00:00.000500000 abs: 0:00:09.366750000 */
3673     0x63,                       /* recv delta: 0:00:00.024750000 abs: 0:00:09.391500000 */
3674     0x8d,                       /* recv delta: 0:00:00.035250000 abs: 0:00:09.426750000 */
3675     0x01,                       /* recv delta: 0:00:00.000250000 abs: 0:00:09.427000000 */
3676     0x00, 0x00,                 /* padding */
3677   };
3678 
3679   twcc_push_packets (h, packets);
3680   buf = session_harness_produce_twcc (h);
3681   twcc_verify_fci (buf, exp_fci);
3682 
3683   session_harness_recv_rtcp (h, buf);
3684   for (i = 0; i < 2; i++)
3685     gst_event_unref (gst_harness_pull_upstream_event (h->send_rtp_h));
3686   event = gst_harness_pull_upstream_event (h->send_rtp_h);
3687 
3688   packets_array =
3689       g_value_get_boxed (gst_structure_get_value (gst_event_get_structure
3690           (event), "packets"));
3691   for (i = 0; i < packets_array->n_values; i++) {
3692     TWCCPacket *twcc_pkt;
3693     const GstStructure *pkt_s =
3694         gst_value_get_structure (g_value_array_get_nth (packets_array, i));
3695     GstClockTime ts;
3696     guint seqnum;
3697     gboolean lost;
3698     fail_unless (gst_structure_get_boolean (pkt_s, "lost", &lost));
3699     if (lost)
3700       continue;
3701     twcc_pkt = &exp_packets[j++];
3702 
3703     fail_unless (gst_structure_get_clock_time (pkt_s, "remote-ts", &ts));
3704     fail_unless (gst_structure_get_uint (pkt_s, "seqnum", &seqnum));
3705 
3706     fail_unless_equals_int (twcc_pkt->seqnum, seqnum);
3707     fail_unless_equals_clocktime (twcc_pkt->timestamp, ts);
3708   }
3709 
3710   gst_event_unref (event);
3711   session_harness_free (h);
3712 }
3713 
3714 GST_END_TEST;
3715 
GST_START_TEST(test_twcc_double_gap)3716 GST_START_TEST (test_twcc_double_gap)
3717 {
3718   SessionHarness *h0 = session_harness_new ();
3719   SessionHarness *h1 = session_harness_new ();
3720 
3721   TWCCPacket packets[] = {
3722     {1202, 5 * GST_SECOND + 717000000, FALSE}
3723     ,
3724     {1215, 5 * GST_SECOND + 760250000, FALSE}
3725     ,
3726     {1221, 5 * GST_SECOND + 775500000, TRUE}
3727     ,
3728   };
3729 
3730   guint8 exp_fci[] = {
3731     0x04, 0xb2,                 /* base sequence number: 1202 */
3732     0x00, 0x14,                 /* packet status count: 20 */
3733     0x00, 0x00, 0x59,           /* reference time: 0:00:05.696000000 */
3734     0x00,                       /* feedback packet count: 0 */
3735     0xa0, 0x01,                 /* packet chunk: 1 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 1 */
3736     0x81, 0x00,                 /* packet chunk: 1 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 0 */
3737     0x54,                       /* recv delta: +0:00:00.021000000 */
3738     0xad,                       /* recv delta: +0:00:00.043250000 */
3739     0x3d,                       /* recv delta: +0:00:00.015250000 */
3740     0x00,                       /* padding */
3741   };
3742 
3743   twcc_verify_packets_to_fci (h0, packets, exp_fci);
3744 
3745   twcc_verify_packets_to_packets (h1, h1, packets);
3746 
3747   session_harness_free (h0);
3748   session_harness_free (h1);
3749 }
3750 
3751 GST_END_TEST;
3752 
GST_START_TEST(test_twcc_recv_packets_reordered)3753 GST_START_TEST (test_twcc_recv_packets_reordered)
3754 {
3755   SessionHarness *h = session_harness_new ();
3756   GstBuffer *buf;
3757 
3758   /* a reordered seqence, with marker-bits for #3 and #4 */
3759   TWCCPacket packets[] = {
3760     {1, 1 * 250 * GST_USECOND, FALSE}
3761     ,
3762     {3, 2 * 250 * GST_USECOND, TRUE}
3763     ,
3764     {2, 3 * 250 * GST_USECOND, FALSE}
3765     ,
3766     {4, 4 * 250 * GST_USECOND, TRUE}
3767     ,
3768   };
3769 
3770   /* first we expect #2 to be reported lost */
3771   guint8 exp_fci0[] = {
3772     0x00, 0x01,                 /* base sequence number: 1 */
3773     0x00, 0x03,                 /* packet status count: 3 */
3774     0x00, 0x00, 0x00,           /* reference time: 0 */
3775     0x00,                       /* feedback packet count: 0 */
3776     /* packet chunks: */
3777     0xa8, 0x00,                 /* 1 0 1 0 1 0 0 0 | 0 0 0 0 0 0 0 0 */
3778     0x01, 0x01,                 /* recv deltas, +1, +1 */
3779   };
3780 
3781   /* and then when 2 actually arrives, it is already reported lost,
3782      so we will not re-report it, but drop it */
3783   guint8 exp_fci1[] = {
3784     0x00, 0x04,                 /* base sequence number: 4 */
3785     0x00, 0x01,                 /* packet status count: 1 */
3786     0x00, 0x00, 0x00,           /* reference time: 0 */
3787     0x01,                       /* feedback packet count: 1 */
3788     /* packet chunks: */
3789     0x20, 0x01,                 /* 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 1 */
3790     0x04,                       /* recv deltas, +4 */
3791     0x00,                       /* padding */
3792   };
3793 
3794   twcc_push_packets (h, packets);
3795 
3796   buf = session_harness_produce_twcc (h);
3797   twcc_verify_fci (buf, exp_fci0);
3798   gst_buffer_unref (buf);
3799 
3800   buf = session_harness_produce_twcc (h);
3801   twcc_verify_fci (buf, exp_fci1);
3802   gst_buffer_unref (buf);
3803 
3804   session_harness_free (h);
3805 }
3806 
3807 GST_END_TEST;
3808 
GST_START_TEST(test_twcc_recv_late_packet_fb_pkt_count_wrap)3809 GST_START_TEST (test_twcc_recv_late_packet_fb_pkt_count_wrap)
3810 {
3811   SessionHarness *h = session_harness_new ();
3812   GstBuffer *buf;
3813   guint i;
3814 
3815   guint8 exp_fci0[] = {
3816     0x01, 0x00,                 /* base sequence number: 256 */
3817     0x00, 0x01,                 /* packet status count: 1 */
3818     0x00, 0x00, 0x01,           /* reference time: 1 */
3819     0x00,                       /* feedback packet count: 00 */
3820     /* packet chunks: */
3821     0x20, 0x01,                 /* 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 1 */
3822     0x00,                       /* 0 recv-delta */
3823     0x00,                       /* padding */
3824   };
3825 
3826   guint8 exp_fci1[] = {
3827     0x01, 0x01,                 /* base sequence number: 257 */
3828     0x00, 0x01,                 /* packet status count: 1 */
3829     0x00, 0x00, 0x01,           /* reference time: 1 */
3830     0x01,                       /* feedback packet count: 1 */
3831     /* packet chunks: */
3832     0x20, 0x01,                 /* 0 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 1 */
3833     0x01,                       /* 1 recv-delta */
3834     0x00,                       /* padding */
3835   };
3836 
3837   session_harness_set_twcc_recv_ext_id ((h), TEST_TWCC_EXT_ID);
3838 
3839   /* Push packets to get the feedback packet count wrap limit */
3840   for (i = 0; i < 255; i++) {
3841     GstClockTime ts = i * 250 * GST_USECOND;
3842     gst_test_clock_set_time (h->testclock, ts);
3843     fail_unless_equals_int (GST_FLOW_OK,
3844         session_harness_recv_rtp ((h),
3845             generate_twcc_recv_buffer (i, ts, TRUE)));
3846   }
3847 
3848   /* push pkt #256 to jump ahead and force the overflow */
3849   gst_test_clock_set_time (h->testclock, 256 * 250 * GST_USECOND);
3850   fail_unless_equals_int (GST_FLOW_OK,
3851       session_harness_recv_rtp ((h),
3852           generate_twcc_recv_buffer (256, 256 * 250 * GST_USECOND, TRUE)));
3853 
3854   /* pkt #255 is late and should be dropped */
3855   fail_unless_equals_int (GST_FLOW_OK,
3856       session_harness_recv_rtp ((h),
3857           generate_twcc_recv_buffer (255, 255 * 250 * GST_USECOND, TRUE)));
3858 
3859 
3860   /* push pkt #257 to verify fci is correct */
3861   gst_test_clock_set_time (h->testclock, 257 * 250 * GST_USECOND);
3862   fail_unless_equals_int (GST_FLOW_OK,
3863       session_harness_recv_rtp ((h),
3864           generate_twcc_recv_buffer (257, 257 * 250 * GST_USECOND, TRUE)));
3865 
3866   /* ignore the twcc for the first 255 packets  */
3867   for (i = 0; i < 255; i++)
3868     gst_buffer_unref (session_harness_produce_twcc (h));
3869 
3870   /* we expect a fci for pkt #256 */
3871   buf = session_harness_produce_twcc (h);
3872   twcc_verify_fci (buf, exp_fci0);
3873   gst_buffer_unref (buf);
3874 
3875   /* and one fci for pkt #257 */
3876   buf = session_harness_produce_twcc (h);
3877   twcc_verify_fci (buf, exp_fci1);
3878   gst_buffer_unref (buf);
3879 
3880   session_harness_free (h);
3881 }
3882 
3883 GST_END_TEST;
3884 
GST_START_TEST(test_twcc_recv_rtcp_reordered)3885 GST_START_TEST (test_twcc_recv_rtcp_reordered)
3886 {
3887   SessionHarness *send_h = session_harness_new ();
3888   SessionHarness *recv_h = session_harness_new ();
3889   GstBuffer *buf[4];
3890   GstEvent *event;
3891   guint i;
3892 
3893   /* three frames, two packets each */
3894   TWCCPacket packets[] = {
3895     {1, 1 * GST_SECOND, FALSE}
3896     ,
3897     {2, 2 * GST_SECOND, TRUE}
3898     ,
3899     {3, 3 * GST_SECOND, FALSE}
3900     ,
3901     {4, 4 * GST_SECOND, TRUE}
3902     ,
3903     {5, 5 * GST_SECOND, FALSE}
3904     ,
3905     {6, 6 * GST_SECOND, TRUE}
3906     ,
3907     {7, 7 * GST_SECOND, FALSE}
3908     ,
3909     {8, 8 * GST_SECOND, TRUE}
3910     ,
3911   };
3912 
3913 /*
3914   TWCCPacket expected_packets0[] = {
3915     {1, 1 * 250 * GST_USECOND, FALSE},
3916     {2, 2 * 250 * GST_USECOND, TRUE},
3917   };
3918 */
3919   twcc_push_packets (recv_h, packets);
3920 
3921   buf[0] = session_harness_produce_twcc (recv_h);
3922   buf[1] = session_harness_produce_twcc (recv_h);
3923   buf[2] = session_harness_produce_twcc (recv_h);
3924   buf[3] = session_harness_produce_twcc (recv_h);
3925 
3926   /* reorder the twcc-feedback */
3927   session_harness_recv_rtcp (send_h, buf[0]);
3928   session_harness_recv_rtcp (send_h, buf[2]);
3929   session_harness_recv_rtcp (send_h, buf[1]);
3930   session_harness_recv_rtcp (send_h, buf[3]);
3931 
3932   for (i = 0; i < 2; i++)
3933     gst_event_unref (gst_harness_pull_upstream_event (send_h->send_rtp_h));
3934 
3935   event = gst_harness_pull_upstream_event (send_h->send_rtp_h);
3936   twcc_verify_packets_to_event (&packets[0 * 2], event);
3937 
3938   event = gst_harness_pull_upstream_event (send_h->send_rtp_h);
3939   twcc_verify_packets_to_event (&packets[2 * 2], event);
3940 
3941   event = gst_harness_pull_upstream_event (send_h->send_rtp_h);
3942   twcc_verify_packets_to_event (&packets[1 * 2], event);
3943 
3944   event = gst_harness_pull_upstream_event (send_h->send_rtp_h);
3945   twcc_verify_packets_to_event (&packets[3 * 2], event);
3946 
3947   session_harness_free (send_h);
3948   session_harness_free (recv_h);
3949 }
3950 
3951 GST_END_TEST;
3952 
GST_START_TEST(test_twcc_no_exthdr_in_buffer)3953 GST_START_TEST (test_twcc_no_exthdr_in_buffer)
3954 {
3955   SessionHarness *h = session_harness_new ();
3956 
3957   session_harness_set_twcc_recv_ext_id (h, TEST_TWCC_EXT_ID);
3958 
3959   fail_unless_equals_int (GST_FLOW_OK,
3960       session_harness_recv_rtp (h, generate_test_buffer (0, 1234)));
3961   session_harness_free (h);
3962 }
3963 
3964 GST_END_TEST;
3965 
GST_START_TEST(test_twcc_send_and_recv)3966 GST_START_TEST (test_twcc_send_and_recv)
3967 {
3968   SessionHarness *h_send = session_harness_new ();
3969   SessionHarness *h_recv = session_harness_new ();
3970   guint frame;
3971   const guint num_frames = 2;
3972   const guint num_slices = 15;
3973 
3974   /* enable twcc */
3975   session_harness_set_twcc_recv_ext_id (h_recv, TEST_TWCC_EXT_ID);
3976   session_harness_set_twcc_send_ext_id (h_send, TEST_TWCC_EXT_ID);
3977 
3978   for (frame = 0; frame < num_frames; frame++) {
3979     GstBuffer *buf;
3980     guint slice;
3981 
3982     for (slice = 0; slice < num_slices; slice++) {
3983       GstFlowReturn res;
3984       guint seq = frame * num_slices + slice;
3985 
3986       /* from payloder to rtpbin */
3987       buf = generate_twcc_send_buffer (seq, slice == num_slices - 1);
3988       res = session_harness_send_rtp (h_send, buf);
3989       fail_unless_equals_int (GST_FLOW_OK, res);
3990       session_harness_advance_and_crank (h_send, TEST_BUF_DURATION);
3991 
3992       /* get the buffer ready for the network */
3993       buf = session_harness_pull_send_rtp (h_send);
3994 
3995       /* buffer arrives at the receiver */
3996       res = session_harness_recv_rtp (h_recv, buf);
3997       fail_unless_equals_int (GST_FLOW_OK, res);
3998     }
3999 
4000     /* receiver sends a TWCC packet to the sender */
4001     buf = session_harness_produce_twcc (h_recv);
4002 
4003     /* sender receives the TWCC packet */
4004     session_harness_recv_rtcp (h_send, buf);
4005 
4006     if (frame > 0)
4007       twcc_verify_stats (h_send, TEST_BUF_BPS, TEST_BUF_BPS, num_slices,
4008           num_slices, 0.0f, 0);
4009   }
4010 
4011   session_harness_free (h_send);
4012   session_harness_free (h_recv);
4013 }
4014 
4015 GST_END_TEST;
4016 
GST_START_TEST(test_twcc_multiple_payloads_below_window)4017 GST_START_TEST (test_twcc_multiple_payloads_below_window)
4018 {
4019   SessionHarness *h_send = session_harness_new ();
4020   SessionHarness *h_recv = session_harness_new ();
4021 
4022   guint i;
4023 
4024   GstBuffer *buffers[] = {
4025     generate_twcc_send_buffer_full (0, FALSE, 0xabc, 98),
4026     generate_twcc_send_buffer_full (0, FALSE, 0xdef, 111),
4027     generate_twcc_send_buffer_full (1, FALSE, 0xdef, 111),
4028     generate_twcc_send_buffer_full (2, FALSE, 0xdef, 111),
4029     generate_twcc_send_buffer_full (1, TRUE, 0xabc, 98),
4030   };
4031 
4032   /* enable twcc */
4033   session_harness_set_twcc_recv_ext_id (h_recv, TEST_TWCC_EXT_ID);
4034   session_harness_set_twcc_send_ext_id (h_send, TEST_TWCC_EXT_ID);
4035 
4036   for (i = 0; i < G_N_ELEMENTS (buffers); i++) {
4037     GstBuffer *buf = buffers[i];
4038     GstFlowReturn res;
4039 
4040     /* from payloder to rtpbin */
4041     res = session_harness_send_rtp (h_send, buf);
4042     fail_unless_equals_int (GST_FLOW_OK, res);
4043 
4044     buf = session_harness_pull_send_rtp (h_send);
4045     session_harness_advance_and_crank (h_send, TEST_BUF_DURATION);
4046 
4047     /* buffer arrives at the receiver */
4048     res = session_harness_recv_rtp (h_recv, buf);
4049     fail_unless_equals_int (GST_FLOW_OK, res);
4050   }
4051 
4052   /* sender receives the TWCC packet from the receiver */
4053   session_harness_recv_rtcp (h_send, session_harness_produce_twcc (h_recv));
4054   twcc_verify_stats (h_send, 0, 0, 5, 5, 0.0f, GST_CLOCK_STIME_NONE);
4055 
4056   session_harness_free (h_send);
4057   session_harness_free (h_recv);
4058 }
4059 
4060 GST_END_TEST;
4061 
4062 typedef struct
4063 {
4064   GstClockTime interval;
4065   guint num_packets;
4066   GstClockTime ts_delta;
4067   guint num_feedback;
4068 } TWCCFeedbackIntervalCtx;
4069 
4070 static TWCCFeedbackIntervalCtx test_twcc_feedback_interval_ctx[] = {
4071   {50 * GST_MSECOND, 21, 10 * GST_MSECOND, 4},
4072   {50 * GST_MSECOND, 16, 7 * GST_MSECOND, 2},
4073   {50 * GST_MSECOND, 16, 66 * GST_MSECOND, 15},
4074   {50 * GST_MSECOND, 15, 33 * GST_MSECOND, 9},
4075 };
4076 
GST_START_TEST(test_twcc_feedback_interval)4077 GST_START_TEST (test_twcc_feedback_interval)
4078 {
4079   SessionHarness *h = session_harness_new ();
4080   GstBuffer *buf;
4081   TWCCFeedbackIntervalCtx *ctx = &test_twcc_feedback_interval_ctx[__i__];
4082 
4083   session_harness_set_twcc_recv_ext_id (h, TEST_TWCC_EXT_ID);
4084   g_object_set (h->internal_session, "twcc-feedback-interval", ctx->interval,
4085       NULL);
4086 
4087   for (guint i = 0; i < ctx->num_packets; i++) {
4088     GstClockTime ts = i * ctx->ts_delta;
4089     gst_test_clock_set_time ((h->testclock), ts);
4090     fail_unless_equals_int (GST_FLOW_OK,
4091         session_harness_recv_rtp (h, generate_twcc_recv_buffer (i, ts, FALSE)));
4092   }
4093 
4094   for (guint i = 0; i < ctx->num_feedback; i++) {
4095     buf = session_harness_produce_twcc (h);
4096     gst_buffer_unref (buf);
4097   }
4098 
4099   session_harness_free (h);
4100 }
4101 
4102 GST_END_TEST;
4103 
GST_START_TEST(test_twcc_feedback_count_wrap)4104 GST_START_TEST (test_twcc_feedback_count_wrap)
4105 {
4106   SessionHarness *h = session_harness_new ();
4107   guint i;
4108   GstBuffer *buf;
4109   GstEvent *event;
4110   GValueArray *packets_array;
4111 
4112   guint8 fci1[] = {
4113     0x05, 0xfd,                 /* base sequence number: 1533 */
4114     0x00, 0x00,                 /* packet status count: 0 */
4115     0x00, 0x00, 0x00,           /* reference time: 0 */
4116     0xff,                       /* feedback packet count: 255 */
4117     0x00, 0x00,                 /* packet chunk: run-length, 0 */
4118     0x00,                       /* 0 recv-delta */
4119   };
4120 
4121   guint8 fci2[] = {
4122     0x05, 0xfe,                 /* base sequence number: 1534 */
4123     0x00, 0x00,                 /* packet status count: 0 */
4124     0x00, 0x00, 0x00,           /* reference time: 0 */
4125     0x01,                       /* feedback packet count: 1 */
4126     0x00, 0x00,                 /* packet chunk: run-length, 0 */
4127     0x00,                       /* 0 recv-delta */
4128   };
4129 
4130   buf = generate_twcc_feedback_rtcp (fci1, sizeof (fci1));
4131   session_harness_recv_rtcp (h, buf);
4132 
4133   buf = generate_twcc_feedback_rtcp (fci2, sizeof (fci2));
4134   session_harness_recv_rtcp (h, buf);
4135 
4136   /* two reconfigure events */
4137   for (i = 0; i < 2; i++)
4138     gst_event_unref (gst_harness_pull_upstream_event (h->send_rtp_h));
4139 
4140 
4141   for (i = 0; i < 2; i++) {
4142     event = gst_harness_pull_upstream_event (h->send_rtp_h);
4143     packets_array =
4144         g_value_get_boxed (gst_structure_get_value (gst_event_get_structure
4145             (event), "packets"));
4146 
4147     /* we expect zero packets due to feedback packet count jump ahead */
4148     fail_unless_equals_int (packets_array->n_values, 0);
4149     gst_event_unref (event);
4150   }
4151 
4152   session_harness_free (h);
4153 }
4154 
4155 GST_END_TEST;
4156 
GST_START_TEST(test_twcc_feedback_old_seqnum)4157 GST_START_TEST (test_twcc_feedback_old_seqnum)
4158 {
4159   SessionHarness *h = session_harness_new ();
4160   guint i;
4161   GstBuffer *buf;
4162   GstEvent *event;
4163   GValueArray *packets_array;
4164 
4165   guint8 fci1[] = {
4166     0x05, 0xfd,                 /* base sequence number: 1533 */
4167     0x00, 0x00,                 /* packet status count: 0 */
4168     0x00, 0x00, 0x00,           /* reference time: 0 */
4169     0x00,                       /* feedback packet count: 255 */
4170     0x00, 0x00,                 /* packet chunk: run-length, 0 */
4171     0x00,                       /* 0 recv-delta */
4172   };
4173 
4174   guint8 fci2[] = {
4175     0x05, 0xdc,                 /* base sequence number: 1500 */
4176     0x00, 0x00,                 /* packet status count: 0 */
4177     0x00, 0x00, 0x00,           /* reference time: 0 */
4178     0x01,                       /* feedback packet count: 1 */
4179     0x00, 0x00,                 /* packet chunk: run-length, 0 */
4180     0x00,                       /* 0 recv-delta */
4181   };
4182 
4183   buf = generate_twcc_feedback_rtcp (fci1, sizeof (fci1));
4184   session_harness_recv_rtcp (h, buf);
4185 
4186   buf = generate_twcc_feedback_rtcp (fci2, sizeof (fci2));
4187   session_harness_recv_rtcp (h, buf);
4188 
4189   /* two reconfigure events */
4190   for (i = 0; i < 2; i++)
4191     gst_event_unref (gst_harness_pull_upstream_event (h->send_rtp_h));
4192 
4193   for (i = 0; i < 2; i++) {
4194     event = gst_harness_pull_upstream_event (h->send_rtp_h);
4195     packets_array =
4196         g_value_get_boxed (gst_structure_get_value (gst_event_get_structure
4197             (event), "packets"));
4198 
4199     /* we expect zero packets due to old sequence number */
4200     fail_unless_equals_int (packets_array->n_values, 0);
4201     gst_event_unref (event);
4202   }
4203 
4204   session_harness_free (h);
4205 }
4206 
4207 GST_END_TEST;
4208 
GST_START_TEST(test_twcc_run_length_max)4209 GST_START_TEST (test_twcc_run_length_max)
4210 {
4211   SessionHarness *h0 = session_harness_new ();
4212   SessionHarness *h1 = session_harness_new ();
4213 
4214   TWCCPacket packets[] = {
4215     /* *INDENT-OFF* */
4216     {0, 1000 * GST_USECOND, FALSE},
4217     {8205, 2000 * GST_USECOND, TRUE},
4218     /* *INDENT-ON* */
4219   };
4220 
4221   guint8 exp_fci[] = {
4222     0x00, 0x00,                 /* base sequence number: 0 */
4223     0x20, 0x0e,                 /* packet status count: 8206 */
4224     0x00, 0x00, 0x00,           /* reference time: 0 */
4225     0x00,                       /* feedback packet count: 0 */
4226 
4227     0xa0, 0x00,                 /* 1bit status for #0 received:                               1 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */
4228     0x1f, 0xff,                 /* run-length with max length is reported as not received:    0 0 0 1 1 1 1 1 | 1 1 1 1 1 1 1 1 */
4229     0xa0, 0x00,                 /* 1bit status for #8205 received:                            1 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */
4230 
4231     0x04,                       /* recv delta: +0:00:00.001000000 */
4232     0x04,                       /* recv delta: +0:00:00.001000000 */
4233   };
4234 
4235   twcc_verify_packets_to_fci (h0, packets, exp_fci);
4236   twcc_verify_packets_to_packets (h1, h1, packets);
4237 
4238   session_harness_free (h0);
4239   session_harness_free (h1);
4240 }
4241 
4242 GST_END_TEST;
4243 
GST_START_TEST(test_twcc_run_length_min)4244 GST_START_TEST (test_twcc_run_length_min)
4245 {
4246   SessionHarness *h0 = session_harness_new ();
4247   SessionHarness *h1 = session_harness_new ();
4248 
4249   TWCCPacket packets[] = {
4250     /* *INDENT-OFF* */
4251     {0, 1000 * GST_USECOND, FALSE},
4252     {29, 2000 * GST_USECOND, TRUE},
4253     /* *INDENT-ON* */
4254   };
4255 
4256   guint8 exp_fci[] = {
4257     0x00, 0x00,                 /* base sequence number: 0 */
4258     0x00, 0x1e,                 /* packet status count: 30 */
4259     0x00, 0x00, 0x00,           /* reference time: 0 */
4260     0x00,                       /* feedback packet count: 0 */
4261 
4262     0xa0, 0x00,                 /* 1bit status for #0 received:                      1 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */
4263     0x00, 0x0f,                 /* run-length with length of 15, all not received:   0 0 0 0 0 0 0 0 | 0 0 0 0 1 1 1 1 */
4264     0xa0, 0x00,                 /* 1bit status for #29 received:                     1 0 1 0 0 0 0 0 | 0 0 0 0 0 0 0 0 */
4265 
4266     0x04,                       /* recv delta: +0:00:00.001000000 */
4267     0x04,                       /* recv delta: +0:00:00.001000000 */
4268   };
4269 
4270   twcc_verify_packets_to_fci (h0, packets, exp_fci);
4271   twcc_verify_packets_to_packets (h1, h1, packets);
4272 
4273   session_harness_free (h0);
4274   session_harness_free (h1);
4275 }
4276 
4277 GST_END_TEST;
4278 
4279 
4280 static Suite *
rtpsession_suite(void)4281 rtpsession_suite (void)
4282 {
4283   Suite *s = suite_create ("rtpsession");
4284   TCase *tc_chain = tcase_create ("general");
4285 
4286   suite_add_tcase (s, tc_chain);
4287   tcase_add_test (tc_chain, test_multiple_ssrc_rr);
4288   tcase_add_test (tc_chain, test_multiple_senders_roundrobin_rbs);
4289   tcase_add_test (tc_chain, test_no_rbs_for_internal_senders);
4290   tcase_add_test (tc_chain, test_internal_sources_timeout);
4291   tcase_add_test (tc_chain, test_receive_rtcp_app_packet);
4292   tcase_add_test (tc_chain, test_dont_lock_on_stats);
4293   tcase_add_test (tc_chain, test_ignore_suspicious_bye);
4294 
4295   tcase_add_test (tc_chain, test_ssrc_collision_when_sending);
4296   tcase_add_test (tc_chain, test_ssrc_collision_when_sending_loopback);
4297   tcase_add_test (tc_chain, test_ssrc_collision_when_receiving);
4298   tcase_add_test (tc_chain, test_ssrc_collision_third_party);
4299   tcase_add_test (tc_chain, test_ssrc_collision_third_party_favor_new);
4300   tcase_add_test (tc_chain,
4301       test_ssrc_collision_never_send_on_non_internal_source);
4302 
4303   tcase_add_test (tc_chain, test_request_fir);
4304   tcase_add_test (tc_chain, test_request_pli);
4305   tcase_add_test (tc_chain, test_request_fir_after_pli_in_caps);
4306   tcase_add_test (tc_chain, test_request_nack);
4307   tcase_add_test (tc_chain, test_request_nack_surplus);
4308   tcase_add_test (tc_chain, test_request_nack_packing);
4309   tcase_add_test (tc_chain, test_illegal_rtcp_fb_packet);
4310   tcase_add_test (tc_chain, test_feedback_rtcp_race);
4311   tcase_add_test (tc_chain, test_receive_regular_pli);
4312   tcase_add_test (tc_chain, test_receive_pli_no_sender_ssrc);
4313   tcase_add_test (tc_chain, test_dont_send_rtcp_while_idle);
4314   tcase_add_test (tc_chain, test_send_rtcp_when_signalled);
4315   tcase_add_test (tc_chain, test_change_sent_sdes);
4316   tcase_add_test (tc_chain, test_disable_sr_timestamp);
4317   tcase_add_test (tc_chain, test_on_sending_nacks);
4318   tcase_add_test (tc_chain, test_disable_probation);
4319   tcase_add_test (tc_chain, test_request_late_nack);
4320   tcase_add_test (tc_chain, test_clear_pt_map_stress);
4321   tcase_add_test (tc_chain, test_packet_rate);
4322   tcase_add_test (tc_chain, test_stepped_packet_rate);
4323 
4324   /* twcc */
4325   tcase_add_loop_test (tc_chain, test_twcc_header_and_run_length,
4326       0, G_N_ELEMENTS (twcc_header_and_run_length_test_data));
4327   tcase_add_test (tc_chain, test_twcc_run_length_max);
4328   tcase_add_test (tc_chain, test_twcc_run_length_min);
4329   tcase_add_test (tc_chain, test_twcc_1_bit_status_vector);
4330   tcase_add_test (tc_chain, test_twcc_2_bit_status_vector);
4331   tcase_add_test (tc_chain, test_twcc_2_bit_over_capacity);
4332   tcase_add_test (tc_chain, test_twcc_2_bit_full_status_vector);
4333   tcase_add_test (tc_chain, test_twcc_status_vector_split_large_delta);
4334   tcase_add_test (tc_chain, test_twcc_status_vector_split_with_gap);
4335   tcase_add_test (tc_chain, test_twcc_status_vector_split_into_three);
4336   tcase_add_loop_test (tc_chain, test_twcc_various_gaps, 0, 50);
4337   tcase_add_test (tc_chain, test_twcc_negative_delta);
4338   tcase_add_test (tc_chain, test_twcc_seqnum_wrap);
4339   tcase_add_test (tc_chain, test_twcc_seqnum_wrap_with_loss);
4340   tcase_add_test (tc_chain, test_twcc_huge_seqnum_gap);
4341   tcase_add_test (tc_chain, test_twcc_double_packets);
4342   tcase_add_test (tc_chain, test_twcc_duplicate_seqnums);
4343   tcase_add_test (tc_chain, test_twcc_multiple_markers);
4344   tcase_add_test (tc_chain, test_twcc_no_marker_and_gaps);
4345   tcase_add_test (tc_chain, test_twcc_bad_rtcp);
4346   tcase_add_test (tc_chain, test_twcc_delta_ts_rounding);
4347   tcase_add_test (tc_chain, test_twcc_double_gap);
4348   tcase_add_test (tc_chain, test_twcc_recv_packets_reordered);
4349   tcase_add_test (tc_chain, test_twcc_recv_late_packet_fb_pkt_count_wrap);
4350   tcase_add_test (tc_chain, test_twcc_recv_rtcp_reordered);
4351   tcase_add_test (tc_chain, test_twcc_no_exthdr_in_buffer);
4352   tcase_add_test (tc_chain, test_twcc_send_and_recv);
4353   tcase_add_test (tc_chain, test_twcc_multiple_payloads_below_window);
4354   tcase_add_loop_test (tc_chain, test_twcc_feedback_interval, 0,
4355       G_N_ELEMENTS (test_twcc_feedback_interval_ctx));
4356   tcase_add_test (tc_chain, test_twcc_feedback_count_wrap);
4357   tcase_add_test (tc_chain, test_twcc_feedback_old_seqnum);
4358 
4359   return s;
4360 }
4361 
4362 GST_CHECK_MAIN (rtpsession);
4363