Merging gst-devtools
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / tests / check / elements / rtpbin_buffer_list.c
1 /* GStreamer
2  *
3  * Unit test for gstrtpbin sending rtp packets using GstBufferList.
4  * Copyright (C) 2009 Branko Subasic <branko dot subasic at axis dot com>
5  * Copyright 2019, Collabora Ltd.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include <gst/check/gstcheck.h>
24
25 #include <gst/rtp/gstrtpbuffer.h>
26 #include <gst/rtp/gstrtcpbuffer.h>
27
28 /* UDP/IP is assumed for bandwidth calculation */
29 #define UDP_IP_HEADER_OVERHEAD 28
30
31 /* This test makes sure that RTP packets sent as buffer lists are sent through
32  * the rtpbin as they are supposed to, and not corrupted in any way.
33  */
34
35
36 #define TEST_CAPS \
37   "application/x-rtp, "                \
38   "media=(string)video, "              \
39   "clock-rate=(int)90000, "            \
40   "encoding-name=(string)H264, "       \
41   "profile-level-id=(string)4d4015, "  \
42   "payload=(int)96, "                  \
43   "ssrc=(guint)2633237432, "           \
44   "clock-base=(guint)1868267015, "     \
45   "seqnum-base=(guint)54229"
46
47
48 /* RTP headers and the first 2 bytes of the payload (FU indicator and FU header)
49  */
50 static const guint8 rtp_header[2][14] = {
51   {0x80, 0x60, 0xbb, 0xb7, 0x5c, 0xe9, 0x09,
52       0x0d, 0xf5, 0x9c, 0x43, 0x55, 0x1c, 0x86},
53   {0x80, 0x60, 0xbb, 0xb8, 0x5c, 0xe9, 0x09,
54       0x0d, 0xf5, 0x9c, 0x43, 0x55, 0x1c, 0x46}
55 };
56
57 static const guint rtp_header_len[] = {
58   sizeof rtp_header[0],
59   sizeof rtp_header[1]
60 };
61
62 /* Some payload.
63  */
64 static const char *payload =
65     "0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF"
66     "0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF"
67     "0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF"
68     "0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF"
69     "0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF"
70     "0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF0123456789ABSDEF"
71     "0123456789ABSDEF0123456";
72
73 static const guint payload_offset[] = {
74   0, 498
75 };
76
77 static const guint payload_len[] = {
78   498, 5
79 };
80
81
82 static GstBuffer *original_buffer = NULL;
83
84 static GstStaticPadTemplate sinktemplate_rtcp = GST_STATIC_PAD_TEMPLATE ("sink",
85     GST_PAD_SINK,
86     GST_PAD_ALWAYS,
87     GST_STATIC_CAPS ("application/x-rtcp"));
88
89 static GstStaticPadTemplate srctemplate_rtcp = GST_STATIC_PAD_TEMPLATE ("src",
90     GST_PAD_SRC,
91     GST_PAD_ALWAYS,
92     GST_STATIC_CAPS ("application/x-rtcp"));
93
94 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
95     GST_PAD_SINK,
96     GST_PAD_ALWAYS,
97     GST_STATIC_CAPS ("application/x-rtp"));
98
99 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
100     GST_PAD_SRC,
101     GST_PAD_ALWAYS,
102     GST_STATIC_CAPS ("application/x-rtp"));
103
104
105 static GstBuffer *
106 create_original_buffer (void)
107 {
108   if (original_buffer != NULL)
109     return original_buffer;
110
111   original_buffer =
112       gst_buffer_new_wrapped ((guint8 *) payload, strlen (payload));
113   fail_unless (original_buffer != NULL);
114
115   GST_BUFFER_TIMESTAMP (original_buffer) =
116       gst_clock_get_internal_time (gst_system_clock_obtain ());
117
118   return original_buffer;
119 }
120
121 static GstBuffer *
122 create_rtp_packet_buffer (gconstpointer header, gint header_size,
123     GstBuffer * payload_buffer, gint payload_offset, gint payload_size)
124 {
125   GstBuffer *buffer;
126   GstBuffer *sub_buffer;
127
128   /* Create buffer with RTP header. */
129   buffer = gst_buffer_new_allocate (NULL, header_size, NULL);
130   gst_buffer_fill (buffer, 0, header, header_size);
131   gst_buffer_copy_into (buffer, payload_buffer, GST_BUFFER_COPY_METADATA, 0,
132       -1);
133
134   /* Create the payload buffer and add it to the current buffer. */
135   sub_buffer =
136       gst_buffer_copy_region (payload_buffer, GST_BUFFER_COPY_MEMORY,
137       payload_offset, payload_size);
138
139   buffer = gst_buffer_append (buffer, sub_buffer);
140   fail_if (buffer == NULL);
141
142   return buffer;
143 }
144
145 static GstBuffer *
146 create_rtp_buffer_fields (gconstpointer header, gint header_size,
147     GstBuffer * payload_buffer, gint payload_offset, gint payload_size,
148     guint16 seqnum, guint32 timestamp)
149 {
150   GstBuffer *buffer;
151   GstMemory *memory;
152   GstMapInfo info;
153   gboolean ret;
154   guint32 *tmp;
155
156   buffer =
157       create_rtp_packet_buffer (header, header_size, payload_buffer,
158       payload_offset, payload_size);
159   fail_if (buffer == NULL);
160
161   memory = gst_buffer_get_memory (buffer, 0);
162   ret = gst_memory_map (memory, &info, GST_MAP_READ);
163   fail_if (ret == FALSE);
164
165   info.data[2] = (seqnum >> 8) & 0xff;
166   info.data[3] = seqnum & 0xff;
167
168   tmp = (guint32 *) & (info.data[4]);
169   *tmp = g_htonl (timestamp);
170
171   gst_memory_unmap (memory, &info);
172   gst_memory_unref (memory);
173
174   return buffer;
175 }
176
177 static void
178 check_seqnum (GstBuffer * buffer, guint16 seqnum)
179 {
180   GstMemory *memory;
181   GstMapInfo info;
182   gboolean ret;
183   guint16 current_seqnum;
184
185   fail_if (buffer == NULL);
186
187   memory = gst_buffer_get_memory (buffer, 0);
188   ret = gst_memory_map (memory, &info, GST_MAP_READ);
189   fail_if (ret == FALSE);
190
191   current_seqnum = info.data[2] << 8 | info.data[3];
192   fail_unless (current_seqnum == seqnum);
193
194   gst_memory_unmap (memory, &info);
195   gst_memory_unref (memory);
196 }
197
198 static void
199 check_timestamp (GstBuffer * buffer, guint32 timestamp)
200 {
201   GstMemory *memory;
202   GstMapInfo info;
203   gboolean ret;
204   guint32 current_timestamp;
205
206   fail_if (buffer == NULL);
207
208   memory = gst_buffer_get_memory (buffer, 0);
209   ret = gst_memory_map (memory, &info, GST_MAP_READ);
210   fail_if (ret == FALSE);
211
212   current_timestamp = g_ntohl (*((guint32 *) & (info.data[4])));
213   fail_unless (current_timestamp == timestamp);
214
215   gst_memory_unmap (memory, &info);
216   gst_memory_unref (memory);
217 }
218
219 static void
220 check_header (GstBuffer * buffer, guint index)
221 {
222   GstMemory *memory;
223   GstMapInfo info;
224   gboolean ret;
225
226   fail_if (buffer == NULL);
227   fail_unless (index < 2);
228
229   memory = gst_buffer_get_memory (buffer, 0);
230   ret = gst_memory_map (memory, &info, GST_MAP_READ);
231   fail_if (ret == FALSE);
232
233   fail_unless (info.size == rtp_header_len[index]);
234
235   /* Can't do a memcmp() on the whole header, cause the SSRC (bytes 8-11) will
236    * most likely be changed in gstrtpbin.
237    */
238   fail_unless (info.data != NULL);
239   fail_unless_equals_uint64 (*(guint64 *) info.data,
240       *(guint64 *) rtp_header[index]);
241   fail_unless (*(guint16 *) (info.data + 12) ==
242       *(guint16 *) (rtp_header[index] + 12));
243
244   gst_memory_unmap (memory, &info);
245   gst_memory_unref (memory);
246 }
247
248 static void
249 check_payload (GstBuffer * buffer, guint index)
250 {
251   GstMemory *memory;
252   GstMapInfo info;
253   gboolean ret;
254
255   fail_if (buffer == NULL);
256   fail_unless (index < 2);
257
258   memory = gst_buffer_get_memory (buffer, 1);
259   ret = gst_memory_map (memory, &info, GST_MAP_READ);
260   fail_if (ret == FALSE);
261
262   fail_unless (info.size == payload_len[index]);
263   fail_if (info.data != (gpointer) (payload + payload_offset[index]));
264   fail_if (memcmp (info.data, payload + payload_offset[index],
265           payload_len[index]));
266
267   gst_memory_unmap (memory, &info);
268   gst_memory_unref (memory);
269 }
270
271 static void
272 check_packet (GstBufferList * list, guint list_index, guint packet_index)
273 {
274   GstBuffer *buffer;
275
276   fail_unless (list != NULL);
277
278   fail_unless ((buffer = gst_buffer_list_get (list, list_index)) != NULL);
279   fail_unless (gst_buffer_n_memory (buffer) == 2);
280
281   fail_unless (GST_BUFFER_TIMESTAMP (buffer) ==
282       GST_BUFFER_TIMESTAMP (original_buffer));
283
284   check_header (buffer, packet_index);
285   check_payload (buffer, packet_index);
286 }
287
288 /*
289  * Used to verify that the chain_list function is actually implemented by the
290  * element and called when executing the pipeline. This is needed because pads
291  * always have a default chain_list handler which handle buffers in a buffer
292  * list individually, and pushing a list to a pad can succeed even if no
293  * chain_list handler has been set.
294  */
295 static gboolean chain_list_func_called;
296 static guint chain_list_bytes_received;
297
298 /* Create two packets with different payloads. */
299 static GstBufferList *
300 create_buffer_list (void)
301 {
302   GstBufferList *list;
303   GstBuffer *orig_buffer;
304   GstBuffer *buffer;
305
306   orig_buffer = create_original_buffer ();
307   fail_if (orig_buffer == NULL);
308
309   list = gst_buffer_list_new ();
310   fail_if (list == NULL);
311
312   /*** First packet. **/
313   buffer =
314       create_rtp_packet_buffer (&rtp_header[0], rtp_header_len[0], orig_buffer,
315       payload_offset[0], payload_len[0]);
316   gst_buffer_list_add (list, buffer);
317
318   /***  Second packet. ***/
319   buffer =
320       create_rtp_packet_buffer (&rtp_header[1], rtp_header_len[1], orig_buffer,
321       payload_offset[1], payload_len[1]);
322   gst_buffer_list_add (list, buffer);
323
324   return list;
325 }
326
327 /* Check that the correct packets have been pushed out of the element. */
328 static GstFlowReturn
329 sink_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
330 {
331   GstCaps *current_caps;
332   GstCaps *caps;
333
334   chain_list_func_called = TRUE;
335
336   current_caps = gst_pad_get_current_caps (pad);
337   fail_unless (current_caps != NULL);
338
339   caps = gst_caps_from_string (TEST_CAPS);
340   fail_unless (caps != NULL);
341
342   fail_unless (gst_caps_is_equal (caps, current_caps));
343   gst_caps_unref (caps);
344   gst_caps_unref (current_caps);
345
346   fail_unless (GST_IS_BUFFER_LIST (list));
347   fail_unless (gst_buffer_list_length (list) == 2);
348
349   /* received bytes include lower level protocol overhead */
350   chain_list_bytes_received = gst_buffer_list_calculate_size (list) +
351       2 * UDP_IP_HEADER_OVERHEAD;
352
353   fail_unless (gst_buffer_list_get (list, 0));
354   check_packet (list, 0, 0);
355
356   fail_unless (gst_buffer_list_get (list, 1));
357   check_packet (list, 1, 1);
358
359   gst_buffer_list_unref (list);
360
361   return GST_FLOW_OK;
362 }
363
364
365 /* Non-consecutive seqnums makes probation fail. */
366 static GstBufferList *
367 create_buffer_list_fail_probation (void)
368 {
369   GstBufferList *list;
370   GstBuffer *orig_buffer;
371   GstBuffer *buffer;
372
373   guint16 seqnums[] = { 1, 3, 5 };
374   guint i;
375
376   orig_buffer = create_original_buffer ();
377   fail_if (orig_buffer == NULL);
378
379   list = gst_buffer_list_new ();
380   fail_if (list == NULL);
381
382   for (i = 0; i < sizeof (seqnums) / sizeof (seqnums[0]); i++) {
383     buffer =
384         create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
385         orig_buffer, payload_offset[0], payload_len[0], seqnums[i], 0);
386     gst_buffer_list_add (list, buffer);
387   }
388
389   return list;
390 }
391
392 /* When probation fails this function shouldn't be called. */
393 static GstFlowReturn
394 sink_chain_list_probation_failed (GstPad * pad, GstObject * parent,
395     GstBufferList * list)
396 {
397   chain_list_func_called = TRUE;
398   return GST_FLOW_OK;
399 }
400
401
402 /* After probation succeeds, a small gap in seqnums is allowed. */
403 static GstBufferList *
404 create_buffer_list_permissible_gap (void)
405 {
406   GstBufferList *list;
407   GstBuffer *orig_buffer;
408   GstBuffer *buffer;
409
410   /* probation succeeds, but then there is a permissible out of sequence */
411   guint16 seqnums[] = { 1, 2, 4, 5 };
412   guint i;
413
414   orig_buffer = create_original_buffer ();
415   fail_if (orig_buffer == NULL);
416
417   list = gst_buffer_list_new ();
418   fail_if (list == NULL);
419
420   for (i = 0; i < sizeof (seqnums) / sizeof (seqnums[0]); i++) {
421     buffer =
422         create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
423         orig_buffer, payload_offset[0], payload_len[0], seqnums[i], 0);
424     gst_buffer_list_add (list, buffer);
425   }
426
427   return list;
428 }
429
430 /* All buffers should have been pushed. */
431 static GstFlowReturn
432 sink_chain_list_permissible_gap (GstPad * pad, GstObject * parent,
433     GstBufferList * list)
434 {
435   GstBuffer *buffer;
436
437   chain_list_func_called = TRUE;
438
439   fail_unless (GST_IS_BUFFER_LIST (list));
440   fail_unless (gst_buffer_list_length (list) == 4);
441
442   /* Verify sequence numbers */
443   buffer = gst_buffer_list_get (list, 0);
444   check_seqnum (buffer, 1);
445
446   buffer = gst_buffer_list_get (list, 1);
447   check_seqnum (buffer, 2);
448
449   buffer = gst_buffer_list_get (list, 2);
450   check_seqnum (buffer, 4);
451
452   buffer = gst_buffer_list_get (list, 3);
453   check_seqnum (buffer, 5);
454
455   gst_buffer_list_unref (list);
456
457   return GST_FLOW_OK;
458 }
459
460
461 /* After probation succeeds, wrapping seqnum is allowed. */
462 static GstBufferList *
463 create_buffer_list_wrapping_seqnums (void)
464 {
465   GstBufferList *list;
466   GstBuffer *orig_buffer;
467   GstBuffer *buffer;
468
469   /* probation succeeds, but then seqnum wraps around */
470   guint16 seqnums[] = { 65533, 65534, 65535, 0 };
471   guint i;
472
473   orig_buffer = create_original_buffer ();
474   fail_if (orig_buffer == NULL);
475
476   list = gst_buffer_list_new ();
477   fail_if (list == NULL);
478
479   for (i = 0; i < sizeof (seqnums) / sizeof (seqnums[0]); i++) {
480     buffer =
481         create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
482         orig_buffer, payload_offset[0], payload_len[0], seqnums[i], 0);
483     gst_buffer_list_add (list, buffer);
484   }
485
486   return list;
487 }
488
489 /* All buffers should have been pushed. */
490 static GstFlowReturn
491 sink_chain_list_wrapping_seqnums (GstPad * pad, GstObject * parent,
492     GstBufferList * list)
493 {
494   GstBuffer *buffer;
495
496   chain_list_func_called = TRUE;
497
498   fail_unless (GST_IS_BUFFER_LIST (list));
499   fail_unless (gst_buffer_list_length (list) == 4);
500
501   /* Verify sequence numbers */
502   buffer = gst_buffer_list_get (list, 0);
503   check_seqnum (buffer, 65533);
504
505   buffer = gst_buffer_list_get (list, 1);
506   check_seqnum (buffer, 65534);
507
508   buffer = gst_buffer_list_get (list, 2);
509   check_seqnum (buffer, 65535);
510
511   buffer = gst_buffer_list_get (list, 3);
512   check_seqnum (buffer, 0);
513
514   gst_buffer_list_unref (list);
515
516   return GST_FLOW_OK;
517 }
518
519
520 /* Large jump, packet discarded. */
521 static GstBufferList *
522 create_buffer_list_large_jump_discarded (void)
523 {
524   GstBufferList *list;
525   GstBuffer *orig_buffer;
526   GstBuffer *buffer;
527
528   /*
529    * Probation succeeds, but then a large jump happens and the bogus packet
530    * gets discarded, receiving continues normally afterwards.
531    */
532   guint16 seqnums[] = { 1, 2, 3, 4, 50000, 5 };
533   guint i;
534
535   orig_buffer = create_original_buffer ();
536   fail_if (orig_buffer == NULL);
537
538   list = gst_buffer_list_new ();
539   fail_if (list == NULL);
540
541   for (i = 0; i < sizeof (seqnums) / sizeof (seqnums[0]); i++) {
542     /*
543      * Make the timestamps proportional to seqnums, to make it easier to predict
544      * the packet rate.
545      */
546     guint32 timestamp = seqnums[i] * 100;
547
548     buffer =
549         create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
550         orig_buffer, payload_offset[0], payload_len[0], seqnums[i], timestamp);
551     gst_buffer_list_add (list, buffer);
552   }
553
554   return list;
555 }
556
557 /* One buffer has been discarded. */
558 static GstFlowReturn
559 sink_chain_list_large_jump_discarded (GstPad * pad, GstObject * parent,
560     GstBufferList * list)
561 {
562   GstBuffer *buffer;
563
564   chain_list_func_called = TRUE;
565
566   fail_unless (GST_IS_BUFFER_LIST (list));
567   fail_unless (gst_buffer_list_length (list) == 5);
568
569   /* Verify sequence numbers */
570   buffer = gst_buffer_list_get (list, 0);
571   check_seqnum (buffer, 1);
572
573   buffer = gst_buffer_list_get (list, 1);
574   check_seqnum (buffer, 2);
575
576   buffer = gst_buffer_list_get (list, 2);
577   check_seqnum (buffer, 3);
578
579   buffer = gst_buffer_list_get (list, 3);
580   check_seqnum (buffer, 4);
581
582   buffer = gst_buffer_list_get (list, 4);
583   check_seqnum (buffer, 5);
584
585   gst_buffer_list_unref (list);
586
587   return GST_FLOW_OK;
588 }
589
590
591 /* Large jump, with recovery. */
592 static GstBufferList *
593 create_buffer_list_large_jump_recovery (void)
594 {
595   GstBufferList *list;
596   GstBuffer *orig_buffer;
597   GstBuffer *buffer;
598
599   /*
600    * Probation succeeds, but then a large jump happens.
601    * A consecutive next packet makes the session manager recover: it assumes
602    * that the other side restarted without telling.
603    */
604   guint16 seqnums[] = { 1, 2, 3, 4, 50000, 50001 };
605   guint i;
606
607   orig_buffer = create_original_buffer ();
608   fail_if (orig_buffer == NULL);
609
610   list = gst_buffer_list_new ();
611   fail_if (list == NULL);
612
613   for (i = 0; i < sizeof (seqnums) / sizeof (seqnums[0]); i++) {
614     /*
615      * Make the timestamps proportional to seqnums, to make it easier to predict
616      * the packet rate.
617      */
618     guint32 timestamp = seqnums[i] * 100;
619
620     buffer =
621         create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
622         orig_buffer, payload_offset[0], payload_len[0], seqnums[i], timestamp);
623     gst_buffer_list_add (list, buffer);
624   }
625
626   return list;
627 }
628
629 /* All buffers should have been pushed. */
630 static GstFlowReturn
631 sink_chain_list_large_jump_recovery (GstPad * pad, GstObject * parent,
632     GstBufferList * list)
633 {
634   GstBuffer *buffer;
635
636   chain_list_func_called = TRUE;
637
638   fail_unless (GST_IS_BUFFER_LIST (list));
639   fail_unless (gst_buffer_list_length (list) == 6);
640
641   /* Verify sequence numbers */
642   buffer = gst_buffer_list_get (list, 0);
643   check_seqnum (buffer, 1);
644
645   buffer = gst_buffer_list_get (list, 1);
646   check_seqnum (buffer, 2);
647
648   buffer = gst_buffer_list_get (list, 2);
649   check_seqnum (buffer, 3);
650
651   buffer = gst_buffer_list_get (list, 3);
652   check_seqnum (buffer, 4);
653
654   buffer = gst_buffer_list_get (list, 4);
655   check_seqnum (buffer, 50000);
656
657   buffer = gst_buffer_list_get (list, 5);
658   check_seqnum (buffer, 50001);
659
660   gst_buffer_list_unref (list);
661
662   return GST_FLOW_OK;
663 }
664
665
666 /* After probation succeeds, reordered and duplicated packets are allowed. */
667 static GstBufferList *
668 create_buffer_list_reordered_packets (void)
669 {
670   GstBufferList *list;
671   GstBuffer *orig_buffer;
672   GstBuffer *buffer;
673
674   /* probation succeeds, but then there are reordered or duplicated packets */
675   guint16 seqnums[] = { 4, 5, 2, 2 };
676   guint i;
677
678   orig_buffer = create_original_buffer ();
679   fail_if (orig_buffer == NULL);
680
681   list = gst_buffer_list_new ();
682   fail_if (list == NULL);
683
684   for (i = 0; i < sizeof (seqnums) / sizeof (seqnums[0]); i++) {
685     buffer =
686         create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
687         orig_buffer, payload_offset[0], payload_len[0], seqnums[i], 0);
688     gst_buffer_list_add (list, buffer);
689   }
690
691   return list;
692 }
693
694 /* All buffers should have been pushed, they will be filtered by jitterbuffer */
695 static GstFlowReturn
696 sink_chain_list_reordered_packets (GstPad * pad, GstObject * parent,
697     GstBufferList * list)
698 {
699   GstBuffer *buffer;
700
701   chain_list_func_called = TRUE;
702
703   fail_unless (GST_IS_BUFFER_LIST (list));
704   fail_unless (gst_buffer_list_length (list) == 4);
705
706   /* Verify sequence numbers */
707   buffer = gst_buffer_list_get (list, 0);
708   check_seqnum (buffer, 4);
709
710   buffer = gst_buffer_list_get (list, 1);
711   check_seqnum (buffer, 5);
712
713   buffer = gst_buffer_list_get (list, 2);
714   check_seqnum (buffer, 2);
715
716   buffer = gst_buffer_list_get (list, 3);
717   check_seqnum (buffer, 2);
718
719   gst_buffer_list_unref (list);
720
721   return GST_FLOW_OK;
722 }
723
724
725 /* Frames with different timestamps in the same buffer list. */
726 static GstBufferList *
727 create_buffer_list_different_frames (void)
728 {
729   GstBufferList *list;
730   GstBuffer *orig_buffer;
731   GstBuffer *buffer;
732
733   guint32 timestamps[] = { 0, 0, 1000, 1000 };
734   guint i;
735
736   orig_buffer = create_original_buffer ();
737   fail_if (orig_buffer == NULL);
738
739   list = gst_buffer_list_new ();
740   fail_if (list == NULL);
741
742   for (i = 0; i < sizeof (timestamps) / sizeof (timestamps[0]); i++) {
743     buffer =
744         create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
745         orig_buffer, payload_offset[0], payload_len[0], i, timestamps[i]);
746     gst_buffer_list_add (list, buffer);
747   }
748
749   return list;
750 }
751
752 /* All buffers should have been pushed, regardless of the timestamp. */
753 static GstFlowReturn
754 sink_chain_list_different_frames (GstPad * pad, GstObject * parent,
755     GstBufferList * list)
756 {
757   GstBuffer *buffer;
758
759   chain_list_func_called = TRUE;
760
761   fail_unless (GST_IS_BUFFER_LIST (list));
762   fail_unless (gst_buffer_list_length (list) == 4);
763
764   /* Verify seqnums and timestamps. */
765   buffer = gst_buffer_list_get (list, 0);
766   check_seqnum (buffer, 0);
767   check_timestamp (buffer, 0);
768
769   buffer = gst_buffer_list_get (list, 1);
770   check_seqnum (buffer, 1);
771   check_timestamp (buffer, 0);
772
773   buffer = gst_buffer_list_get (list, 2);
774   check_seqnum (buffer, 2);
775   check_timestamp (buffer, 1000);
776
777   buffer = gst_buffer_list_get (list, 3);
778   check_seqnum (buffer, 3);
779   check_timestamp (buffer, 1000);
780
781   gst_buffer_list_unref (list);
782
783   return GST_FLOW_OK;
784 }
785
786
787 /*
788  * RTP and RTCP can be multiplexed in the same channel and end up in the same
789  * buffer list.
790  */
791 static GstBufferList *
792 create_buffer_list_muxed_rtcp (void)
793 {
794   GstBufferList *list;
795   GstBuffer *orig_buffer;
796   GstBuffer *buffer;
797   GstRTCPBuffer rtcpbuf = GST_RTCP_BUFFER_INIT;
798   GstRTCPPacket rtcppacket;
799
800   guint seqnum = 0;
801
802   orig_buffer = create_original_buffer ();
803   fail_if (orig_buffer == NULL);
804
805   list = gst_buffer_list_new ();
806   fail_if (list == NULL);
807
808   buffer =
809       create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
810       orig_buffer, payload_offset[0], payload_len[0], seqnum, 0);
811   gst_buffer_list_add (list, buffer);
812
813   seqnum++;
814
815   buffer =
816       create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
817       orig_buffer, payload_offset[0], payload_len[0], seqnum, 0);
818   gst_buffer_list_add (list, buffer);
819
820   seqnum++;
821
822   buffer = gst_rtcp_buffer_new (1500);
823   gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcpbuf);
824   gst_rtcp_buffer_add_packet (&rtcpbuf, GST_RTCP_TYPE_SR, &rtcppacket);
825   gst_rtcp_packet_sr_set_sender_info (&rtcppacket, 0, 0, 0, 0, 0);
826   gst_rtcp_buffer_add_packet (&rtcpbuf, GST_RTCP_TYPE_RR, &rtcppacket);
827   gst_rtcp_packet_rr_set_ssrc (&rtcppacket, 1);
828   gst_rtcp_packet_add_rb (&rtcppacket, 0, 0, 0, 0, 0, 0, 0);
829   gst_rtcp_buffer_add_packet (&rtcpbuf, GST_RTCP_TYPE_SDES, &rtcppacket);
830   gst_rtcp_packet_sdes_add_item (&rtcppacket, 1);
831   gst_rtcp_packet_sdes_add_entry (&rtcppacket, GST_RTCP_SDES_CNAME, 3,
832       (guint8 *) "a@a");
833   gst_rtcp_packet_sdes_add_entry (&rtcppacket, GST_RTCP_SDES_NAME, 2,
834       (guint8 *) "aa");
835   gst_rtcp_packet_sdes_add_entry (&rtcppacket, GST_RTCP_SDES_END, 0,
836       (guint8 *) "");
837   gst_rtcp_buffer_unmap (&rtcpbuf);
838
839   gst_buffer_list_add (list, buffer);
840
841   buffer =
842       create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
843       orig_buffer, payload_offset[0], payload_len[0], seqnum, 0);
844   gst_buffer_list_add (list, buffer);
845
846   return list;
847 }
848
849 /*
850  * All RTP buffers should have been pushed to recv_rtp_src, the RTCP packet
851  * should have been pushed to sync_src.
852  */
853 static GstFlowReturn
854 sink_chain_list_muxed_rtcp (GstPad * pad, GstObject * parent,
855     GstBufferList * list)
856 {
857   GstBuffer *buffer;
858
859   chain_list_func_called = TRUE;
860
861   fail_unless (GST_IS_BUFFER_LIST (list));
862   fail_unless (gst_buffer_list_length (list) == 3);
863
864   /* Verify seqnums of RTP packets. */
865   buffer = gst_buffer_list_get (list, 0);
866   check_seqnum (buffer, 0);
867
868   buffer = gst_buffer_list_get (list, 1);
869   check_seqnum (buffer, 1);
870
871   buffer = gst_buffer_list_get (list, 2);
872   check_seqnum (buffer, 2);
873
874   gst_buffer_list_unref (list);
875
876   return GST_FLOW_OK;
877 }
878
879 /* count multiplexed rtcp packets */
880 static guint rtcp_packets;
881
882 static GstFlowReturn
883 sink_chain_muxed_rtcp (GstPad * pad, GstObject * parent, GstBuffer * buffer)
884 {
885   rtcp_packets++;
886   gst_buffer_unref (buffer);
887   return GST_FLOW_OK;
888 }
889
890
891 /* Invalid data can be received muxed with valid RTP packets */
892 static GstBufferList *
893 create_buffer_list_muxed_invalid (void)
894 {
895   GstBufferList *list;
896   GstBuffer *orig_buffer;
897   GstBuffer *buffer;
898
899   guint seqnum = 0;
900
901   orig_buffer = create_original_buffer ();
902   fail_if (orig_buffer == NULL);
903
904   list = gst_buffer_list_new ();
905   fail_if (list == NULL);
906
907   buffer =
908       create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
909       orig_buffer, payload_offset[0], payload_len[0], seqnum, 0);
910   gst_buffer_list_add (list, buffer);
911
912   seqnum++;
913
914   buffer =
915       create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
916       orig_buffer, payload_offset[0], payload_len[0], seqnum, 0);
917   gst_buffer_list_add (list, buffer);
918
919   seqnum++;
920
921   /* add an invalid RTP packet to the list */
922   buffer = gst_buffer_new_allocate (NULL, 10, NULL);
923   /* initialize the memory to make valgrind happy */
924   gst_buffer_memset (buffer, 0, 0, 10);
925
926   gst_buffer_list_add (list, buffer);
927
928   buffer =
929       create_rtp_buffer_fields (&rtp_header[0], rtp_header_len[0],
930       orig_buffer, payload_offset[0], payload_len[0], seqnum, 0);
931   gst_buffer_list_add (list, buffer);
932
933   return list;
934 }
935
936 /*
937  * Only valid RTP buffers should have been pushed to recv_rtp_src.
938  */
939 static GstFlowReturn
940 sink_chain_list_muxed_invalid (GstPad * pad, GstObject * parent,
941     GstBufferList * list)
942 {
943   GstBuffer *buffer;
944
945   chain_list_func_called = TRUE;
946
947   fail_unless (GST_IS_BUFFER_LIST (list));
948   fail_unless (gst_buffer_list_length (list) == 3);
949
950   /* Verify seqnums of valid RTP packets. */
951   buffer = gst_buffer_list_get (list, 0);
952   check_seqnum (buffer, 0);
953
954   buffer = gst_buffer_list_get (list, 1);
955   check_seqnum (buffer, 1);
956
957   buffer = gst_buffer_list_get (list, 2);
958   check_seqnum (buffer, 2);
959
960   gst_buffer_list_unref (list);
961
962   return GST_FLOW_OK;
963 }
964
965
966 /* Get the stats of the **first** source of the given type (get_sender) */
967 static void
968 get_source_stats (GstElement * rtpsession,
969     gboolean get_sender, GstStructure ** source_stats)
970 {
971   GstStructure *stats;
972   GValueArray *stats_arr;
973   guint i;
974
975   g_object_get (rtpsession, "stats", &stats, NULL);
976   stats_arr =
977       g_value_get_boxed (gst_structure_get_value (stats, "source-stats"));
978   g_assert (stats_arr != NULL);
979   fail_unless (stats_arr->n_values >= 1);
980
981   *source_stats = NULL;
982   for (i = 0; i < stats_arr->n_values; i++) {
983     GstStructure *tmp_source_stats;
984     gboolean is_sender;
985
986     tmp_source_stats = g_value_dup_boxed (&stats_arr->values[i]);
987     gst_structure_get (tmp_source_stats, "is-sender", G_TYPE_BOOLEAN,
988         &is_sender, NULL);
989
990     /* Return the stats of the **first** source of the given type. */
991     if (is_sender == get_sender) {
992       *source_stats = tmp_source_stats;
993       break;
994     }
995     gst_structure_free (tmp_source_stats);
996   }
997
998   gst_structure_free (stats);
999 }
1000
1001 /* Get the source stats given a session and a source type (get_sender) */
1002 static void
1003 get_session_source_stats (GstElement * rtpbin, guint session,
1004     gboolean get_sender, GstStructure ** source_stats)
1005 {
1006   GstElement *rtpsession;
1007
1008   g_signal_emit_by_name (rtpbin, "get-session", session, &rtpsession);
1009   fail_if (rtpsession == NULL);
1010
1011   get_source_stats (rtpsession, get_sender, source_stats);
1012
1013   gst_object_unref (rtpsession);
1014 }
1015
1016 GST_START_TEST (test_bufferlist)
1017 {
1018   GstElement *rtpbin;
1019   GstPad *srcpad;
1020   GstPad *sinkpad;
1021   GstCaps *caps;
1022   GstBufferList *list;
1023   GstStructure *stats;
1024   guint64 packets_sent;
1025   guint64 packets_received;
1026
1027   list = create_buffer_list ();
1028   fail_unless (list != NULL);
1029
1030   rtpbin = gst_check_setup_element ("rtpbin");
1031
1032   srcpad =
1033       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "send_rtp_sink_0");
1034   fail_if (srcpad == NULL);
1035   sinkpad =
1036       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate,
1037       "send_rtp_src_0");
1038   fail_if (sinkpad == NULL);
1039
1040   gst_pad_set_chain_list_function (sinkpad,
1041       GST_DEBUG_FUNCPTR (sink_chain_list));
1042
1043   gst_pad_set_active (srcpad, TRUE);
1044   gst_pad_set_active (sinkpad, TRUE);
1045
1046   caps = gst_caps_from_string (TEST_CAPS);
1047   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1048   gst_caps_unref (caps);
1049
1050   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1051
1052   chain_list_func_called = FALSE;
1053   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1054   fail_if (chain_list_func_called == FALSE);
1055
1056   /* make sure that stats about the number of sent packets are OK too */
1057   get_session_source_stats (rtpbin, 0, TRUE, &stats);
1058   fail_if (stats == NULL);
1059
1060   gst_structure_get (stats,
1061       "packets-sent", G_TYPE_UINT64, &packets_sent,
1062       "packets-received", G_TYPE_UINT64, &packets_received, NULL);
1063   fail_unless (packets_sent == 2);
1064   fail_unless (packets_received == 2);
1065   gst_structure_free (stats);
1066
1067   gst_pad_set_active (sinkpad, FALSE);
1068   gst_pad_set_active (srcpad, FALSE);
1069
1070   gst_check_teardown_pad_by_name (rtpbin, "send_rtp_src_0");
1071   gst_check_teardown_pad_by_name (rtpbin, "send_rtp_sink_0");
1072   gst_check_teardown_element (rtpbin);
1073 }
1074
1075 GST_END_TEST;
1076
1077
1078 GST_START_TEST (test_bufferlist_recv)
1079 {
1080   GstElement *rtpbin;
1081   GstPad *srcpad;
1082   GstPad *sinkpad;
1083   GstCaps *caps;
1084   GstBufferList *list;
1085   GstStructure *stats;
1086   guint64 bytes_received;
1087   guint64 packets_received;
1088
1089   list = create_buffer_list ();
1090   fail_unless (list != NULL);
1091
1092   rtpbin = gst_check_setup_element ("rtpsession");
1093
1094   srcpad =
1095       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1096   fail_if (srcpad == NULL);
1097
1098   sinkpad =
1099       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1100   fail_if (sinkpad == NULL);
1101
1102   gst_pad_set_chain_list_function (sinkpad,
1103       GST_DEBUG_FUNCPTR (sink_chain_list));
1104
1105   gst_pad_set_active (srcpad, TRUE);
1106   gst_pad_set_active (sinkpad, TRUE);
1107
1108   caps = gst_caps_from_string (TEST_CAPS);
1109   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1110   gst_caps_unref (caps);
1111
1112   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1113
1114   chain_list_func_called = FALSE;
1115   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1116   fail_if (chain_list_func_called == FALSE);
1117
1118   /* make sure that stats about the number of received packets are OK too */
1119   /* The source becomes a sender after probation succeeds, pass TRUE here. */
1120   get_source_stats (rtpbin, TRUE, &stats);
1121   fail_if (stats == NULL);
1122
1123   gst_structure_get (stats,
1124       "bytes-received", G_TYPE_UINT64, &bytes_received,
1125       "packets-received", G_TYPE_UINT64, &packets_received, NULL);
1126   fail_unless (packets_received == 2);
1127   fail_unless (bytes_received == chain_list_bytes_received);
1128   gst_structure_free (stats);
1129
1130
1131   gst_pad_set_active (sinkpad, FALSE);
1132   gst_pad_set_active (srcpad, FALSE);
1133
1134   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1135   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1136   gst_check_teardown_element (rtpbin);
1137 }
1138
1139 GST_END_TEST;
1140
1141
1142 GST_START_TEST (test_bufferlist_recv_probation_failed)
1143 {
1144   GstElement *rtpbin;
1145   GstPad *srcpad;
1146   GstPad *sinkpad;
1147   GstCaps *caps;
1148   GstBufferList *list;
1149
1150   list = create_buffer_list_fail_probation ();
1151   fail_unless (list != NULL);
1152
1153   rtpbin = gst_check_setup_element ("rtpsession");
1154
1155   srcpad =
1156       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1157   fail_if (srcpad == NULL);
1158
1159   sinkpad =
1160       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1161   fail_if (sinkpad == NULL);
1162
1163   gst_pad_set_chain_list_function (sinkpad,
1164       GST_DEBUG_FUNCPTR (sink_chain_list_probation_failed));
1165
1166   gst_pad_set_active (srcpad, TRUE);
1167   gst_pad_set_active (sinkpad, TRUE);
1168
1169   caps = gst_caps_from_string (TEST_CAPS);
1170   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1171   gst_caps_unref (caps);
1172
1173   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1174
1175   chain_list_func_called = FALSE;
1176   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1177   /* when probation fails the list should not be pushed at all, and the
1178    * chain_list functions should not be called, fail if it has been. */
1179   fail_if (chain_list_func_called == TRUE);
1180
1181   gst_pad_set_active (sinkpad, FALSE);
1182   gst_pad_set_active (srcpad, FALSE);
1183
1184   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1185   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1186   gst_check_teardown_element (rtpbin);
1187 }
1188
1189 GST_END_TEST;
1190
1191
1192 GST_START_TEST (test_bufferlist_recv_permissible_gap)
1193 {
1194   GstElement *rtpbin;
1195   GstPad *srcpad;
1196   GstPad *sinkpad;
1197   GstCaps *caps;
1198   GstBufferList *list;
1199
1200   list = create_buffer_list_permissible_gap ();
1201   fail_unless (list != NULL);
1202
1203   rtpbin = gst_check_setup_element ("rtpsession");
1204
1205   srcpad =
1206       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1207   fail_if (srcpad == NULL);
1208
1209   sinkpad =
1210       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1211   fail_if (sinkpad == NULL);
1212
1213   gst_pad_set_chain_list_function (sinkpad,
1214       GST_DEBUG_FUNCPTR (sink_chain_list_permissible_gap));
1215
1216   gst_pad_set_active (srcpad, TRUE);
1217   gst_pad_set_active (sinkpad, TRUE);
1218
1219   caps = gst_caps_from_string (TEST_CAPS);
1220   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1221   gst_caps_unref (caps);
1222
1223   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1224
1225   chain_list_func_called = FALSE;
1226   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1227   fail_if (chain_list_func_called == FALSE);
1228
1229   gst_pad_set_active (sinkpad, FALSE);
1230   gst_pad_set_active (srcpad, FALSE);
1231
1232   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1233   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1234   gst_check_teardown_element (rtpbin);
1235 }
1236
1237 GST_END_TEST;
1238
1239
1240 GST_START_TEST (test_bufferlist_recv_wrapping_seqnums)
1241 {
1242   GstElement *rtpbin;
1243   GstPad *srcpad;
1244   GstPad *sinkpad;
1245   GstCaps *caps;
1246   GstBufferList *list;
1247
1248   list = create_buffer_list_wrapping_seqnums ();
1249   fail_unless (list != NULL);
1250
1251   rtpbin = gst_check_setup_element ("rtpsession");
1252
1253   srcpad =
1254       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1255   fail_if (srcpad == NULL);
1256
1257   sinkpad =
1258       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1259   fail_if (sinkpad == NULL);
1260
1261   gst_pad_set_chain_list_function (sinkpad,
1262       GST_DEBUG_FUNCPTR (sink_chain_list_wrapping_seqnums));
1263
1264   gst_pad_set_active (srcpad, TRUE);
1265   gst_pad_set_active (sinkpad, TRUE);
1266
1267   caps = gst_caps_from_string (TEST_CAPS);
1268   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1269   gst_caps_unref (caps);
1270
1271   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1272
1273   chain_list_func_called = FALSE;
1274   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1275   fail_if (chain_list_func_called == FALSE);
1276
1277   gst_pad_set_active (sinkpad, FALSE);
1278   gst_pad_set_active (srcpad, FALSE);
1279
1280   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1281   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1282   gst_check_teardown_element (rtpbin);
1283 }
1284
1285 GST_END_TEST;
1286
1287
1288 GST_START_TEST (test_bufferlist_recv_large_jump_discarded)
1289 {
1290   GstElement *rtpbin;
1291   GstPad *srcpad;
1292   GstPad *sinkpad;
1293   GstCaps *caps;
1294   GstBufferList *list;
1295
1296   list = create_buffer_list_large_jump_discarded ();
1297   fail_unless (list != NULL);
1298
1299   rtpbin = gst_check_setup_element ("rtpsession");
1300
1301   srcpad =
1302       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1303   fail_if (srcpad == NULL);
1304
1305   sinkpad =
1306       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1307   fail_if (sinkpad == NULL);
1308
1309   gst_pad_set_chain_list_function (sinkpad,
1310       GST_DEBUG_FUNCPTR (sink_chain_list_large_jump_discarded));
1311
1312   gst_pad_set_active (srcpad, TRUE);
1313   gst_pad_set_active (sinkpad, TRUE);
1314
1315   caps = gst_caps_from_string (TEST_CAPS);
1316   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1317   gst_caps_unref (caps);
1318
1319   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1320
1321   chain_list_func_called = FALSE;
1322   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1323   fail_if (chain_list_func_called == FALSE);
1324
1325   gst_pad_set_active (sinkpad, FALSE);
1326   gst_pad_set_active (srcpad, FALSE);
1327
1328   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1329   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1330   gst_check_teardown_element (rtpbin);
1331 }
1332
1333 GST_END_TEST;
1334
1335
1336 GST_START_TEST (test_bufferlist_recv_large_jump_recovery)
1337 {
1338   GstElement *rtpbin;
1339   GstPad *srcpad;
1340   GstPad *sinkpad;
1341   GstCaps *caps;
1342   GstBufferList *list;
1343
1344   list = create_buffer_list_large_jump_recovery ();
1345   fail_unless (list != NULL);
1346
1347   rtpbin = gst_check_setup_element ("rtpsession");
1348
1349   srcpad =
1350       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1351   fail_if (srcpad == NULL);
1352
1353   sinkpad =
1354       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1355   fail_if (sinkpad == NULL);
1356
1357   gst_pad_set_chain_list_function (sinkpad,
1358       GST_DEBUG_FUNCPTR (sink_chain_list_large_jump_recovery));
1359
1360   gst_pad_set_active (srcpad, TRUE);
1361   gst_pad_set_active (sinkpad, TRUE);
1362
1363   caps = gst_caps_from_string (TEST_CAPS);
1364   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1365   gst_caps_unref (caps);
1366
1367   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1368
1369   chain_list_func_called = FALSE;
1370   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1371   fail_if (chain_list_func_called == FALSE);
1372
1373   gst_pad_set_active (sinkpad, FALSE);
1374   gst_pad_set_active (srcpad, FALSE);
1375
1376   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1377   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1378   gst_check_teardown_element (rtpbin);
1379 }
1380
1381 GST_END_TEST;
1382
1383
1384 GST_START_TEST (test_bufferlist_recv_reordered_packets)
1385 {
1386   GstElement *rtpbin;
1387   GstPad *srcpad;
1388   GstPad *sinkpad;
1389   GstCaps *caps;
1390   GstBufferList *list;
1391
1392   list = create_buffer_list_reordered_packets ();
1393   fail_unless (list != NULL);
1394
1395   rtpbin = gst_check_setup_element ("rtpsession");
1396
1397   srcpad =
1398       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1399   fail_if (srcpad == NULL);
1400
1401   sinkpad =
1402       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1403   fail_if (sinkpad == NULL);
1404
1405   gst_pad_set_chain_list_function (sinkpad,
1406       GST_DEBUG_FUNCPTR (sink_chain_list_reordered_packets));
1407
1408   gst_pad_set_active (srcpad, TRUE);
1409   gst_pad_set_active (sinkpad, TRUE);
1410
1411   caps = gst_caps_from_string (TEST_CAPS);
1412   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1413   gst_caps_unref (caps);
1414
1415   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1416
1417   chain_list_func_called = FALSE;
1418   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1419   fail_if (chain_list_func_called == FALSE);
1420
1421   gst_pad_set_active (sinkpad, FALSE);
1422   gst_pad_set_active (srcpad, FALSE);
1423
1424   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1425   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1426   gst_check_teardown_element (rtpbin);
1427 }
1428
1429 GST_END_TEST;
1430
1431 GST_START_TEST (test_bufferlist_recv_different_frames)
1432 {
1433   GstElement *rtpbin;
1434   GstPad *srcpad;
1435   GstPad *sinkpad;
1436   GstCaps *caps;
1437   GstBufferList *list;
1438
1439   list = create_buffer_list_different_frames ();
1440   fail_unless (list != NULL);
1441
1442   rtpbin = gst_check_setup_element ("rtpsession");
1443
1444   srcpad =
1445       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1446   fail_if (srcpad == NULL);
1447
1448   sinkpad =
1449       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1450   fail_if (sinkpad == NULL);
1451
1452   gst_pad_set_chain_list_function (sinkpad,
1453       GST_DEBUG_FUNCPTR (sink_chain_list_different_frames));
1454
1455   gst_pad_set_active (srcpad, TRUE);
1456   gst_pad_set_active (sinkpad, TRUE);
1457
1458   caps = gst_caps_from_string (TEST_CAPS);
1459   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1460   gst_caps_unref (caps);
1461
1462   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1463
1464   chain_list_func_called = FALSE;
1465   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1466   fail_if (chain_list_func_called == FALSE);
1467
1468   gst_pad_set_active (sinkpad, FALSE);
1469   gst_pad_set_active (srcpad, FALSE);
1470
1471   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1472   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1473   gst_check_teardown_element (rtpbin);
1474 }
1475
1476 GST_END_TEST;
1477
1478
1479 GST_START_TEST (test_bufferlist_recv_muxed_rtcp)
1480 {
1481   GstElement *rtpbin;
1482   GstPad *srcpad;
1483   GstPad *sinkpad;
1484   GstPad *srcpad_rtcp;
1485   GstPad *sinkpad_rtcp;
1486   GstCaps *caps;
1487   GstBufferList *list;
1488
1489   list = create_buffer_list_muxed_rtcp ();
1490   fail_unless (list != NULL);
1491
1492   rtpbin = gst_check_setup_element ("rtpsession");
1493
1494   srcpad =
1495       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1496   fail_if (srcpad == NULL);
1497
1498   sinkpad =
1499       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1500   fail_if (sinkpad == NULL);
1501
1502   gst_pad_set_chain_list_function (sinkpad,
1503       GST_DEBUG_FUNCPTR (sink_chain_list_muxed_rtcp));
1504
1505   gst_pad_set_active (srcpad, TRUE);
1506   gst_pad_set_active (sinkpad, TRUE);
1507
1508   caps = gst_caps_from_string (TEST_CAPS);
1509   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1510   gst_caps_unref (caps);
1511
1512   /*
1513    * Create supplementary pads after gst_check_setup_events() to avoid
1514    * a failure in gst_pad_create_stream_id().
1515    */
1516   srcpad_rtcp =
1517       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate_rtcp,
1518       "recv_rtcp_sink");
1519   fail_if (srcpad_rtcp == NULL);
1520
1521   sinkpad_rtcp =
1522       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate_rtcp, "sync_src");
1523   fail_if (sinkpad_rtcp == NULL);
1524
1525   gst_pad_set_chain_function (sinkpad_rtcp,
1526       GST_DEBUG_FUNCPTR (sink_chain_muxed_rtcp));
1527
1528   gst_pad_set_active (srcpad_rtcp, TRUE);
1529   gst_pad_set_active (sinkpad_rtcp, TRUE);
1530
1531   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1532
1533   chain_list_func_called = FALSE;
1534   rtcp_packets = 0;
1535   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1536   fail_if (chain_list_func_called == FALSE);
1537   fail_unless (rtcp_packets == 1);
1538
1539   gst_pad_set_active (sinkpad_rtcp, FALSE);
1540   gst_pad_set_active (srcpad_rtcp, FALSE);
1541   gst_pad_set_active (sinkpad, FALSE);
1542   gst_pad_set_active (srcpad, FALSE);
1543
1544   gst_check_teardown_pad_by_name (rtpbin, "sync_src");
1545   gst_check_teardown_pad_by_name (rtpbin, "recv_rtcp_sink");
1546   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1547   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1548   gst_check_teardown_element (rtpbin);
1549 }
1550
1551 GST_END_TEST;
1552
1553
1554 GST_START_TEST (test_bufferlist_recv_muxed_invalid)
1555 {
1556   GstElement *rtpbin;
1557   GstPad *srcpad;
1558   GstPad *sinkpad;
1559   GstCaps *caps;
1560   GstBufferList *list;
1561
1562   list = create_buffer_list_muxed_invalid ();
1563   fail_unless (list != NULL);
1564
1565   rtpbin = gst_check_setup_element ("rtpsession");
1566
1567   srcpad =
1568       gst_check_setup_src_pad_by_name (rtpbin, &srctemplate, "recv_rtp_sink");
1569   fail_if (srcpad == NULL);
1570
1571   sinkpad =
1572       gst_check_setup_sink_pad_by_name (rtpbin, &sinktemplate, "recv_rtp_src");
1573   fail_if (sinkpad == NULL);
1574
1575   gst_pad_set_chain_list_function (sinkpad,
1576       GST_DEBUG_FUNCPTR (sink_chain_list_muxed_invalid));
1577
1578   gst_pad_set_active (srcpad, TRUE);
1579   gst_pad_set_active (sinkpad, TRUE);
1580
1581   caps = gst_caps_from_string (TEST_CAPS);
1582   gst_check_setup_events (srcpad, rtpbin, caps, GST_FORMAT_TIME);
1583   gst_caps_unref (caps);
1584
1585   gst_element_set_state (rtpbin, GST_STATE_PLAYING);
1586
1587   chain_list_func_called = FALSE;
1588   fail_unless (gst_pad_push_list (srcpad, list) == GST_FLOW_OK);
1589   fail_if (chain_list_func_called == FALSE);
1590
1591   gst_pad_set_active (sinkpad, FALSE);
1592   gst_pad_set_active (srcpad, FALSE);
1593
1594   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_src");
1595   gst_check_teardown_pad_by_name (rtpbin, "recv_rtp_sink");
1596   gst_check_teardown_element (rtpbin);
1597 }
1598
1599 GST_END_TEST;
1600
1601
1602 static Suite *
1603 bufferlist_suite (void)
1604 {
1605   Suite *s = suite_create ("BufferList");
1606
1607   TCase *tc_chain = tcase_create ("general");
1608
1609   /* time out after 30s. */
1610   tcase_set_timeout (tc_chain, 10);
1611
1612   suite_add_tcase (s, tc_chain);
1613   tcase_add_test (tc_chain, test_bufferlist);
1614   tcase_add_test (tc_chain, test_bufferlist_recv);
1615   tcase_add_test (tc_chain, test_bufferlist_recv_probation_failed);
1616   tcase_add_test (tc_chain, test_bufferlist_recv_permissible_gap);
1617   tcase_add_test (tc_chain, test_bufferlist_recv_wrapping_seqnums);
1618   tcase_add_test (tc_chain, test_bufferlist_recv_large_jump_discarded);
1619   tcase_add_test (tc_chain, test_bufferlist_recv_large_jump_recovery);
1620   tcase_add_test (tc_chain, test_bufferlist_recv_reordered_packets);
1621   tcase_add_test (tc_chain, test_bufferlist_recv_different_frames);
1622   tcase_add_test (tc_chain, test_bufferlist_recv_muxed_rtcp);
1623   tcase_add_test (tc_chain, test_bufferlist_recv_muxed_invalid);
1624
1625   return s;
1626 }
1627
1628 GST_CHECK_MAIN (bufferlist);