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