• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
gst_rtp_dummy_depay_class_init(GstRtpDummyDepayClass * klass)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
gst_rtp_dummy_depay_init(GstRtpDummyDepay * depay)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 *
rtp_dummy_depay_new(void)118 rtp_dummy_depay_new (void)
119 {
120   return g_object_new (GST_TYPE_RTP_DUMMY_DEPAY, NULL);
121 }
122 
123 static GstBuffer *
gst_rtp_dummy_depay_process(GstRTPBaseDepayload * depayload,GstBuffer * buf)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
gst_rtp_dummy_depay_set_caps(GstRTPBaseDepayload * filter,GstCaps * caps)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
event_func(GstPad * pad,GstObject * noparent,GstEvent * event)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
drop_events(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
validate_events_received(guint received)239 validate_events_received (guint received)
240 {
241   fail_unless_equals_int (g_list_length (events), received);
242 }
243 
244 static void
validate_event(guint index,const gchar * name,const gchar * field,...)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
rtp_buffer_set_valist(GstBuffer * buf,const gchar * field,va_list var_args,gboolean * extra_ref_)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
rtp_buffer_set(GstBuffer * buf,const gchar * field,...)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
push_rtp_buffer_full(State * state,GstFlowReturn expected,const gchar * field,...)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
push_buffer_full(State * state,GstFlowReturn expected,const gchar * field,...)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
validate_buffers_received(guint received)506 validate_buffers_received (guint received)
507 {
508   fail_unless_equals_int (g_list_length (buffers), received);
509 }
510 
511 static void
validate_buffer(guint index,const gchar * field,...)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 *
create_depayloader(const gchar * caps_str,const gchar * property,...)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
set_state(State * state,GstState new_state)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
packet_lost(State * state,GstClockTime timestamp,GstClockTime duration,gboolean might_have_been_fec)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
reconfigure_caps(State * state,const gchar * caps_str)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
flush_pipeline(State * state)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
destroy_depayloader(State * state)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  */
GST_START_TEST(rtp_base_depayload_buffer_test)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  */
GST_START_TEST(rtp_base_depayload_invalid_rtp_packet_test)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  */
GST_START_TEST(rtp_base_depayload_with_gap_test)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  */
GST_START_TEST(rtp_base_depayload_reversed_test)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  */
GST_START_TEST(rtp_base_depayload_ssrc_changed_test)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  */
GST_START_TEST(rtp_base_depayload_old_reversed_test)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  */
GST_START_TEST(rtp_base_depayload_without_negotiation_test)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  */
GST_START_TEST(rtp_base_depayload_packet_lost_test)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. */
GST_START_TEST(rtp_base_depayload_packet_lost_before_first_buffer_test)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  */
GST_START_TEST(rtp_base_depayload_seq_discont_test)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  */
GST_START_TEST(rtp_base_depayload_repeated_caps_test)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  */
GST_START_TEST(rtp_base_depayload_npt_test)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  */
GST_START_TEST(rtp_base_depayload_play_scale_test)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  */
GST_START_TEST(rtp_base_depayload_play_speed_test)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  */
GST_START_TEST(rtp_base_depayload_clock_base_test)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. */
GST_START_TEST(rtp_base_depayload_source_info_test)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 */
GST_START_TEST(rtp_base_depayload_source_info_from_rtp_only)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. */
GST_START_TEST(rtp_base_depayload_max_reorder)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 
GST_START_TEST(rtp_base_depayload_flow_return_push_func)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 
GST_START_TEST(rtp_base_depayload_flow_return_push_list_func)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 
GST_START_TEST(rtp_base_depayload_one_byte_hdr_ext)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 
GST_START_TEST(rtp_base_depayload_two_byte_hdr_ext)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 *
request_extension(GstRTPBaseDepayload * depayload,guint ext_id,const gchar * ext_uri,gpointer user_data)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 
GST_START_TEST(rtp_base_depayload_request_extension)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 
GST_START_TEST(rtp_base_depayload_clear_extensions)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 
GST_START_TEST(rtp_base_depayload_multiple_exts)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 *
request_extension_ignored(GstRTPBaseDepayload * depayload,guint ext_id,const gchar * ext_uri,gpointer user_data)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 
GST_START_TEST(rtp_base_depayload_caps_request_ignored)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
hdr_ext_caps_change_chain_func(GstPad * pad,GstObject * parent,GstBuffer * buffer)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 
GST_START_TEST(rtp_base_depayload_hdr_ext_caps_change)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 *
rtp_basepayloading_suite(void)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)
1929