rtpbasedepayload: handle caps change partway through buffer list
[platform/upstream/gstreamer.git] / tests / check / libs / rtpbasedepayload.c
1 /* GStreamer RTP base depayloader unit tests
2  * Copyright (C) 2014 Sebastian Rasmussen <sebras@hotmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General
15  * Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/gst.h>
25 #include <gst/check/gstcheck.h>
26 #include <gst/check/gstharness.h>
27 #include <gst/rtp/rtp.h>
28
29 #include "rtpdummyhdrextimpl.c"
30
31 #define DEFAULT_CLOCK_RATE (42)
32
33 /* GstRtpDummyDepay */
34
35 #define GST_TYPE_RTP_DUMMY_DEPAY \
36   (gst_rtp_dummy_depay_get_type())
37 #define GST_RTP_DUMMY_DEPAY(obj) \
38   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepay))
39 #define GST_RTP_DUMMY_DEPAY_CLASS(klass) \
40   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepayClass))
41 #define GST_IS_RTP_DUMMY_DEPAY(obj) \
42   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DUMMY_DEPAY))
43 #define GST_IS_RTP_DUMMY_DEPAY_CLASS(klass) \
44   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DUMMY_DEPAY))
45
46 typedef enum
47 {
48   GST_RTP_DUMMY_RETURN_TO_PUSH,
49   GST_RTP_DUMMY_USE_PUSH_FUNC,
50   GST_RTP_DUMMY_USE_PUSH_LIST_FUNC,
51 } GstRtpDummyPushMethod;
52
53 typedef struct _GstRtpDummyDepay GstRtpDummyDepay;
54 typedef struct _GstRtpDummyDepayClass GstRtpDummyDepayClass;
55
56 struct _GstRtpDummyDepay
57 {
58   GstRTPBaseDepayload depayload;
59   guint64 rtptime;
60
61   GstRtpDummyPushMethod push_method;
62   guint num_buffers_in_blist;
63 };
64
65 struct _GstRtpDummyDepayClass
66 {
67   GstRTPBaseDepayloadClass parent_class;
68 };
69
70 GType gst_rtp_dummy_depay_get_type (void);
71
72 G_DEFINE_TYPE (GstRtpDummyDepay, gst_rtp_dummy_depay,
73     GST_TYPE_RTP_BASE_DEPAYLOAD);
74
75 static GstBuffer *gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload,
76     GstBuffer * buf);
77 static gboolean gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter,
78     GstCaps * caps);
79
80 static GstStaticPadTemplate gst_rtp_dummy_depay_sink_template =
81 GST_STATIC_PAD_TEMPLATE ("sink",
82     GST_PAD_SINK,
83     GST_PAD_ALWAYS,
84     GST_STATIC_CAPS_ANY);
85
86 static GstStaticPadTemplate gst_rtp_dummy_depay_src_template =
87 GST_STATIC_PAD_TEMPLATE ("src",
88     GST_PAD_SRC,
89     GST_PAD_ALWAYS,
90     GST_STATIC_CAPS_ANY);
91
92 static void
93 gst_rtp_dummy_depay_class_init (GstRtpDummyDepayClass * klass)
94 {
95   GstElementClass *gstelement_class;
96   GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
97
98   gstelement_class = GST_ELEMENT_CLASS (klass);
99   gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
100
101   gst_element_class_add_static_pad_template (gstelement_class,
102       &gst_rtp_dummy_depay_sink_template);
103   gst_element_class_add_static_pad_template (gstelement_class,
104       &gst_rtp_dummy_depay_src_template);
105
106   gstrtpbasedepayload_class->process = gst_rtp_dummy_depay_process;
107   gstrtpbasedepayload_class->set_caps = gst_rtp_dummy_depay_set_caps;
108 }
109
110 static void
111 gst_rtp_dummy_depay_init (GstRtpDummyDepay * depay)
112 {
113   depay->rtptime = 0;
114   depay->num_buffers_in_blist = 1;
115 }
116
117 static GstRtpDummyDepay *
118 rtp_dummy_depay_new (void)
119 {
120   return g_object_new (GST_TYPE_RTP_DUMMY_DEPAY, NULL);
121 }
122
123 static GstBuffer *
124 gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
125 {
126   GstRtpDummyDepay *self = GST_RTP_DUMMY_DEPAY (depayload);
127   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
128   GstBuffer *outbuf;
129   guint32 rtptime;
130   guint i;
131
132   GST_LOG ("depayloading buffer pts=%" GST_TIME_FORMAT " offset=%"
133       G_GUINT64_FORMAT " memories=%d", GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
134       GST_BUFFER_OFFSET (buf), gst_buffer_n_memory (buf));
135
136   for (i = 0; i < gst_buffer_n_memory (buf); i++) {
137     GstMemory *mem = gst_buffer_get_memory (buf, 0);
138     gsize size, offset, maxsize;
139     size = gst_memory_get_sizes (mem, &offset, &maxsize);
140     GST_LOG ("\tsize=%" G_GSIZE_FORMAT " offset=%" G_GSIZE_FORMAT " maxsize=%"
141         G_GSIZE_FORMAT, size, offset, maxsize);
142     gst_memory_unref (mem);
143   }
144
145   gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
146   outbuf = gst_rtp_buffer_get_payload_buffer (&rtp);
147   rtptime = gst_rtp_buffer_get_timestamp (&rtp);
148   gst_rtp_buffer_unmap (&rtp);
149
150   GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
151   GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
152
153   GST_LOG ("depayloaded buffer pts=%" GST_TIME_FORMAT " offset=%"
154       G_GUINT64_FORMAT " rtptime=%" G_GUINT32_FORMAT " memories=%d",
155       GST_TIME_ARGS (GST_BUFFER_PTS (outbuf)),
156       GST_BUFFER_OFFSET (outbuf), rtptime, gst_buffer_n_memory (buf));
157
158   for (i = 0; i < gst_buffer_n_memory (buf); i++) {
159     GstMemory *mem = gst_buffer_get_memory (buf, 0);
160     gsize size, offset, maxsize;
161     size = gst_memory_get_sizes (mem, &offset, &maxsize);
162     GST_LOG ("\tsize=%" G_GSIZE_FORMAT " offset=%" G_GSIZE_FORMAT " maxsize=%"
163         G_GSIZE_FORMAT, size, offset, maxsize);
164     gst_memory_unref (mem);
165   }
166
167   switch (self->push_method) {
168     case GST_RTP_DUMMY_USE_PUSH_FUNC:
169       gst_rtp_base_depayload_push (depayload, outbuf);
170       outbuf = NULL;
171       break;
172     case GST_RTP_DUMMY_USE_PUSH_LIST_FUNC:{
173       GstBufferList *blist = gst_buffer_list_new ();
174       gint i;
175       gst_buffer_list_add (blist, outbuf);
176       for (i = 0; i != self->num_buffers_in_blist - 1; ++i) {
177         gst_buffer_list_add (blist, gst_buffer_copy (outbuf));
178       }
179       outbuf = NULL;
180       gst_rtp_base_depayload_push_list (depayload, blist);
181       break;
182     }
183     case GST_RTP_DUMMY_RETURN_TO_PUSH:
184       break;
185   }
186
187   return outbuf;
188 }
189
190 static gboolean
191 gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter, GstCaps * caps)
192 {
193   GstEvent *event;
194   event = gst_event_new_caps (caps);
195   gst_pad_push_event (filter->srcpad, event);
196   return TRUE;
197 }
198
199 /* Helper functions and global state */
200
201 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
202     GST_PAD_SRC,
203     GST_PAD_ALWAYS,
204     GST_STATIC_CAPS_ANY);
205
206 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
207     GST_PAD_SINK,
208     GST_PAD_ALWAYS,
209     GST_STATIC_CAPS_ANY);
210
211 typedef struct State State;
212
213 struct State
214 {
215   GstElement *element;
216   GstPad *sinkpad;
217   GstPad *srcpad;
218 };
219
220 static GList *events;
221
222 static gboolean
223 event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
224 {
225   events = g_list_append (events, gst_event_ref (event));
226   return gst_pad_event_default (pad, noparent, event);
227 }
228
229 static void
230 drop_events (void)
231 {
232   while (events != NULL) {
233     gst_event_unref (GST_EVENT (events->data));
234     events = g_list_delete_link (events, events);
235   }
236 }
237
238 static void
239 validate_events_received (guint received)
240 {
241   fail_unless_equals_int (g_list_length (events), received);
242 }
243
244 static void
245 validate_event (guint index, const gchar * name, const gchar * field, ...)
246 {
247   GstEvent *event;
248   va_list var_args;
249
250   fail_if (index >= g_list_length (events));
251   event = GST_EVENT (g_list_nth_data (events, index));
252   fail_if (event == NULL);
253
254   GST_TRACE ("%" GST_PTR_FORMAT, event);
255
256   fail_unless_equals_string (GST_EVENT_TYPE_NAME (event), name);
257
258   va_start (var_args, field);
259   while (field) {
260     if (!g_strcmp0 (field, "timestamp")) {
261       GstClockTime expected = va_arg (var_args, GstClockTime);
262       GstClockTime timestamp, duration;
263       gst_event_parse_gap (event, &timestamp, &duration);
264       fail_unless_equals_uint64 (timestamp, expected);
265     } else if (!g_strcmp0 (field, "duration")) {
266       GstClockTime expected = va_arg (var_args, GstClockTime);
267       GstClockTime timestamp, duration;
268       gst_event_parse_gap (event, &timestamp, &duration);
269       fail_unless_equals_uint64 (duration, expected);
270     } else if (!g_strcmp0 (field, "time")) {
271       GstClockTime expected = va_arg (var_args, GstClockTime);
272       const GstSegment *segment;
273       gst_event_parse_segment (event, &segment);
274       fail_unless_equals_uint64 (segment->time, expected);
275     } else if (!g_strcmp0 (field, "start")) {
276       GstClockTime expected = va_arg (var_args, GstClockTime);
277       const GstSegment *segment;
278       gst_event_parse_segment (event, &segment);
279       fail_unless_equals_uint64 (segment->start, expected);
280     } else if (!g_strcmp0 (field, "stop")) {
281       GstClockTime expected = va_arg (var_args, GstClockTime);
282       const GstSegment *segment;
283       gst_event_parse_segment (event, &segment);
284       fail_unless_equals_uint64 (segment->stop, expected);
285     } else if (!g_strcmp0 (field, "applied-rate")) {
286       gdouble expected = va_arg (var_args, gdouble);
287       const GstSegment *segment;
288       gst_event_parse_segment (event, &segment);
289       fail_unless_equals_float (segment->applied_rate, expected);
290     } else if (!g_strcmp0 (field, "rate")) {
291       gdouble expected = va_arg (var_args, gdouble);
292       const GstSegment *segment;
293       gst_event_parse_segment (event, &segment);
294       fail_unless_equals_float (segment->rate, expected);
295     } else if (!g_strcmp0 (field, "base")) {
296       GstClockTime expected = va_arg (var_args, GstClockTime);
297       const GstSegment *segment;
298       gst_event_parse_segment (event, &segment);
299       fail_unless_equals_uint64 (segment->base, expected);
300     } else if (!g_strcmp0 (field, "media-type")) {
301       const gchar *expected = va_arg (var_args, const gchar *);
302       GstCaps *caps;
303       const gchar *media_type;
304       gst_event_parse_caps (event, &caps);
305       media_type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
306       fail_unless_equals_string (media_type, expected);
307     } else if (!g_strcmp0 (field, "npt-start")) {
308       GstClockTime expected = va_arg (var_args, GstClockTime);
309       GstCaps *caps;
310       GstClockTime start;
311       gst_event_parse_caps (event, &caps);
312       fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
313                   0), "npt-start", &start));
314       fail_unless_equals_uint64 (start, expected);
315     } else if (!g_strcmp0 (field, "npt-stop")) {
316       GstClockTime expected = va_arg (var_args, GstClockTime);
317       GstCaps *caps;
318       GstClockTime stop;
319       gst_event_parse_caps (event, &caps);
320       fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
321                   0), "npt-stop", &stop));
322       fail_unless_equals_uint64 (stop, expected);
323     } else if (!g_strcmp0 (field, "play-speed")) {
324       gdouble expected = va_arg (var_args, gdouble);
325       GstCaps *caps;
326       gdouble speed;
327       gst_event_parse_caps (event, &caps);
328       fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
329               "play-speed", &speed));
330       fail_unless (speed == expected);
331     } else if (!g_strcmp0 (field, "play-scale")) {
332       gdouble expected = va_arg (var_args, gdouble);
333       GstCaps *caps;
334       gdouble scale;
335       gst_event_parse_caps (event, &caps);
336       fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
337               "play-scale", &scale));
338       fail_unless (scale == expected);
339     } else if (!g_strcmp0 (field, "clock-base")) {
340       guint expected = va_arg (var_args, guint);
341       GstCaps *caps;
342       guint clock_base;
343       gst_event_parse_caps (event, &caps);
344       fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
345               "clock-base", &clock_base));
346       fail_unless (clock_base == expected);
347
348     } else {
349       fail ("test cannot validate unknown event field '%s'", field);
350     }
351     field = va_arg (var_args, const gchar *);
352   }
353   va_end (var_args);
354 }
355
356 static void
357 rtp_buffer_set_valist (GstBuffer * buf, const gchar * field, va_list var_args,
358     gboolean * extra_ref_)
359 {
360   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
361   gboolean mapped = FALSE;
362   gboolean extra_ref = FALSE;
363
364   while (field) {
365     if (!g_strcmp0 (field, "pts")) {
366       GstClockTime pts = va_arg (var_args, GstClockTime);
367       GST_BUFFER_PTS (buf) = pts;
368     } else if (!g_strcmp0 (field, "offset")) {
369       guint64 offset = va_arg (var_args, guint64);
370       GST_BUFFER_OFFSET (buf) = offset;
371     } else if (!g_strcmp0 (field, "discont")) {
372       gboolean discont = va_arg (var_args, gboolean);
373       if (discont) {
374         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
375       } else {
376         GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
377       }
378     } else {
379       if (!mapped) {
380         gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
381         mapped = TRUE;
382       }
383       if (!g_strcmp0 (field, "rtptime")) {
384         guint32 rtptime = va_arg (var_args, guint64);
385         gst_rtp_buffer_set_timestamp (&rtp, rtptime);
386       } else if (!g_strcmp0 (field, "payload-type")) {
387         guint payload_type = va_arg (var_args, guint);
388         gst_rtp_buffer_set_payload_type (&rtp, payload_type);
389       } else if (!g_strcmp0 (field, "seq")) {
390         guint seq = va_arg (var_args, guint);
391         gst_rtp_buffer_set_seq (&rtp, seq);
392       } else if (!g_strcmp0 (field, "ssrc")) {
393         guint32 ssrc = va_arg (var_args, guint);
394         gst_rtp_buffer_set_ssrc (&rtp, ssrc);
395       } else if (!g_strcmp0 (field, "extra-ref")) {
396         extra_ref = va_arg (var_args, gboolean);
397         if (extra_ref_)
398           *extra_ref_ = extra_ref;
399       } else if (!g_strcmp0 (field, "csrc")) {
400         guint idx = va_arg (var_args, guint);
401         guint csrc = va_arg (var_args, guint);
402         gst_rtp_buffer_set_csrc (&rtp, idx, csrc);
403       } else if (g_str_has_prefix (field, "hdrext-")) {
404         GstRTPHeaderExtension *ext = va_arg (var_args, GstRTPHeaderExtension *);
405         guint id = gst_rtp_header_extension_get_id (ext);
406         gsize size = gst_rtp_header_extension_get_max_size (ext, buf);
407         guint8 *data = g_malloc0 (size);
408
409         if (!g_strcmp0 (field, "hdrext-1")) {
410           fail_unless (gst_rtp_header_extension_write (ext, buf,
411                   GST_RTP_HEADER_EXTENSION_ONE_BYTE, buf, data, size) > 0);
412           fail_unless (gst_rtp_buffer_add_extension_onebyte_header (&rtp, id,
413                   data, size));
414         } else if (!g_strcmp0 (field, "hdrext-2")) {
415           fail_unless (gst_rtp_header_extension_write (ext, buf,
416                   GST_RTP_HEADER_EXTENSION_TWO_BYTE, buf, data, size) > 0);
417           fail_unless (gst_rtp_buffer_add_extension_twobytes_header (&rtp, 0,
418                   id, data, size));
419         }
420
421         g_free (data);
422       } else {
423         fail ("test cannot set unknown buffer field '%s'", field);
424       }
425     }
426     field = va_arg (var_args, const gchar *);
427   }
428
429   if (mapped) {
430     gst_rtp_buffer_unmap (&rtp);
431   }
432
433   if (extra_ref)
434     gst_buffer_ref (buf);
435 }
436
437 static void
438 rtp_buffer_set (GstBuffer * buf, const gchar * field, ...)
439 {
440   va_list var_args;
441
442   va_start (var_args, field);
443   rtp_buffer_set_valist (buf, field, var_args, NULL);
444   va_end (var_args);
445 }
446
447 #define push_rtp_buffer(state, field, ...) \
448     push_rtp_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
449 #define push_rtp_buffer_fails(state, error, field, ...) \
450     push_rtp_buffer_full ((state), (error), (field), __VA_ARGS__)
451
452 static void
453 push_rtp_buffer_full (State * state, GstFlowReturn expected,
454     const gchar * field, ...)
455 {
456   GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
457   va_list var_args;
458   gboolean extra_ref = FALSE;
459
460   va_start (var_args, field);
461   rtp_buffer_set_valist (buf, field, var_args, &extra_ref);
462   va_end (var_args);
463
464   fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
465
466   if (extra_ref)
467     gst_buffer_unref (buf);
468 }
469
470 #define push_buffer(state, field, ...) \
471     push_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
472
473 static void
474 push_buffer_full (State * state, GstFlowReturn expected,
475     const gchar * field, ...)
476 {
477   GstBuffer *buf = gst_buffer_new_allocate (0, 0, 0);
478   va_list var_args;
479
480   va_start (var_args, field);
481   while (field) {
482     if (!g_strcmp0 (field, "pts")) {
483       GstClockTime pts = va_arg (var_args, GstClockTime);
484       GST_BUFFER_PTS (buf) = pts;
485     } else if (!g_strcmp0 (field, "offset")) {
486       guint64 offset = va_arg (var_args, guint64);
487       GST_BUFFER_OFFSET (buf) = offset;
488     } else if (!g_strcmp0 (field, "discont")) {
489       gboolean discont = va_arg (var_args, gboolean);
490       if (discont) {
491         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
492       } else {
493         GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
494       }
495     } else {
496       fail ("test cannot set unknown buffer field '%s'", field);
497     }
498     field = va_arg (var_args, const gchar *);
499   }
500   va_end (var_args);
501
502   fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
503 }
504
505 static void
506 validate_buffers_received (guint received)
507 {
508   fail_unless_equals_int (g_list_length (buffers), received);
509 }
510
511 static void
512 validate_buffer (guint index, const gchar * field, ...)
513 {
514   GstBuffer *buf;
515   va_list var_args;
516
517   fail_if (index >= g_list_length (buffers));
518   buf = GST_BUFFER (g_list_nth_data (buffers, (index)));
519   fail_if (buf == NULL);
520
521   GST_TRACE ("%" GST_PTR_FORMAT, buf);
522
523   va_start (var_args, field);
524   while (field) {
525     if (!g_strcmp0 (field, "pts")) {
526       GstClockTime pts = va_arg (var_args, GstClockTime);
527       fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), pts);
528     } else if (!g_strcmp0 (field, "offset")) {
529       guint64 offset = va_arg (var_args, guint64);
530       fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buf), offset);
531     } else if (!g_strcmp0 (field, "discont")) {
532       gboolean discont = va_arg (var_args, gboolean);
533       if (discont) {
534         fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
535       } else {
536         fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
537       }
538     } else {
539       fail ("test cannot validate unknown buffer field '%s'", field);
540     }
541     field = va_arg (var_args, const gchar *);
542   }
543   va_end (var_args);
544 }
545
546 static State *
547 create_depayloader (const gchar * caps_str, const gchar * property, ...)
548 {
549   va_list var_args;
550   GstCaps *caps;
551   State *state;
552
553   state = g_new0 (State, 1);
554
555   state->element = GST_ELEMENT (rtp_dummy_depay_new ());
556   fail_unless (GST_IS_RTP_DUMMY_DEPAY (state->element));
557
558   va_start (var_args, property);
559   g_object_set_valist (G_OBJECT (state->element), property, var_args);
560   va_end (var_args);
561
562   state->srcpad = gst_check_setup_src_pad (state->element, &srctemplate);
563   state->sinkpad = gst_check_setup_sink_pad (state->element, &sinktemplate);
564
565   fail_unless (gst_pad_set_active (state->srcpad, TRUE));
566   fail_unless (gst_pad_set_active (state->sinkpad, TRUE));
567
568   if (caps_str) {
569     caps = gst_caps_from_string (caps_str);
570   } else {
571     caps = NULL;
572   }
573   gst_check_setup_events (state->srcpad, state->element, caps, GST_FORMAT_TIME);
574   if (caps) {
575     gst_caps_unref (caps);
576   }
577
578   gst_pad_set_chain_function (state->sinkpad, gst_check_chain_func);
579   gst_pad_set_event_function (state->sinkpad, event_func);
580
581   return state;
582 }
583
584 static void
585 set_state (State * state, GstState new_state)
586 {
587   fail_unless_equals_int (gst_element_set_state (state->element, new_state),
588       GST_STATE_CHANGE_SUCCESS);
589 }
590
591 static void
592 packet_lost (State * state, GstClockTime timestamp, GstClockTime duration,
593     gboolean might_have_been_fec)
594 {
595   GstEvent *event;
596   guint seqnum = 0x4243;
597   gboolean late = TRUE;
598   guint retries = 42;
599
600   event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
601       gst_structure_new ("GstRTPPacketLost",
602           "seqnum", G_TYPE_UINT, seqnum,
603           "timestamp", G_TYPE_UINT64, timestamp,
604           "duration", G_TYPE_UINT64, duration,
605           "might-have-been-fec", G_TYPE_BOOLEAN, might_have_been_fec,
606           "late", G_TYPE_BOOLEAN, late, "retry", G_TYPE_UINT, retries, NULL));
607
608   fail_unless (gst_pad_push_event (state->srcpad, event));
609 }
610
611 static void
612 reconfigure_caps (State * state, const gchar * caps_str)
613 {
614   GstCaps *newcaps;
615   GstEvent *event;
616   newcaps = gst_caps_from_string (caps_str);
617   event = gst_event_new_caps (newcaps);
618   gst_caps_unref (newcaps);
619   fail_unless (gst_pad_push_event (state->srcpad, event));
620 }
621
622 static void
623 flush_pipeline (State * state)
624 {
625   GstEvent *event;
626   GstSegment segment;
627   event = gst_event_new_flush_start ();
628   fail_unless (gst_pad_push_event (state->srcpad, event));
629   event = gst_event_new_flush_stop (TRUE);
630   fail_unless (gst_pad_push_event (state->srcpad, event));
631   gst_segment_init (&segment, GST_FORMAT_TIME);
632   event = gst_event_new_segment (&segment);
633   fail_unless (gst_pad_push_event (state->srcpad, event));
634 }
635
636 static void
637 destroy_depayloader (State * state)
638 {
639   gst_check_teardown_sink_pad (state->element);
640   gst_check_teardown_src_pad (state->element);
641
642   gst_check_drop_buffers ();
643   drop_events ();
644
645   g_object_unref (state->element);
646
647   g_free (state);
648 }
649
650 /* Tests */
651
652 /* send two RTP packets having sequential sequence numbers and timestamps
653  * differing by DEFAULT_CLOCK_RATE. the depayloader first pushes the normal
654  * stream-start, caps and segment events downstream before processing each RTP
655  * packet and pushing a corresponding buffer. PTS will be carried over from the
656  * RTP packets by the payloader to the buffers. because the sequence numbers are
657  * sequential then GST_BUFFER_FLAG_DISCONT will not be set for either buffer.
658  */
659 GST_START_TEST (rtp_base_depayload_buffer_test)
660 {
661   State *state;
662
663   state = create_depayloader ("application/x-rtp", NULL);
664
665   set_state (state, GST_STATE_PLAYING);
666
667   push_rtp_buffer (state,
668       "pts", 0 * GST_SECOND,
669       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
670
671   push_rtp_buffer (state,
672       "pts", 1 * GST_SECOND,
673       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
674       "seq", 0x4242 + 1, NULL);
675
676   set_state (state, GST_STATE_NULL);
677
678   validate_buffers_received (2);
679
680   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
681
682   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
683
684   validate_events_received (3);
685
686   validate_event (0, "stream-start", NULL);
687
688   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
689
690   validate_event (2, "segment",
691       "time", G_GUINT64_CONSTANT (0),
692       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
693
694   destroy_depayloader (state);
695 }
696
697 GST_END_TEST
698 /* the intent with this test is to provide the depayloader with a buffer that
699  * does not contain an RTP header. this makes it impossible for the depayloader
700  * to depayload the incoming RTP packet, yet the stream-start and caps events
701  * will still be pushed.
702  */
703 GST_START_TEST (rtp_base_depayload_invalid_rtp_packet_test)
704 {
705   State *state;
706
707   state = create_depayloader ("application/x-rtp", NULL);
708
709   set_state (state, GST_STATE_PLAYING);
710
711   push_buffer (state,
712       "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
713
714   set_state (state, GST_STATE_NULL);
715
716   validate_buffers_received (0);
717
718   validate_events_received (2);
719
720   validate_event (0, "stream-start", NULL);
721
722   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
723
724   destroy_depayloader (state);
725 }
726
727 GST_END_TEST
728 /* validate what happens when a depayloader is provided with two RTP packets
729  * sent after each other that do not have sequential sequence numbers. in this
730  * case the depayloader should be able to depayload both first and the second
731  * buffer, but the second buffer will have GST_BUFFER_FLAG_DISCONT set to
732  * indicate that the was a discontinuity in the stream. the initial events are
733  * pushed prior to the buffers arriving so they should be unaffected by the gap
734  * in sequence numbers.
735  */
736 GST_START_TEST (rtp_base_depayload_with_gap_test)
737 {
738   State *state;
739
740   state = create_depayloader ("application/x-rtp", NULL);
741
742   set_state (state, GST_STATE_PLAYING);
743
744   push_rtp_buffer (state,
745       "pts", 0 * GST_SECOND,
746       "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
747
748   push_rtp_buffer (state,
749       "pts", 1 * GST_SECOND,
750       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
751       "seq", 0x4242 + 2, NULL);
752
753   set_state (state, GST_STATE_NULL);
754
755   validate_buffers_received (2);
756
757   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
758
759   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
760
761   validate_events_received (3);
762
763   validate_event (0, "stream-start", NULL);
764
765   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
766
767   validate_event (2, "segment",
768       "time", G_GUINT64_CONSTANT (0),
769       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
770
771   destroy_depayloader (state);
772 }
773
774 GST_END_TEST
775 /* two RTP packets are pushed in this test, and while the sequence numbers are
776  * sequential they are reversed. the expectation is that the depayloader will be
777  * able to depayload the first RTP packet, but once the second RTP packet
778  * arrives it will be discarded because it arrived too late. the initial events
779  * should be unaffected by the reversed buffers.
780  */
781 GST_START_TEST (rtp_base_depayload_reversed_test)
782 {
783   State *state;
784
785   state = create_depayloader ("application/x-rtp", NULL);
786
787   set_state (state, GST_STATE_PLAYING);
788
789   push_rtp_buffer (state,
790       "pts", 0 * GST_SECOND,
791       "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
792
793   push_rtp_buffer (state,
794       "pts", 1 * GST_SECOND,
795       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
796       "seq", 0x4242 - 1, NULL);
797
798   set_state (state, GST_STATE_NULL);
799
800   validate_buffers_received (1);
801
802   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
803
804   validate_events_received (3);
805
806   validate_event (0, "stream-start", NULL);
807
808   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
809
810   validate_event (2, "segment",
811       "time", G_GUINT64_CONSTANT (0),
812       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
813
814   destroy_depayloader (state);
815 }
816
817 GST_END_TEST
818 /* The same scenario as in rtp_base_depayload_reversed_test
819  * except that SSRC is changed for the 2nd packet that is why
820  * it should not be discarded.
821  */
822 GST_START_TEST (rtp_base_depayload_ssrc_changed_test)
823 {
824   State *state;
825
826   state = create_depayloader ("application/x-rtp", NULL);
827
828   set_state (state, GST_STATE_PLAYING);
829
830   push_rtp_buffer (state,
831       "pts", 0 * GST_SECOND,
832       "rtptime", G_GUINT64_CONSTANT (0x43214321),
833       "seq", 0x4242, "ssrc", 0xabe2b0b, NULL);
834
835   push_rtp_buffer (state,
836       "pts", 1 * GST_SECOND,
837       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
838       "seq", 0x4242 - 1, "ssrc", 0xcafebabe, NULL);
839
840   set_state (state, GST_STATE_NULL);
841
842   validate_buffers_received (2);
843
844   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
845
846   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
847
848   validate_events_received (3);
849
850   validate_event (0, "stream-start", NULL);
851
852   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
853
854   validate_event (2, "segment",
855       "time", G_GUINT64_CONSTANT (0),
856       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
857
858   destroy_depayloader (state);
859 }
860
861 GST_END_TEST
862 /* the intent of this test is to push two RTP packets that have reverse sequence
863  * numbers that differ significantly. the depayloader will consider RTP packets
864  * where the sequence numbers differ by more than 1000 to indicate that the
865  * source of the RTP packets has been restarted. therefore it will let both
866  * depayloaded buffers through, but the latter buffer marked
867  * GST_BUFFER_FLAG_DISCONT to indicate the discontinuity in the stream. the
868  * initial events should be unaffected by the reversed buffers.
869  */
870 GST_START_TEST (rtp_base_depayload_old_reversed_test)
871 {
872   State *state;
873
874   state = create_depayloader ("application/x-rtp", NULL);
875
876   set_state (state, GST_STATE_PLAYING);
877
878   push_rtp_buffer (state,
879       "pts", 0 * GST_SECOND,
880       "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
881
882   push_rtp_buffer (state,
883       "pts", 1 * GST_SECOND,
884       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
885       "seq", 0x4242 - 1000, NULL);
886
887   set_state (state, GST_STATE_NULL);
888
889   validate_buffers_received (2);
890
891   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
892
893   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
894
895   validate_events_received (3);
896
897   validate_event (0, "stream-start", NULL);
898
899   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
900
901   validate_event (2, "segment",
902       "time", G_GUINT64_CONSTANT (0),
903       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
904
905   destroy_depayloader (state);
906 }
907
908 GST_END_TEST
909 /* a depayloader that has not received any caps event will not be able to
910  * process any incoming RTP packet. instead pushing an RTP packet should result
911  * in the expected error.
912  */
913 GST_START_TEST (rtp_base_depayload_without_negotiation_test)
914 {
915   State *state;
916
917   state = create_depayloader (NULL, NULL);
918
919   set_state (state, GST_STATE_PLAYING);
920
921   push_rtp_buffer_fails (state, GST_FLOW_NOT_NEGOTIATED,
922       "pts", 0 * GST_SECOND,
923       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
924
925   set_state (state, GST_STATE_NULL);
926
927   validate_buffers_received (0);
928
929   validate_events_received (1);
930
931   validate_event (0, "stream-start", NULL);
932
933   destroy_depayloader (state);
934 }
935
936 GST_END_TEST
937 /* a depayloader that receives the downstream event GstRTPPacketLost should
938  * respond by emitting a gap event with the corresponding timestamp and
939  * duration. the initial events are unaffected, but are succeeded by the added
940  * gap event.
941  */
942 GST_START_TEST (rtp_base_depayload_packet_lost_test)
943 {
944   State *state;
945
946   state = create_depayloader ("application/x-rtp", NULL);
947
948   set_state (state, GST_STATE_PLAYING);
949
950   push_rtp_buffer (state,
951       "pts", 0 * GST_SECOND,
952       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
953
954   packet_lost (state, 1 * GST_SECOND, GST_SECOND, FALSE);
955
956   /* If a packet was lost but we don't know whether it was a FEC packet,
957    * the depayloader should not generate gap events */
958   packet_lost (state, 2 * GST_SECOND, GST_SECOND, TRUE);
959
960   push_rtp_buffer (state,
961       "pts", 2 * GST_SECOND,
962       "rtptime", G_GUINT64_CONSTANT (0x1234) + 2 * DEFAULT_CLOCK_RATE,
963       "seq", 0x4242 + 2, NULL);
964
965   set_state (state, GST_STATE_NULL);
966
967   validate_buffers_received (2);
968
969   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
970
971   validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
972
973   validate_events_received (4);
974
975   validate_event (0, "stream-start", NULL);
976
977   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
978
979   validate_event (2, "segment",
980       "time", G_GUINT64_CONSTANT (0),
981       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
982
983   validate_event (3, "gap",
984       "timestamp", 1 * GST_SECOND, "duration", GST_SECOND, NULL);
985
986   destroy_depayloader (state);
987 }
988
989 GST_END_TEST
990 /* If a lost event is received before the first buffer, the rtp base
991  * depayloader will not send a gap event downstream. Alternatively it should
992  * make sure that stream-start, caps and segment events are sent in correct
993  * order before the gap event so that packet loss concealment can take place
994  * downstream, but this is more complicated and without any real benefit since
995  * concealment before any data is received is not very useful. */
996 GST_START_TEST (rtp_base_depayload_packet_lost_before_first_buffer_test)
997 {
998   GstHarness *h;
999   GstEvent *event;
1000   GstRtpDummyDepay *depay;
1001   const GstEventType etype[] = {
1002     GST_EVENT_STREAM_START, GST_EVENT_CAPS, GST_EVENT_SEGMENT
1003   };
1004   gint i;
1005
1006   depay = rtp_dummy_depay_new ();
1007   h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1008   gst_harness_set_src_caps_str (h, "application/x-rtp");
1009
1010   /* Verify that depayloader has received setup events */
1011   for (i = 0; i < 3; i++) {
1012     event = gst_pad_get_sticky_event (h->srcpad, etype[i], 0);
1013     fail_unless (event != NULL);
1014     gst_event_unref (event);
1015   }
1016
1017   /* Send loss event to depayloader */
1018   gst_harness_push_event (h, gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
1019           gst_structure_new ("GstRTPPacketLost",
1020               "seqnum", G_TYPE_UINT, (guint) 0,
1021               "timestamp", G_TYPE_UINT64, (guint64) 0,
1022               "duration", G_TYPE_UINT64, (guint64) 10 * GST_MSECOND, NULL)));
1023
1024   /* When a buffer is pushed, an updated (and more accurate) segment event
1025    * should also be sent. */
1026   gst_harness_push (h, gst_rtp_buffer_new_allocate (0, 0, 0));
1027
1028   /* Verify that setup events are sent before gap event */
1029   for (i = 0; i < 3; i++) {
1030     fail_unless (event = gst_harness_pull_event (h));
1031     fail_unless_equals_int (GST_EVENT_TYPE (event), etype[i]);
1032     gst_event_unref (event);
1033   }
1034   fail_unless_equals_int (gst_harness_events_in_queue (h), 0);
1035
1036   gst_buffer_unref (gst_harness_pull (h));
1037   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1038
1039   g_object_unref (depay);
1040   gst_harness_teardown (h);
1041 }
1042
1043 GST_END_TEST;
1044 /* rtp base depayloader should set DISCONT flag on buffer in case of a large
1045  * sequence number gap, and it's not set already by upstream. This tests a
1046  * certain code path where the buffer needs to be made writable to set the
1047  * DISCONT flag.
1048  */
1049 GST_START_TEST (rtp_base_depayload_seq_discont_test)
1050 {
1051   State *state;
1052
1053   state = create_depayloader ("application/x-rtp", NULL);
1054
1055   set_state (state, GST_STATE_PLAYING);
1056
1057   push_rtp_buffer (state,
1058       "pts", 0 * GST_SECOND,
1059       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 1, NULL);
1060
1061   push_rtp_buffer (state,
1062       "extra-ref", TRUE,
1063       "pts", 2 * GST_SECOND,
1064       "rtptime", G_GUINT64_CONSTANT (0x1234) + DEFAULT_CLOCK_RATE / 2,
1065       "seq", 33333, NULL);
1066
1067   set_state (state, GST_STATE_NULL);
1068
1069   validate_buffers_received (2);
1070
1071   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1072
1073   validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
1074
1075   destroy_depayloader (state);
1076 }
1077
1078 GST_END_TEST
1079 /* a depayloader that receives identical caps events simply ignores the latter
1080  * events without propagating them downstream.
1081  */
1082 GST_START_TEST (rtp_base_depayload_repeated_caps_test)
1083 {
1084   State *state;
1085
1086   state = create_depayloader ("application/x-rtp", NULL);
1087
1088   set_state (state, GST_STATE_PLAYING);
1089
1090   push_rtp_buffer (state,
1091       "pts", 0 * GST_SECOND,
1092       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1093
1094   reconfigure_caps (state, "application/x-rtp");
1095
1096   push_rtp_buffer (state,
1097       "pts", 1 * GST_SECOND,
1098       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1099       "seq", 0x4242 + 1, NULL);
1100
1101   set_state (state, GST_STATE_NULL);
1102
1103   validate_buffers_received (2);
1104
1105   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1106
1107   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1108
1109   validate_events_received (3);
1110
1111   validate_event (0, "stream-start", NULL);
1112
1113   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1114
1115   validate_event (2, "segment",
1116       "time", G_GUINT64_CONSTANT (0),
1117       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1118
1119   destroy_depayloader (state);
1120 }
1121
1122 GST_END_TEST
1123 /* when a depayloader receives new caps events with npt-start and npt-stop times
1124  * it should save these timestamps as they should affect the next segment event
1125  * being pushed by the depayloader. a new segment event is not pushed by the
1126  * depayloader until a flush_stop event and a succeeding segment event are
1127  * received. of course the initial event are unaffected, as is the incoming caps
1128  * event.
1129  */
1130 GST_START_TEST (rtp_base_depayload_npt_test)
1131 {
1132   State *state;
1133
1134   state = create_depayloader ("application/x-rtp", NULL);
1135
1136   set_state (state, GST_STATE_PLAYING);
1137
1138   push_rtp_buffer (state,
1139       "pts", 0 * GST_SECOND,
1140       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1141
1142   reconfigure_caps (state,
1143       "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321");
1144
1145   flush_pipeline (state);
1146
1147   push_rtp_buffer (state,
1148       "pts", 1 * GST_SECOND,
1149       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1150       "seq", 0x4242 + 1, NULL);
1151
1152   set_state (state, GST_STATE_NULL);
1153
1154   validate_buffers_received (2);
1155
1156   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1157
1158   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1159
1160   validate_events_received (7);
1161
1162   validate_event (0, "stream-start", NULL);
1163
1164   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1165
1166   validate_event (2, "segment",
1167       "time", G_GUINT64_CONSTANT (0),
1168       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1169
1170   validate_event (3, "caps",
1171       "media-type", "application/x-rtp",
1172       "npt-start", G_GUINT64_CONSTANT (1234),
1173       "npt-stop", G_GUINT64_CONSTANT (4321), NULL);
1174
1175   validate_event (4, "flush-start", NULL);
1176
1177   validate_event (5, "flush-stop", NULL);
1178
1179   validate_event (6, "segment",
1180       "time", G_GUINT64_CONSTANT (1234),
1181       "start", G_GUINT64_CONSTANT (0),
1182       "stop", G_GUINT64_CONSTANT (4321 - 1234), NULL);
1183
1184   destroy_depayloader (state);
1185 }
1186
1187 GST_END_TEST
1188 /* when a depayloader receives a new caps event with play-scale it should save
1189  * this rate as it should affect the next segment event being pushed by the
1190  * depayloader. a new segment event is not pushed by the depayloader until a
1191  * flush_stop event and a succeeding segment event are received. of course the
1192  * initial event are unaffected, as is the incoming caps event.
1193  */
1194 GST_START_TEST (rtp_base_depayload_play_scale_test)
1195 {
1196   State *state;
1197
1198   state = create_depayloader ("application/x-rtp", NULL);
1199
1200   set_state (state, GST_STATE_PLAYING);
1201
1202   push_rtp_buffer (state,
1203       "pts", 0 * GST_SECOND,
1204       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1205
1206   reconfigure_caps (state, "application/x-rtp, play-scale=(double)2.0");
1207
1208   flush_pipeline (state);
1209
1210   push_rtp_buffer (state,
1211       "pts", 1 * GST_SECOND,
1212       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1213       "seq", 0x4242 + 1, NULL);
1214
1215   set_state (state, GST_STATE_NULL);
1216
1217   validate_buffers_received (2);
1218
1219   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1220
1221   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1222
1223   validate_events_received (7);
1224
1225   validate_event (0, "stream-start", NULL);
1226
1227   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1228
1229   validate_event (2, "segment",
1230       "time", G_GUINT64_CONSTANT (0),
1231       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1232
1233   validate_event (3, "caps",
1234       "media-type", "application/x-rtp", "play-scale", 2.0, NULL);
1235
1236   validate_event (4, "flush-start", NULL);
1237
1238   validate_event (5, "flush-stop", NULL);
1239
1240   validate_event (6, "segment",
1241       "time", G_GUINT64_CONSTANT (0),
1242       "start", G_GUINT64_CONSTANT (0),
1243       "stop", G_MAXUINT64, "rate", 1.0, "applied-rate", 2.0, NULL);
1244
1245   destroy_depayloader (state);
1246 }
1247
1248 GST_END_TEST
1249 /* when a depayloader receives a new caps event with play-speed it should save
1250  * this rate as it should affect the next segment event being pushed by the
1251  * depayloader. a new segment event is not pushed by the depayloader until a
1252  * flush_stop event and a succeeding segment event are received. of course the
1253  * initial event are unaffected, as is the incoming caps event.
1254  */
1255 GST_START_TEST (rtp_base_depayload_play_speed_test)
1256 {
1257   State *state;
1258
1259   state = create_depayloader ("application/x-rtp", NULL);
1260
1261   set_state (state, GST_STATE_PLAYING);
1262
1263   push_rtp_buffer (state,
1264       "pts", 0 * GST_SECOND,
1265       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1266
1267   reconfigure_caps (state, "application/x-rtp, play-speed=(double)2.0");
1268
1269   flush_pipeline (state);
1270
1271   push_rtp_buffer (state,
1272       "pts", 1 * GST_SECOND,
1273       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1274       "seq", 0x4242 + 1, NULL);
1275
1276   set_state (state, GST_STATE_NULL);
1277
1278   validate_buffers_received (2);
1279
1280   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1281
1282   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1283
1284   validate_events_received (7);
1285
1286   validate_event (0, "stream-start", NULL);
1287
1288   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1289
1290   validate_event (2, "segment",
1291       "time", G_GUINT64_CONSTANT (0),
1292       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1293
1294   validate_event (3, "caps",
1295       "media-type", "application/x-rtp", "play-speed", 2.0, NULL);
1296
1297   validate_event (4, "flush-start", NULL);
1298
1299   validate_event (5, "flush-stop", NULL);
1300
1301   validate_event (6, "segment",
1302       "time", G_GUINT64_CONSTANT (0),
1303       "start", G_GUINT64_CONSTANT (0),
1304       "stop", G_MAXUINT64, "rate", 2.0, "applied-rate", 1.0, NULL);
1305
1306   destroy_depayloader (state);
1307 }
1308
1309 GST_END_TEST
1310 /* when a depayloader receives new caps events with npt-start, npt-stop and
1311  * clock-base it should save these timestamps as they should affect the next
1312  * segment event being pushed by the depayloader. the produced segment should
1313  * make the position of the stream reflect the position from clock-base instead
1314  * of reflecting the running time (for RTSP).
1315  */
1316 GST_START_TEST (rtp_base_depayload_clock_base_test)
1317 {
1318   State *state;
1319
1320   state = create_depayloader ("application/x-rtp", NULL);
1321
1322   set_state (state, GST_STATE_PLAYING);
1323
1324   push_rtp_buffer (state,
1325       "pts", 0 * GST_SECOND,
1326       "rtptime", G_GUINT64_CONSTANT (1234), "seq", 0x4242, NULL);
1327
1328   reconfigure_caps (state,
1329       "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321, clock-base=(guint)1234");
1330
1331   flush_pipeline (state);
1332
1333   push_rtp_buffer (state,
1334       "pts", 1 * GST_SECOND,
1335       "rtptime", G_GUINT64_CONSTANT (1234) + 1 * DEFAULT_CLOCK_RATE,
1336       "seq", 0x4242 + 1, NULL);
1337
1338   set_state (state, GST_STATE_NULL);
1339
1340   validate_buffers_received (2);
1341
1342   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1343
1344   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1345
1346   validate_events_received (7);
1347
1348   validate_event (0, "stream-start", NULL);
1349
1350   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1351
1352   validate_event (2, "segment",
1353       "time", G_GUINT64_CONSTANT (0),
1354       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1355
1356   validate_event (3, "caps",
1357       "media-type", "application/x-rtp",
1358       "npt-start", G_GUINT64_CONSTANT (1234),
1359       "npt-stop", G_GUINT64_CONSTANT (4321), "clock-base", 1234, NULL);
1360
1361   validate_event (4, "flush-start", NULL);
1362
1363   validate_event (5, "flush-stop", NULL);
1364
1365   validate_event (6, "segment",
1366       "time", G_GUINT64_CONSTANT (1234),
1367       "start", GST_SECOND,
1368       "stop", GST_SECOND + G_GUINT64_CONSTANT (4321 - 1234),
1369       "base", GST_SECOND, NULL);
1370
1371   destroy_depayloader (state);
1372 }
1373
1374 GST_END_TEST
1375 /* basedepayloader has a property source-info that will add
1376  * GstRTPSourceMeta to the output buffer with RTP source information, such as
1377  * SSRC and CSRCs. The is useful for letting downstream know about the origin
1378  * of the stream. */
1379 GST_START_TEST (rtp_base_depayload_source_info_test)
1380 {
1381   GstHarness *h;
1382   GstRtpDummyDepay *depay;
1383   GstBuffer *buffer;
1384   GstRTPSourceMeta *meta;
1385   guint seq = 0;
1386
1387   depay = rtp_dummy_depay_new ();
1388   h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1389   gst_harness_set_src_caps_str (h, "application/x-rtp");
1390
1391   /* Property enabled should always add meta, also when there is only SSRC and
1392    * no CSRC. */
1393   g_object_set (depay, "source-info", TRUE, NULL);
1394   buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1395   rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1396   buffer = gst_harness_push_and_pull (h, buffer);
1397   fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1398   fail_unless (meta->ssrc_valid);
1399   fail_unless_equals_int (meta->ssrc, 0x11);
1400   fail_unless_equals_int (meta->csrc_count, 0);
1401   gst_buffer_unref (buffer);
1402
1403   /* Both SSRC and CSRC should be added to the meta */
1404   buffer = gst_rtp_buffer_new_allocate (0, 0, 2);
1405   rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, "csrc", 0, 0x22,
1406       "csrc", 1, 0x33, NULL);
1407   buffer = gst_harness_push_and_pull (h, buffer);
1408   fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1409   fail_unless (meta->ssrc_valid);
1410   fail_unless_equals_int (meta->ssrc, 0x11);
1411   fail_unless_equals_int (meta->csrc_count, 2);
1412   fail_unless_equals_int (meta->csrc[0], 0x22);
1413   fail_unless_equals_int (meta->csrc[1], 0x33);
1414   gst_buffer_unref (buffer);
1415
1416   /* Property disabled should never add meta */
1417   g_object_set (depay, "source-info", FALSE, NULL);
1418   buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1419   rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1420   buffer = gst_harness_push_and_pull (h, buffer);
1421   fail_if (gst_buffer_get_rtp_source_meta (buffer));
1422   gst_buffer_unref (buffer);
1423
1424   g_object_unref (depay);
1425   gst_harness_teardown (h);
1426 }
1427
1428 GST_END_TEST;
1429
1430 /* verify that if a buffer arriving in the depayloader already has source-info
1431    meta on it, that this does not affect the source-info coming out of the
1432    depayloder, which should be all derived from the rtp-header */
1433 GST_START_TEST (rtp_base_depayload_source_info_from_rtp_only)
1434 {
1435   GstHarness *h;
1436   GstRtpDummyDepay *depay;
1437   GstBuffer *buffer;
1438   GstRTPSourceMeta *meta;
1439   guint rtp_ssrc = 0x11;
1440   guint rtp_csrc = 0x22;
1441   guint32 meta_ssrc = 0x55;
1442   guint32 meta_csrc = 0x66;
1443
1444   depay = rtp_dummy_depay_new ();
1445   h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1446   gst_harness_set_src_caps_str (h, "application/x-rtp");
1447
1448   g_object_set (depay, "source-info", TRUE, NULL);
1449   buffer = gst_rtp_buffer_new_allocate (0, 0, 1);
1450   rtp_buffer_set (buffer, "seq", 0, "ssrc", rtp_ssrc, "csrc", 0, rtp_csrc,
1451       NULL);
1452   meta = gst_buffer_add_rtp_source_meta (buffer, &meta_ssrc, &meta_csrc, 1);
1453
1454   buffer = gst_harness_push_and_pull (h, buffer);
1455   fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1456   fail_unless (meta->ssrc_valid);
1457   fail_unless_equals_int (meta->ssrc, rtp_ssrc);
1458   fail_unless_equals_int (meta->csrc_count, 1);
1459   fail_unless_equals_int (meta->csrc[0], rtp_csrc);
1460   gst_buffer_unref (buffer);
1461
1462   g_object_unref (depay);
1463   gst_harness_teardown (h);
1464 }
1465
1466 GST_END_TEST;
1467
1468 /* Test max-reorder property. Reordered packets with a gap less than
1469  * max-reordered will be dropped, reordered packets with gap larger than
1470  * max-reorder is considered coming fra a restarted sender and should not be
1471  * dropped. */
1472 GST_START_TEST (rtp_base_depayload_max_reorder)
1473 {
1474   GstHarness *h;
1475   GstRtpDummyDepay *depay;
1476   guint seq = 1000;
1477
1478   depay = rtp_dummy_depay_new ();
1479   h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1480   gst_harness_set_src_caps_str (h, "application/x-rtp");
1481
1482 #define PUSH_AND_CHECK(seqnum, pushed) G_STMT_START {                   \
1483     GstBuffer *buffer = gst_rtp_buffer_new_allocate (0, 0, 0);          \
1484     rtp_buffer_set (buffer, "seq", seqnum, "ssrc", 0x11, NULL);         \
1485     fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer)); \
1486     fail_unless_equals_int (gst_harness_buffers_in_queue (h), pushed);  \
1487     if (pushed)                                                         \
1488       gst_buffer_unref (gst_harness_pull (h));                          \
1489   } G_STMT_END;
1490
1491   /* By default some reordering is accepted. Old seqnums should be
1492    * dropped, but not too old */
1493   PUSH_AND_CHECK (seq, TRUE);
1494   PUSH_AND_CHECK (seq - 50, FALSE);
1495   PUSH_AND_CHECK (seq - 100, TRUE);
1496
1497   /* Update property to allow less reordering */
1498   g_object_set (depay, "max-reorder", 3, NULL);
1499
1500   /* Gaps up to max allowed reordering is dropped. */
1501   PUSH_AND_CHECK (seq, TRUE);
1502   PUSH_AND_CHECK (seq - 2, FALSE);
1503   PUSH_AND_CHECK (seq - 3, TRUE);
1504
1505   /* After a push the initial state should be reset, so a duplicate of the
1506    * last packet should be dropped */
1507   PUSH_AND_CHECK (seq - 3, FALSE);
1508
1509   /* Update property to minimum value. Should never drop buffers. */
1510   g_object_set (depay, "max-reorder", 0, NULL);
1511
1512   /* Duplicate buffer should now be pushed. */
1513   PUSH_AND_CHECK (seq, TRUE);
1514   PUSH_AND_CHECK (seq, TRUE);
1515
1516   g_object_unref (depay);
1517   gst_harness_teardown (h);
1518 }
1519
1520 GST_END_TEST;
1521
1522 GST_START_TEST (rtp_base_depayload_flow_return_push_func)
1523 {
1524   State *state;
1525
1526   state = create_depayloader ("application/x-rtp", NULL);
1527
1528   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1529       GST_RTP_DUMMY_USE_PUSH_LIST_FUNC;
1530
1531   set_state (state, GST_STATE_PLAYING);
1532
1533   GST_PAD_SET_FLUSHING (state->sinkpad);
1534
1535   push_rtp_buffer_fails (state, GST_FLOW_FLUSHING,
1536       "pts", 0 * GST_SECOND,
1537       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1538
1539   set_state (state, GST_STATE_NULL);
1540
1541   destroy_depayloader (state);
1542 }
1543
1544 GST_END_TEST;
1545
1546 GST_START_TEST (rtp_base_depayload_flow_return_push_list_func)
1547 {
1548   State *state;
1549
1550   state = create_depayloader ("application/x-rtp", NULL);
1551
1552   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1553       GST_RTP_DUMMY_USE_PUSH_FUNC;
1554
1555   set_state (state, GST_STATE_PLAYING);
1556
1557   GST_PAD_SET_FLUSHING (state->sinkpad);
1558
1559   push_rtp_buffer_fails (state, GST_FLOW_FLUSHING,
1560       "pts", 0 * GST_SECOND,
1561       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1562
1563   set_state (state, GST_STATE_NULL);
1564
1565   destroy_depayloader (state);
1566 }
1567
1568 GST_END_TEST;
1569
1570 GST_START_TEST (rtp_base_depayload_one_byte_hdr_ext)
1571 {
1572   GstRTPHeaderExtension *ext;
1573   State *state;
1574
1575   state = create_depayloader ("application/x-rtp", NULL);
1576   ext = rtp_dummy_hdr_ext_new ();
1577   gst_rtp_header_extension_set_id (ext, 1);
1578
1579   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1580       GST_RTP_DUMMY_RETURN_TO_PUSH;
1581
1582   g_signal_emit_by_name (state->element, "add-extension", ext);
1583
1584   set_state (state, GST_STATE_PLAYING);
1585
1586   push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1587       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1588       NULL);
1589
1590   set_state (state, GST_STATE_NULL);
1591
1592   validate_buffers_received (1);
1593
1594   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1595
1596   fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1597
1598   gst_object_unref (ext);
1599   destroy_depayloader (state);
1600 }
1601
1602 GST_END_TEST;
1603
1604 GST_START_TEST (rtp_base_depayload_two_byte_hdr_ext)
1605 {
1606   GstRTPHeaderExtension *ext;
1607   State *state;
1608
1609   state = create_depayloader ("application/x-rtp", NULL);
1610   ext = rtp_dummy_hdr_ext_new ();
1611   gst_rtp_header_extension_set_id (ext, 1);
1612
1613   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1614       GST_RTP_DUMMY_RETURN_TO_PUSH;
1615
1616   g_signal_emit_by_name (state->element, "add-extension", ext);
1617
1618   set_state (state, GST_STATE_PLAYING);
1619
1620   push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1621       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-2", ext,
1622       NULL);
1623
1624   set_state (state, GST_STATE_NULL);
1625
1626   validate_buffers_received (1);
1627
1628   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1629
1630   fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1631
1632   gst_object_unref (ext);
1633   destroy_depayloader (state);
1634 }
1635
1636 GST_END_TEST;
1637
1638 static GstRTPHeaderExtension *
1639 request_extension (GstRTPBaseDepayload * depayload, guint ext_id,
1640     const gchar * ext_uri, gpointer user_data)
1641 {
1642   GstRTPHeaderExtension *ext = user_data;
1643
1644   if (ext && gst_rtp_header_extension_get_id (ext) == ext_id
1645       && g_strcmp0 (ext_uri, gst_rtp_header_extension_get_uri (ext)) == 0)
1646     return gst_object_ref (ext);
1647
1648   return NULL;
1649 }
1650
1651 GST_START_TEST (rtp_base_depayload_request_extension)
1652 {
1653   GstRTPHeaderExtension *ext;
1654   GstRTPDummyHdrExt *dummy;
1655   State *state;
1656
1657   state =
1658       create_depayloader ("application/x-rtp,extmap-3=(string)"
1659       DUMMY_HDR_EXT_URI, NULL);
1660   ext = rtp_dummy_hdr_ext_new ();
1661   dummy = GST_RTP_DUMMY_HDR_EXT (ext);
1662   gst_rtp_header_extension_set_id (ext, 3);
1663
1664   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1665       GST_RTP_DUMMY_RETURN_TO_PUSH;
1666
1667   g_signal_connect (state->element, "request-extension",
1668       G_CALLBACK (request_extension), ext);
1669
1670   fail_unless (dummy->set_attributes_count == 0);
1671
1672   set_state (state, GST_STATE_PLAYING);
1673
1674   push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1675       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1676       NULL);
1677
1678   set_state (state, GST_STATE_NULL);
1679
1680   validate_buffers_received (1);
1681
1682   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1683
1684   fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1685   fail_unless (dummy->set_attributes_count == 1);
1686
1687   gst_object_unref (ext);
1688   destroy_depayloader (state);
1689 }
1690
1691 GST_END_TEST;
1692
1693 GST_START_TEST (rtp_base_depayload_clear_extensions)
1694 {
1695   GstRTPHeaderExtension *ext;
1696   State *state;
1697
1698   state = create_depayloader ("application/x-rtp", NULL);
1699   ext = rtp_dummy_hdr_ext_new ();
1700   gst_rtp_header_extension_set_id (ext, 1);
1701
1702   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1703       GST_RTP_DUMMY_RETURN_TO_PUSH;
1704
1705   g_signal_emit_by_name (state->element, "add-extension", ext);
1706
1707   set_state (state, GST_STATE_PLAYING);
1708
1709   push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1710       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1711       NULL);
1712
1713   g_signal_emit_by_name (state->element, "clear-extensions");
1714
1715   push_rtp_buffer (state, "pts", 1 * GST_SECOND,
1716       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1717       "seq", 0x4242 + 1, "hdrext-1", ext, NULL);
1718
1719   set_state (state, GST_STATE_NULL);
1720
1721   validate_buffers_received (2);
1722
1723   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1724   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1725
1726   fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1727
1728   gst_object_unref (ext);
1729   destroy_depayloader (state);
1730 }
1731
1732 GST_END_TEST;
1733
1734 GST_START_TEST (rtp_base_depayload_multiple_exts)
1735 {
1736   GstRTPHeaderExtension *ext1;
1737   GstRTPHeaderExtension *ext2;
1738   State *state;
1739
1740   state = create_depayloader ("application/x-rtp", NULL);
1741   ext1 = rtp_dummy_hdr_ext_new ();
1742   gst_rtp_header_extension_set_id (ext1, 1);
1743   ext2 = rtp_dummy_hdr_ext_new ();
1744   gst_rtp_header_extension_set_id (ext2, 2);
1745
1746   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1747       GST_RTP_DUMMY_RETURN_TO_PUSH;
1748
1749   g_signal_emit_by_name (state->element, "add-extension", ext1);
1750   g_signal_emit_by_name (state->element, "add-extension", ext2);
1751
1752   set_state (state, GST_STATE_PLAYING);
1753
1754   push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1755       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext1,
1756       "hdrext-1", ext2, NULL);
1757
1758   set_state (state, GST_STATE_NULL);
1759
1760   validate_buffers_received (1);
1761
1762   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1763
1764   fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext1)->read_count, 1);
1765   fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext2)->read_count, 1);
1766
1767   gst_object_unref (ext1);
1768   gst_object_unref (ext2);
1769   destroy_depayloader (state);
1770 }
1771
1772 GST_END_TEST;
1773
1774 static GstRTPHeaderExtension *
1775 request_extension_ignored (GstRTPBaseDepayload * depayload, guint ext_id,
1776     const gchar * ext_uri, gpointer user_data)
1777 {
1778   guint *request_counter = user_data;
1779
1780   *request_counter += 1;
1781
1782   return NULL;
1783 }
1784
1785 GST_START_TEST (rtp_base_depayload_caps_request_ignored)
1786 {
1787   State *state;
1788   guint request_counter = 0;
1789
1790   state =
1791       create_depayloader ("application/x-rtp,extmap-3=(string)"
1792       DUMMY_HDR_EXT_URI, NULL);
1793
1794   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1795       GST_RTP_DUMMY_RETURN_TO_PUSH;
1796   g_signal_connect (state->element, "request-extension",
1797       G_CALLBACK (request_extension_ignored), &request_counter);
1798
1799   set_state (state, GST_STATE_PLAYING);
1800
1801   push_rtp_buffer (state,
1802       "pts", 0 * GST_SECOND,
1803       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1804
1805   fail_unless_equals_int (request_counter, 1);
1806
1807   set_state (state, GST_STATE_NULL);
1808
1809   validate_buffers_received (1);
1810
1811   destroy_depayloader (state);
1812 }
1813
1814 GST_END_TEST;
1815
1816 static GstFlowReturn
1817 hdr_ext_caps_change_chain_func (GstPad * pad, GstObject * parent,
1818     GstBuffer * buffer)
1819 {
1820   GstFlowReturn res;
1821   GstCaps *caps;
1822   guint val;
1823   static guint expected_caps_val = 0;
1824
1825   res = gst_check_chain_func (pad, parent, buffer);
1826   if (res != GST_FLOW_OK) {
1827     return res;
1828   }
1829
1830   caps = gst_pad_get_current_caps (pad);
1831
1832   fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
1833           "dummy-hdrext-val", &val));
1834
1835   /* Every fifth buffer increments "dummy-hdrext-val". */
1836   if (g_list_length (buffers) % 5 == 1) {
1837     expected_caps_val++;
1838   }
1839
1840   fail_unless_equals_int (expected_caps_val, val);
1841
1842   gst_caps_unref (caps);
1843
1844   return res;
1845 }
1846
1847 GST_START_TEST (rtp_base_depayload_hdr_ext_caps_change)
1848 {
1849   GstRTPHeaderExtension *ext;
1850   State *state;
1851
1852   state = create_depayloader ("application/x-rtp", NULL);
1853   gst_pad_set_chain_function (state->sinkpad, hdr_ext_caps_change_chain_func);
1854
1855   ext = rtp_dummy_hdr_ext_new ();
1856   gst_rtp_header_extension_set_id (ext, 1);
1857
1858   GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1859       GST_RTP_DUMMY_USE_PUSH_LIST_FUNC;
1860   GST_RTP_DUMMY_DEPAY (state->element)->num_buffers_in_blist = 15;
1861
1862   g_signal_emit_by_name (state->element, "add-extension", ext);
1863
1864   set_state (state, GST_STATE_PLAYING);
1865
1866   push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1867       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1868       NULL);
1869
1870   set_state (state, GST_STATE_NULL);
1871
1872   validate_buffers_received (15);
1873
1874   gst_object_unref (ext);
1875   destroy_depayloader (state);
1876 }
1877
1878 GST_END_TEST;
1879
1880 static Suite *
1881 rtp_basepayloading_suite (void)
1882 {
1883   Suite *s = suite_create ("rtp_base_depayloading_test");
1884   TCase *tc_chain = tcase_create ("depayloading tests");
1885
1886   tcase_set_timeout (tc_chain, 60);
1887
1888   suite_add_tcase (s, tc_chain);
1889   tcase_add_test (tc_chain, rtp_base_depayload_buffer_test);
1890
1891   tcase_add_test (tc_chain, rtp_base_depayload_invalid_rtp_packet_test);
1892   tcase_add_test (tc_chain, rtp_base_depayload_with_gap_test);
1893   tcase_add_test (tc_chain, rtp_base_depayload_reversed_test);
1894   tcase_add_test (tc_chain, rtp_base_depayload_ssrc_changed_test);
1895   tcase_add_test (tc_chain, rtp_base_depayload_old_reversed_test);
1896
1897   tcase_add_test (tc_chain, rtp_base_depayload_without_negotiation_test);
1898
1899   tcase_add_test (tc_chain, rtp_base_depayload_packet_lost_test);
1900   tcase_add_test (tc_chain,
1901       rtp_base_depayload_packet_lost_before_first_buffer_test);
1902   tcase_add_test (tc_chain, rtp_base_depayload_seq_discont_test);
1903
1904   tcase_add_test (tc_chain, rtp_base_depayload_repeated_caps_test);
1905   tcase_add_test (tc_chain, rtp_base_depayload_npt_test);
1906   tcase_add_test (tc_chain, rtp_base_depayload_play_scale_test);
1907   tcase_add_test (tc_chain, rtp_base_depayload_play_speed_test);
1908   tcase_add_test (tc_chain, rtp_base_depayload_clock_base_test);
1909
1910   tcase_add_test (tc_chain, rtp_base_depayload_source_info_test);
1911   tcase_add_test (tc_chain, rtp_base_depayload_source_info_from_rtp_only);
1912   tcase_add_test (tc_chain, rtp_base_depayload_max_reorder);
1913
1914   tcase_add_test (tc_chain, rtp_base_depayload_flow_return_push_func);
1915   tcase_add_test (tc_chain, rtp_base_depayload_flow_return_push_list_func);
1916
1917   tcase_add_test (tc_chain, rtp_base_depayload_one_byte_hdr_ext);
1918   tcase_add_test (tc_chain, rtp_base_depayload_two_byte_hdr_ext);
1919   tcase_add_test (tc_chain, rtp_base_depayload_request_extension);
1920   tcase_add_test (tc_chain, rtp_base_depayload_clear_extensions);
1921   tcase_add_test (tc_chain, rtp_base_depayload_multiple_exts);
1922   tcase_add_test (tc_chain, rtp_base_depayload_caps_request_ignored);
1923   tcase_add_test (tc_chain, rtp_base_depayload_hdr_ext_caps_change);
1924
1925   return s;
1926 }
1927
1928 GST_CHECK_MAIN (rtp_basepayloading)