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