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 #define DEFAULT_CLOCK_RATE (42)
30 
31 /* GstRtpDummyDepay */
32 
33 #define GST_TYPE_RTP_DUMMY_DEPAY \
34   (gst_rtp_dummy_depay_get_type())
35 #define GST_RTP_DUMMY_DEPAY(obj) \
36   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepay))
37 #define GST_RTP_DUMMY_DEPAY_CLASS(klass) \
38   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepayClass))
39 #define GST_IS_RTP_DUMMY_DEPAY(obj) \
40   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DUMMY_DEPAY))
41 #define GST_IS_RTP_DUMMY_DEPAY_CLASS(klass) \
42   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DUMMY_DEPAY))
43 
44 typedef struct _GstRtpDummyDepay GstRtpDummyDepay;
45 typedef struct _GstRtpDummyDepayClass GstRtpDummyDepayClass;
46 
47 struct _GstRtpDummyDepay
48 {
49   GstRTPBaseDepayload depayload;
50   guint64 rtptime;
51 };
52 
53 struct _GstRtpDummyDepayClass
54 {
55   GstRTPBaseDepayloadClass parent_class;
56 };
57 
58 GType gst_rtp_dummy_depay_get_type (void);
59 
60 G_DEFINE_TYPE (GstRtpDummyDepay, gst_rtp_dummy_depay,
61     GST_TYPE_RTP_BASE_DEPAYLOAD);
62 
63 static GstBuffer *gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload,
64     GstBuffer * buf);
65 static gboolean gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter,
66     GstCaps * caps);
67 
68 static GstStaticPadTemplate gst_rtp_dummy_depay_sink_template =
69 GST_STATIC_PAD_TEMPLATE ("sink",
70     GST_PAD_SINK,
71     GST_PAD_ALWAYS,
72     GST_STATIC_CAPS_ANY);
73 
74 static GstStaticPadTemplate gst_rtp_dummy_depay_src_template =
75 GST_STATIC_PAD_TEMPLATE ("src",
76     GST_PAD_SRC,
77     GST_PAD_ALWAYS,
78     GST_STATIC_CAPS_ANY);
79 
80 static void
gst_rtp_dummy_depay_class_init(GstRtpDummyDepayClass * klass)81 gst_rtp_dummy_depay_class_init (GstRtpDummyDepayClass * klass)
82 {
83   GstElementClass *gstelement_class;
84   GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
85 
86   gstelement_class = GST_ELEMENT_CLASS (klass);
87   gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
88 
89   gst_element_class_add_static_pad_template (gstelement_class,
90       &gst_rtp_dummy_depay_sink_template);
91   gst_element_class_add_static_pad_template (gstelement_class,
92       &gst_rtp_dummy_depay_src_template);
93 
94   gstrtpbasedepayload_class->process = gst_rtp_dummy_depay_process;
95   gstrtpbasedepayload_class->set_caps = gst_rtp_dummy_depay_set_caps;
96 }
97 
98 static void
gst_rtp_dummy_depay_init(GstRtpDummyDepay * depay)99 gst_rtp_dummy_depay_init (GstRtpDummyDepay * depay)
100 {
101   depay->rtptime = 0;
102 }
103 
104 static GstRtpDummyDepay *
rtp_dummy_depay_new(void)105 rtp_dummy_depay_new (void)
106 {
107   return g_object_new (GST_TYPE_RTP_DUMMY_DEPAY, NULL);
108 }
109 
110 static GstBuffer *
gst_rtp_dummy_depay_process(GstRTPBaseDepayload * depayload,GstBuffer * buf)111 gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
112 {
113   GstRTPBuffer rtp = { NULL };
114   GstBuffer *outbuf;
115   guint32 rtptime;
116   guint i;
117 
118   GST_LOG ("depayloading buffer pts=%" GST_TIME_FORMAT " offset=%"
119       G_GUINT64_FORMAT " memories=%d", GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
120       GST_BUFFER_OFFSET (buf), gst_buffer_n_memory (buf));
121 
122   for (i = 0; i < gst_buffer_n_memory (buf); i++) {
123     GstMemory *mem = gst_buffer_get_memory (buf, 0);
124     gsize size, offset, maxsize;
125     size = gst_memory_get_sizes (mem, &offset, &maxsize);
126     GST_LOG ("\tsize=%" G_GSIZE_FORMAT " offset=%" G_GSIZE_FORMAT " maxsize=%"
127         G_GSIZE_FORMAT, size, offset, maxsize);
128     gst_memory_unref (mem);
129   }
130 
131   gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
132   outbuf = gst_rtp_buffer_get_payload_buffer (&rtp);
133   rtptime = gst_rtp_buffer_get_timestamp (&rtp);
134   gst_rtp_buffer_unmap (&rtp);
135 
136   GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
137   GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
138 
139   GST_LOG ("depayloaded buffer pts=%" GST_TIME_FORMAT " offset=%"
140       G_GUINT64_FORMAT " rtptime=%" G_GUINT32_FORMAT " memories=%d",
141       GST_TIME_ARGS (GST_BUFFER_PTS (outbuf)),
142       GST_BUFFER_OFFSET (outbuf), rtptime, gst_buffer_n_memory (buf));
143 
144   for (i = 0; i < gst_buffer_n_memory (buf); i++) {
145     GstMemory *mem = gst_buffer_get_memory (buf, 0);
146     gsize size, offset, maxsize;
147     size = gst_memory_get_sizes (mem, &offset, &maxsize);
148     GST_LOG ("\tsize=%" G_GSIZE_FORMAT " offset=%" G_GSIZE_FORMAT " maxsize=%"
149         G_GSIZE_FORMAT, size, offset, maxsize);
150     gst_memory_unref (mem);
151   }
152 
153   return outbuf;
154 }
155 
156 static gboolean
gst_rtp_dummy_depay_set_caps(GstRTPBaseDepayload * filter,GstCaps * caps)157 gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter, GstCaps * caps)
158 {
159   GstEvent *event;
160   event = gst_event_new_caps (caps);
161   gst_pad_push_event (filter->srcpad, event);
162   return TRUE;
163 }
164 
165 /* Helper functions and global state */
166 
167 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
168     GST_PAD_SRC,
169     GST_PAD_ALWAYS,
170     GST_STATIC_CAPS_ANY);
171 
172 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
173     GST_PAD_SINK,
174     GST_PAD_ALWAYS,
175     GST_STATIC_CAPS_ANY);
176 
177 typedef struct State State;
178 
179 struct State
180 {
181   GstElement *element;
182   GstPad *sinkpad;
183   GstPad *srcpad;
184 };
185 
186 static GList *events;
187 
188 static gboolean
event_func(GstPad * pad,GstObject * noparent,GstEvent * event)189 event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
190 {
191   events = g_list_append (events, gst_event_ref (event));
192   return gst_pad_event_default (pad, noparent, event);
193 }
194 
195 static void
drop_events(void)196 drop_events (void)
197 {
198   while (events != NULL) {
199     gst_event_unref (GST_EVENT (events->data));
200     events = g_list_delete_link (events, events);
201   }
202 }
203 
204 static void
validate_events_received(guint received)205 validate_events_received (guint received)
206 {
207   fail_unless_equals_int (g_list_length (events), received);
208 }
209 
210 static void
validate_event(guint index,const gchar * name,const gchar * field,...)211 validate_event (guint index, const gchar * name, const gchar * field, ...)
212 {
213   GstEvent *event;
214   va_list var_args;
215 
216   fail_if (index >= g_list_length (events));
217   event = GST_EVENT (g_list_nth_data (events, index));
218   fail_if (event == NULL);
219 
220   GST_TRACE ("%" GST_PTR_FORMAT, event);
221 
222   fail_unless_equals_string (GST_EVENT_TYPE_NAME (event), name);
223 
224   va_start (var_args, field);
225   while (field) {
226     if (!g_strcmp0 (field, "timestamp")) {
227       GstClockTime expected = va_arg (var_args, GstClockTime);
228       GstClockTime timestamp, duration;
229       gst_event_parse_gap (event, &timestamp, &duration);
230       fail_unless_equals_uint64 (timestamp, expected);
231     } else if (!g_strcmp0 (field, "duration")) {
232       GstClockTime expected = va_arg (var_args, GstClockTime);
233       GstClockTime timestamp, duration;
234       gst_event_parse_gap (event, &timestamp, &duration);
235       fail_unless_equals_uint64 (duration, expected);
236     } else if (!g_strcmp0 (field, "time")) {
237       GstClockTime expected = va_arg (var_args, GstClockTime);
238       const GstSegment *segment;
239       gst_event_parse_segment (event, &segment);
240       fail_unless_equals_uint64 (segment->time, expected);
241     } else if (!g_strcmp0 (field, "start")) {
242       GstClockTime expected = va_arg (var_args, GstClockTime);
243       const GstSegment *segment;
244       gst_event_parse_segment (event, &segment);
245       fail_unless_equals_uint64 (segment->start, expected);
246     } else if (!g_strcmp0 (field, "stop")) {
247       GstClockTime expected = va_arg (var_args, GstClockTime);
248       const GstSegment *segment;
249       gst_event_parse_segment (event, &segment);
250       fail_unless_equals_uint64 (segment->stop, expected);
251     } else if (!g_strcmp0 (field, "applied-rate")) {
252       gdouble expected = va_arg (var_args, gdouble);
253       const GstSegment *segment;
254       gst_event_parse_segment (event, &segment);
255       fail_unless_equals_uint64 (segment->applied_rate, expected);
256     } else if (!g_strcmp0 (field, "rate")) {
257       gdouble expected = va_arg (var_args, gdouble);
258       const GstSegment *segment;
259       gst_event_parse_segment (event, &segment);
260       fail_unless_equals_uint64 (segment->rate, expected);
261     } else if (!g_strcmp0 (field, "base")) {
262       GstClockTime expected = va_arg (var_args, GstClockTime);
263       const GstSegment *segment;
264       gst_event_parse_segment (event, &segment);
265       fail_unless_equals_uint64 (segment->base, expected);
266     } else if (!g_strcmp0 (field, "media-type")) {
267       const gchar *expected = va_arg (var_args, const gchar *);
268       GstCaps *caps;
269       const gchar *media_type;
270       gst_event_parse_caps (event, &caps);
271       media_type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
272       fail_unless_equals_string (media_type, expected);
273     } else if (!g_strcmp0 (field, "npt-start")) {
274       GstClockTime expected = va_arg (var_args, GstClockTime);
275       GstCaps *caps;
276       GstClockTime start;
277       gst_event_parse_caps (event, &caps);
278       fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
279                   0), "npt-start", &start));
280       fail_unless_equals_uint64 (start, expected);
281     } else if (!g_strcmp0 (field, "npt-stop")) {
282       GstClockTime expected = va_arg (var_args, GstClockTime);
283       GstCaps *caps;
284       GstClockTime stop;
285       gst_event_parse_caps (event, &caps);
286       fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
287                   0), "npt-stop", &stop));
288       fail_unless_equals_uint64 (stop, expected);
289     } else if (!g_strcmp0 (field, "play-speed")) {
290       gdouble expected = va_arg (var_args, gdouble);
291       GstCaps *caps;
292       gdouble speed;
293       gst_event_parse_caps (event, &caps);
294       fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
295               "play-speed", &speed));
296       fail_unless (speed == expected);
297     } else if (!g_strcmp0 (field, "play-scale")) {
298       gdouble expected = va_arg (var_args, gdouble);
299       GstCaps *caps;
300       gdouble scale;
301       gst_event_parse_caps (event, &caps);
302       fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
303               "play-scale", &scale));
304       fail_unless (scale == expected);
305     } else if (!g_strcmp0 (field, "clock-base")) {
306       guint expected = va_arg (var_args, guint);
307       GstCaps *caps;
308       guint clock_base;
309       gst_event_parse_caps (event, &caps);
310       fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
311               "clock-base", &clock_base));
312       fail_unless (clock_base == expected);
313 
314     } else {
315       fail ("test cannot validate unknown event field '%s'", field);
316     }
317     field = va_arg (var_args, const gchar *);
318   }
319   va_end (var_args);
320 }
321 
322 static void
rtp_buffer_set_valist(GstBuffer * buf,const gchar * field,va_list var_args,gboolean * extra_ref_)323 rtp_buffer_set_valist (GstBuffer * buf, const gchar * field, va_list var_args,
324     gboolean * extra_ref_)
325 {
326   GstRTPBuffer rtp = { NULL };
327   gboolean mapped = FALSE;
328   gboolean extra_ref = FALSE;
329 
330   while (field) {
331     if (!g_strcmp0 (field, "pts")) {
332       GstClockTime pts = va_arg (var_args, GstClockTime);
333       GST_BUFFER_PTS (buf) = pts;
334     } else if (!g_strcmp0 (field, "offset")) {
335       guint64 offset = va_arg (var_args, guint64);
336       GST_BUFFER_OFFSET (buf) = offset;
337     } else if (!g_strcmp0 (field, "discont")) {
338       gboolean discont = va_arg (var_args, gboolean);
339       if (discont) {
340         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
341       } else {
342         GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
343       }
344     } else {
345       if (!mapped) {
346         gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
347         mapped = TRUE;
348       }
349       if (!g_strcmp0 (field, "rtptime")) {
350         guint32 rtptime = va_arg (var_args, guint64);
351         gst_rtp_buffer_set_timestamp (&rtp, rtptime);
352       } else if (!g_strcmp0 (field, "payload-type")) {
353         guint payload_type = va_arg (var_args, guint);
354         gst_rtp_buffer_set_payload_type (&rtp, payload_type);
355       } else if (!g_strcmp0 (field, "seq")) {
356         guint seq = va_arg (var_args, guint);
357         gst_rtp_buffer_set_seq (&rtp, seq);
358       } else if (!g_strcmp0 (field, "ssrc")) {
359         guint32 ssrc = va_arg (var_args, guint);
360         gst_rtp_buffer_set_ssrc (&rtp, ssrc);
361       } else if (!g_strcmp0 (field, "extra-ref")) {
362         extra_ref = va_arg (var_args, gboolean);
363         if (extra_ref_)
364           *extra_ref_ = extra_ref;
365       } else if (!g_strcmp0 (field, "csrc")) {
366         guint idx = va_arg (var_args, guint);
367         guint csrc = va_arg (var_args, guint);
368         gst_rtp_buffer_set_csrc (&rtp, idx, csrc);
369       } else {
370         fail ("test cannot set unknown buffer field '%s'", field);
371       }
372     }
373     field = va_arg (var_args, const gchar *);
374   }
375 
376   if (mapped) {
377     gst_rtp_buffer_unmap (&rtp);
378   }
379 
380   if (extra_ref)
381     gst_buffer_ref (buf);
382 }
383 
384 static void
rtp_buffer_set(GstBuffer * buf,const gchar * field,...)385 rtp_buffer_set (GstBuffer * buf, const gchar * field, ...)
386 {
387   va_list var_args;
388 
389   va_start (var_args, field);
390   rtp_buffer_set_valist (buf, field, var_args, NULL);
391   va_end (var_args);
392 }
393 
394 #define push_rtp_buffer(state, field, ...) \
395     push_rtp_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
396 #define push_rtp_buffer_fails(state, error, field, ...) \
397     push_rtp_buffer_full ((state), (error), (field), __VA_ARGS__)
398 
399 static void
push_rtp_buffer_full(State * state,GstFlowReturn expected,const gchar * field,...)400 push_rtp_buffer_full (State * state, GstFlowReturn expected,
401     const gchar * field, ...)
402 {
403   GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
404   va_list var_args;
405   gboolean extra_ref = FALSE;
406 
407   va_start (var_args, field);
408   rtp_buffer_set_valist (buf, field, var_args, &extra_ref);
409   va_end (var_args);
410 
411   fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
412 
413   if (extra_ref)
414     gst_buffer_unref (buf);
415 }
416 
417 #define push_buffer(state, field, ...) \
418     push_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
419 
420 static void
push_buffer_full(State * state,GstFlowReturn expected,const gchar * field,...)421 push_buffer_full (State * state, GstFlowReturn expected,
422     const gchar * field, ...)
423 {
424   GstBuffer *buf = gst_buffer_new_allocate (0, 0, 0);
425   va_list var_args;
426 
427   va_start (var_args, field);
428   while (field) {
429     if (!g_strcmp0 (field, "pts")) {
430       GstClockTime pts = va_arg (var_args, GstClockTime);
431       GST_BUFFER_PTS (buf) = pts;
432     } else if (!g_strcmp0 (field, "offset")) {
433       guint64 offset = va_arg (var_args, guint64);
434       GST_BUFFER_OFFSET (buf) = offset;
435     } else if (!g_strcmp0 (field, "discont")) {
436       gboolean discont = va_arg (var_args, gboolean);
437       if (discont) {
438         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
439       } else {
440         GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
441       }
442     } else {
443       fail ("test cannot set unknown buffer field '%s'", field);
444     }
445     field = va_arg (var_args, const gchar *);
446   }
447   va_end (var_args);
448 
449   fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
450 }
451 
452 static void
validate_buffers_received(guint received)453 validate_buffers_received (guint received)
454 {
455   fail_unless_equals_int (g_list_length (buffers), received);
456 }
457 
458 static void
validate_buffer(guint index,const gchar * field,...)459 validate_buffer (guint index, const gchar * field, ...)
460 {
461   GstBuffer *buf;
462   va_list var_args;
463 
464   fail_if (index >= g_list_length (buffers));
465   buf = GST_BUFFER (g_list_nth_data (buffers, (index)));
466   fail_if (buf == NULL);
467 
468   GST_TRACE ("%" GST_PTR_FORMAT, buf);
469 
470   va_start (var_args, field);
471   while (field) {
472     if (!g_strcmp0 (field, "pts")) {
473       GstClockTime pts = va_arg (var_args, GstClockTime);
474       fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), pts);
475     } else if (!g_strcmp0 (field, "offset")) {
476       guint64 offset = va_arg (var_args, guint64);
477       fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buf), offset);
478     } else if (!g_strcmp0 (field, "discont")) {
479       gboolean discont = va_arg (var_args, gboolean);
480       if (discont) {
481         fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
482       } else {
483         fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
484       }
485     } else {
486       fail ("test cannot validate unknown buffer field '%s'", field);
487     }
488     field = va_arg (var_args, const gchar *);
489   }
490   va_end (var_args);
491 }
492 
493 static State *
create_depayloader(const gchar * caps_str,const gchar * property,...)494 create_depayloader (const gchar * caps_str, const gchar * property, ...)
495 {
496   va_list var_args;
497   GstCaps *caps;
498   State *state;
499 
500   state = g_new0 (State, 1);
501 
502   state->element = GST_ELEMENT (rtp_dummy_depay_new ());
503   fail_unless (GST_IS_RTP_DUMMY_DEPAY (state->element));
504 
505   va_start (var_args, property);
506   g_object_set_valist (G_OBJECT (state->element), property, var_args);
507   va_end (var_args);
508 
509   state->srcpad = gst_check_setup_src_pad (state->element, &srctemplate);
510   state->sinkpad = gst_check_setup_sink_pad (state->element, &sinktemplate);
511 
512   fail_unless (gst_pad_set_active (state->srcpad, TRUE));
513   fail_unless (gst_pad_set_active (state->sinkpad, TRUE));
514 
515   if (caps_str) {
516     caps = gst_caps_from_string (caps_str);
517   } else {
518     caps = NULL;
519   }
520   gst_check_setup_events (state->srcpad, state->element, caps, GST_FORMAT_TIME);
521   if (caps) {
522     gst_caps_unref (caps);
523   }
524 
525   gst_pad_set_chain_function (state->sinkpad, gst_check_chain_func);
526   gst_pad_set_event_function (state->sinkpad, event_func);
527 
528   return state;
529 }
530 
531 static void
set_state(State * state,GstState new_state)532 set_state (State * state, GstState new_state)
533 {
534   fail_unless_equals_int (gst_element_set_state (state->element, new_state),
535       GST_STATE_CHANGE_SUCCESS);
536 }
537 
538 static void
packet_lost(State * state,GstClockTime timestamp,GstClockTime duration,gboolean might_have_been_fec)539 packet_lost (State * state, GstClockTime timestamp, GstClockTime duration,
540     gboolean might_have_been_fec)
541 {
542   GstEvent *event;
543   guint seqnum = 0x4243;
544   gboolean late = TRUE;
545   guint retries = 42;
546 
547   event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
548       gst_structure_new ("GstRTPPacketLost",
549           "seqnum", G_TYPE_UINT, seqnum,
550           "timestamp", G_TYPE_UINT64, timestamp,
551           "duration", G_TYPE_UINT64, duration,
552           "might-have-been-fec", G_TYPE_BOOLEAN, might_have_been_fec,
553           "late", G_TYPE_BOOLEAN, late, "retry", G_TYPE_UINT, retries, NULL));
554 
555   fail_unless (gst_pad_push_event (state->srcpad, event));
556 }
557 
558 static void
reconfigure_caps(State * state,const gchar * caps_str)559 reconfigure_caps (State * state, const gchar * caps_str)
560 {
561   GstCaps *newcaps;
562   GstEvent *event;
563   newcaps = gst_caps_from_string (caps_str);
564   event = gst_event_new_caps (newcaps);
565   gst_caps_unref (newcaps);
566   fail_unless (gst_pad_push_event (state->srcpad, event));
567 }
568 
569 static void
flush_pipeline(State * state)570 flush_pipeline (State * state)
571 {
572   GstEvent *event;
573   GstSegment segment;
574   event = gst_event_new_flush_start ();
575   fail_unless (gst_pad_push_event (state->srcpad, event));
576   event = gst_event_new_flush_stop (TRUE);
577   fail_unless (gst_pad_push_event (state->srcpad, event));
578   gst_segment_init (&segment, GST_FORMAT_TIME);
579   event = gst_event_new_segment (&segment);
580   fail_unless (gst_pad_push_event (state->srcpad, event));
581 }
582 
583 static void
destroy_depayloader(State * state)584 destroy_depayloader (State * state)
585 {
586   gst_check_teardown_sink_pad (state->element);
587   gst_check_teardown_src_pad (state->element);
588 
589   gst_check_drop_buffers ();
590   drop_events ();
591 
592   g_object_unref (state->element);
593 
594   g_free (state);
595 }
596 
597 /* Tests */
598 
599 /* send two RTP packets having sequential sequence numbers and timestamps
600  * differing by DEFAULT_CLOCK_RATE. the depayloader first pushes the normal
601  * stream-start, caps and segment events downstream before processing each RTP
602  * packet and pushing a corresponding buffer. PTS will be carried over from the
603  * RTP packets by the payloader to the buffers. because the sequence numbers are
604  * sequential then GST_BUFFER_FLAG_DISCONT will not be set for either buffer.
605  */
GST_START_TEST(rtp_base_depayload_buffer_test)606 GST_START_TEST (rtp_base_depayload_buffer_test)
607 {
608   State *state;
609 
610   state = create_depayloader ("application/x-rtp", NULL);
611 
612   set_state (state, GST_STATE_PLAYING);
613 
614   push_rtp_buffer (state,
615       "pts", 0 * GST_SECOND,
616       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
617 
618   push_rtp_buffer (state,
619       "pts", 1 * GST_SECOND,
620       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
621       "seq", 0x4242 + 1, NULL);
622 
623   set_state (state, GST_STATE_NULL);
624 
625   validate_buffers_received (2);
626 
627   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
628 
629   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
630 
631   validate_events_received (3);
632 
633   validate_event (0, "stream-start", NULL);
634 
635   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
636 
637   validate_event (2, "segment",
638       "time", G_GUINT64_CONSTANT (0),
639       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
640 
641   destroy_depayloader (state);
642 }
643 
644 GST_END_TEST
645 /* the intent with this test is to provide the depayloader with a buffer that
646  * does not contain an RTP header. this makes it impossible for the depayloader
647  * to depayload the incoming RTP packet, yet the stream-start and caps events
648  * will still be pushed.
649  */
GST_START_TEST(rtp_base_depayload_invalid_rtp_packet_test)650 GST_START_TEST (rtp_base_depayload_invalid_rtp_packet_test)
651 {
652   State *state;
653 
654   state = create_depayloader ("application/x-rtp", NULL);
655 
656   set_state (state, GST_STATE_PLAYING);
657 
658   push_buffer (state,
659       "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
660 
661   set_state (state, GST_STATE_NULL);
662 
663   validate_buffers_received (0);
664 
665   validate_events_received (2);
666 
667   validate_event (0, "stream-start", NULL);
668 
669   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
670 
671   destroy_depayloader (state);
672 }
673 
674 GST_END_TEST
675 /* validate what happens when a depayloader is provided with two RTP packets
676  * sent after each other that do not have sequential sequence numbers. in this
677  * case the depayloader should be able to depayload both first and the second
678  * buffer, but the second buffer will have GST_BUFFER_FLAG_DISCONT set to
679  * indicate that the was a discontinuity in the stream. the initial events are
680  * pushed prior to the buffers arriving so they should be unaffected by the gap
681  * in sequence numbers.
682  */
GST_START_TEST(rtp_base_depayload_with_gap_test)683 GST_START_TEST (rtp_base_depayload_with_gap_test)
684 {
685   State *state;
686 
687   state = create_depayloader ("application/x-rtp", NULL);
688 
689   set_state (state, GST_STATE_PLAYING);
690 
691   push_rtp_buffer (state,
692       "pts", 0 * GST_SECOND,
693       "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
694 
695   push_rtp_buffer (state,
696       "pts", 1 * GST_SECOND,
697       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
698       "seq", 0x4242 + 2, NULL);
699 
700   set_state (state, GST_STATE_NULL);
701 
702   validate_buffers_received (2);
703 
704   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
705 
706   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
707 
708   validate_events_received (3);
709 
710   validate_event (0, "stream-start", NULL);
711 
712   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
713 
714   validate_event (2, "segment",
715       "time", G_GUINT64_CONSTANT (0),
716       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
717 
718   destroy_depayloader (state);
719 }
720 
721 GST_END_TEST
722 /* two RTP packets are pushed in this test, and while the sequence numbers are
723  * sequential they are reversed. the expectation is that the depayloader will be
724  * able to depayload the first RTP packet, but once the second RTP packet
725  * arrives it will be discarded because it arrived too late. the initial events
726  * should be unaffected by the reversed buffers.
727  */
GST_START_TEST(rtp_base_depayload_reversed_test)728 GST_START_TEST (rtp_base_depayload_reversed_test)
729 {
730   State *state;
731 
732   state = create_depayloader ("application/x-rtp", NULL);
733 
734   set_state (state, GST_STATE_PLAYING);
735 
736   push_rtp_buffer (state,
737       "pts", 0 * GST_SECOND,
738       "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
739 
740   push_rtp_buffer (state,
741       "pts", 1 * GST_SECOND,
742       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
743       "seq", 0x4242 - 1, NULL);
744 
745   set_state (state, GST_STATE_NULL);
746 
747   validate_buffers_received (1);
748 
749   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
750 
751   validate_events_received (3);
752 
753   validate_event (0, "stream-start", NULL);
754 
755   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
756 
757   validate_event (2, "segment",
758       "time", G_GUINT64_CONSTANT (0),
759       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
760 
761   destroy_depayloader (state);
762 }
763 
764 GST_END_TEST
765 /* The same scenario as in rtp_base_depayload_reversed_test
766  * except that SSRC is changed for the 2nd packet that is why
767  * it should not be discarded.
768  */
GST_START_TEST(rtp_base_depayload_ssrc_changed_test)769 GST_START_TEST (rtp_base_depayload_ssrc_changed_test)
770 {
771   State *state;
772 
773   state = create_depayloader ("application/x-rtp", NULL);
774 
775   set_state (state, GST_STATE_PLAYING);
776 
777   push_rtp_buffer (state,
778       "pts", 0 * GST_SECOND,
779       "rtptime", G_GUINT64_CONSTANT (0x43214321),
780       "seq", 0x4242, "ssrc", 0xabe2b0b, NULL);
781 
782   push_rtp_buffer (state,
783       "pts", 1 * GST_SECOND,
784       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
785       "seq", 0x4242 - 1, "ssrc", 0xcafebabe, NULL);
786 
787   set_state (state, GST_STATE_NULL);
788 
789   validate_buffers_received (2);
790 
791   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
792 
793   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
794 
795   validate_events_received (3);
796 
797   validate_event (0, "stream-start", NULL);
798 
799   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
800 
801   validate_event (2, "segment",
802       "time", G_GUINT64_CONSTANT (0),
803       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
804 
805   destroy_depayloader (state);
806 }
807 
808 GST_END_TEST
809 /* the intent of this test is to push two RTP packets that have reverse sequence
810  * numbers that differ significantly. the depayloader will consider RTP packets
811  * where the sequence numbers differ by more than 1000 to indicate that the
812  * source of the RTP packets has been restarted. therefore it will let both
813  * depayloaded buffers through, but the latter buffer marked
814  * GST_BUFFER_FLAG_DISCONT to indicate the discontinuity in the stream. the
815  * initial events should be unaffected by the reversed buffers.
816  */
GST_START_TEST(rtp_base_depayload_old_reversed_test)817 GST_START_TEST (rtp_base_depayload_old_reversed_test)
818 {
819   State *state;
820 
821   state = create_depayloader ("application/x-rtp", NULL);
822 
823   set_state (state, GST_STATE_PLAYING);
824 
825   push_rtp_buffer (state,
826       "pts", 0 * GST_SECOND,
827       "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
828 
829   push_rtp_buffer (state,
830       "pts", 1 * GST_SECOND,
831       "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
832       "seq", 0x4242 - 1000, NULL);
833 
834   set_state (state, GST_STATE_NULL);
835 
836   validate_buffers_received (2);
837 
838   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
839 
840   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
841 
842   validate_events_received (3);
843 
844   validate_event (0, "stream-start", NULL);
845 
846   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
847 
848   validate_event (2, "segment",
849       "time", G_GUINT64_CONSTANT (0),
850       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
851 
852   destroy_depayloader (state);
853 }
854 
855 GST_END_TEST
856 /* a depayloader that has not received any caps event will not be able to
857  * process any incoming RTP packet. instead pushing an RTP packet should result
858  * in the expected error.
859  */
GST_START_TEST(rtp_base_depayload_without_negotiation_test)860 GST_START_TEST (rtp_base_depayload_without_negotiation_test)
861 {
862   State *state;
863 
864   state = create_depayloader (NULL, NULL);
865 
866   set_state (state, GST_STATE_PLAYING);
867 
868   push_rtp_buffer_fails (state, GST_FLOW_NOT_NEGOTIATED,
869       "pts", 0 * GST_SECOND,
870       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
871 
872   set_state (state, GST_STATE_NULL);
873 
874   validate_buffers_received (0);
875 
876   validate_events_received (1);
877 
878   validate_event (0, "stream-start", NULL);
879 
880   destroy_depayloader (state);
881 }
882 
883 GST_END_TEST
884 /* a depayloader that receives the downstream event GstRTPPacketLost should
885  * respond by emitting a gap event with the corresponding timestamp and
886  * duration. the initial events are unaffected, but are succeeded by the added
887  * gap event.
888  */
GST_START_TEST(rtp_base_depayload_packet_lost_test)889 GST_START_TEST (rtp_base_depayload_packet_lost_test)
890 {
891   State *state;
892 
893   state = create_depayloader ("application/x-rtp", NULL);
894 
895   set_state (state, GST_STATE_PLAYING);
896 
897   push_rtp_buffer (state,
898       "pts", 0 * GST_SECOND,
899       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
900 
901   packet_lost (state, 1 * GST_SECOND, GST_SECOND, FALSE);
902 
903   /* If a packet was lost but we don't know whether it was a FEC packet,
904    * the depayloader should not generate gap events */
905   packet_lost (state, 2 * GST_SECOND, GST_SECOND, TRUE);
906 
907   push_rtp_buffer (state,
908       "pts", 2 * GST_SECOND,
909       "rtptime", G_GUINT64_CONSTANT (0x1234) + 2 * DEFAULT_CLOCK_RATE,
910       "seq", 0x4242 + 2, NULL);
911 
912   set_state (state, GST_STATE_NULL);
913 
914   validate_buffers_received (2);
915 
916   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
917 
918   validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
919 
920   validate_events_received (4);
921 
922   validate_event (0, "stream-start", NULL);
923 
924   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
925 
926   validate_event (2, "segment",
927       "time", G_GUINT64_CONSTANT (0),
928       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
929 
930   validate_event (3, "gap",
931       "timestamp", 1 * GST_SECOND, "duration", GST_SECOND, NULL);
932 
933   destroy_depayloader (state);
934 }
935 
936 GST_END_TEST
937 /* If a lost event is received before the first buffer, the rtp base
938  * depayloader will not send a gap event downstream. Alternatively it should
939  * make sure that stream-start, caps and segment events are sent in correct
940  * order before the gap event so that packet loss concealment can take place
941  * downstream, but this is more complicated and without any real benefit since
942  * concealment before any data is received is not very useful. */
GST_START_TEST(rtp_base_depayload_packet_lost_before_first_buffer_test)943 GST_START_TEST (rtp_base_depayload_packet_lost_before_first_buffer_test)
944 {
945   GstHarness *h;
946   GstEvent *event;
947   GstRtpDummyDepay *depay;
948   const GstEventType etype[] = {
949     GST_EVENT_STREAM_START, GST_EVENT_CAPS, GST_EVENT_SEGMENT
950   };
951   gint i;
952 
953   depay = rtp_dummy_depay_new ();
954   h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
955   gst_harness_set_src_caps_str (h, "application/x-rtp");
956 
957   /* Verify that depayloader has received setup events */
958   for (i = 0; i < 3; i++) {
959     event = gst_pad_get_sticky_event (h->srcpad, etype[i], 0);
960     fail_unless (event != NULL);
961     gst_event_unref (event);
962   }
963 
964   /* Send loss event to depayloader */
965   gst_harness_push_event (h, gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
966           gst_structure_new ("GstRTPPacketLost",
967               "seqnum", G_TYPE_UINT, (guint) 0,
968               "timestamp", G_TYPE_UINT64, (guint64) 0,
969               "duration", G_TYPE_UINT64, (guint64) 10 * GST_MSECOND, NULL)));
970 
971   /* When a buffer is pushed, an updated (and more accurate) segment event
972    * should aslo be sent. */
973   gst_harness_push (h, gst_rtp_buffer_new_allocate (0, 0, 0));
974 
975   /* Verify that setup events are sent before gap event */
976   for (i = 0; i < 3; i++) {
977     fail_unless (event = gst_harness_pull_event (h));
978     fail_unless_equals_int (GST_EVENT_TYPE (event), etype[i]);
979     gst_event_unref (event);
980   }
981   fail_unless_equals_int (gst_harness_events_in_queue (h), 0);
982 
983   gst_buffer_unref (gst_harness_pull (h));
984   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
985 
986   g_object_unref (depay);
987   gst_harness_teardown (h);
988 }
989 
990 GST_END_TEST;
991 /* rtp base depayloader should set DISCONT flag on buffer in case of a large
992  * sequence number gap, and it's not set already by upstream. This tests a
993  * certain code path where the buffer needs to be made writable to set the
994  * DISCONT flag.
995  */
GST_START_TEST(rtp_base_depayload_seq_discont_test)996 GST_START_TEST (rtp_base_depayload_seq_discont_test)
997 {
998   State *state;
999 
1000   state = create_depayloader ("application/x-rtp", NULL);
1001 
1002   set_state (state, GST_STATE_PLAYING);
1003 
1004   push_rtp_buffer (state,
1005       "pts", 0 * GST_SECOND,
1006       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 1, NULL);
1007 
1008   push_rtp_buffer (state,
1009       "extra-ref", TRUE,
1010       "pts", 2 * GST_SECOND,
1011       "rtptime", G_GUINT64_CONSTANT (0x1234) + DEFAULT_CLOCK_RATE / 2,
1012       "seq", 33333, NULL);
1013 
1014   set_state (state, GST_STATE_NULL);
1015 
1016   validate_buffers_received (2);
1017 
1018   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1019 
1020   validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
1021 
1022   destroy_depayloader (state);
1023 }
1024 
1025 GST_END_TEST
1026 /* a depayloader that receives identical caps events simply ignores the latter
1027  * events without propagating them downstream.
1028  */
GST_START_TEST(rtp_base_depayload_repeated_caps_test)1029 GST_START_TEST (rtp_base_depayload_repeated_caps_test)
1030 {
1031   State *state;
1032 
1033   state = create_depayloader ("application/x-rtp", NULL);
1034 
1035   set_state (state, GST_STATE_PLAYING);
1036 
1037   push_rtp_buffer (state,
1038       "pts", 0 * GST_SECOND,
1039       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1040 
1041   reconfigure_caps (state, "application/x-rtp");
1042 
1043   push_rtp_buffer (state,
1044       "pts", 1 * GST_SECOND,
1045       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1046       "seq", 0x4242 + 1, NULL);
1047 
1048   set_state (state, GST_STATE_NULL);
1049 
1050   validate_buffers_received (2);
1051 
1052   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1053 
1054   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1055 
1056   validate_events_received (3);
1057 
1058   validate_event (0, "stream-start", NULL);
1059 
1060   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1061 
1062   validate_event (2, "segment",
1063       "time", G_GUINT64_CONSTANT (0),
1064       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1065 
1066   destroy_depayloader (state);
1067 }
1068 
1069 GST_END_TEST
1070 /* when a depayloader receives new caps events with npt-start and npt-stop times
1071  * it should save these timestamps as they should affect the next segment event
1072  * being pushed by the depayloader. a new segment event is not pushed by the
1073  * depayloader until a flush_stop event and a succeeding segment event are
1074  * received. of course the intial event are unaffected, as is the incoming caps
1075  * event.
1076  */
GST_START_TEST(rtp_base_depayload_npt_test)1077 GST_START_TEST (rtp_base_depayload_npt_test)
1078 {
1079   State *state;
1080 
1081   state = create_depayloader ("application/x-rtp", NULL);
1082 
1083   set_state (state, GST_STATE_PLAYING);
1084 
1085   push_rtp_buffer (state,
1086       "pts", 0 * GST_SECOND,
1087       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1088 
1089   reconfigure_caps (state,
1090       "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321");
1091 
1092   flush_pipeline (state);
1093 
1094   push_rtp_buffer (state,
1095       "pts", 1 * GST_SECOND,
1096       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1097       "seq", 0x4242 + 1, NULL);
1098 
1099   set_state (state, GST_STATE_NULL);
1100 
1101   validate_buffers_received (2);
1102 
1103   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1104 
1105   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1106 
1107   validate_events_received (7);
1108 
1109   validate_event (0, "stream-start", NULL);
1110 
1111   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1112 
1113   validate_event (2, "segment",
1114       "time", G_GUINT64_CONSTANT (0),
1115       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1116 
1117   validate_event (3, "caps",
1118       "media-type", "application/x-rtp",
1119       "npt-start", G_GUINT64_CONSTANT (1234),
1120       "npt-stop", G_GUINT64_CONSTANT (4321), NULL);
1121 
1122   validate_event (4, "flush-start", NULL);
1123 
1124   validate_event (5, "flush-stop", NULL);
1125 
1126   validate_event (6, "segment",
1127       "time", G_GUINT64_CONSTANT (1234),
1128       "start", G_GUINT64_CONSTANT (0),
1129       "stop", G_GUINT64_CONSTANT (4321 - 1234), NULL);
1130 
1131   destroy_depayloader (state);
1132 }
1133 
1134 GST_END_TEST
1135 /* when a depayloader receives a new caps event with play-scale it should save
1136  * this rate as it should affect the next segment event being pushed by the
1137  * depayloader. a new segment event is not pushed by the depayloader until a
1138  * flush_stop event and a succeeding segment event are received. of course the
1139  * intial event are unaffected, as is the incoming caps event.
1140  */
GST_START_TEST(rtp_base_depayload_play_scale_test)1141 GST_START_TEST (rtp_base_depayload_play_scale_test)
1142 {
1143   State *state;
1144 
1145   state = create_depayloader ("application/x-rtp", NULL);
1146 
1147   set_state (state, GST_STATE_PLAYING);
1148 
1149   push_rtp_buffer (state,
1150       "pts", 0 * GST_SECOND,
1151       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1152 
1153   reconfigure_caps (state, "application/x-rtp, play-scale=(double)2.0");
1154 
1155   flush_pipeline (state);
1156 
1157   push_rtp_buffer (state,
1158       "pts", 1 * GST_SECOND,
1159       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1160       "seq", 0x4242 + 1, NULL);
1161 
1162   set_state (state, GST_STATE_NULL);
1163 
1164   validate_buffers_received (2);
1165 
1166   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1167 
1168   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1169 
1170   validate_events_received (7);
1171 
1172   validate_event (0, "stream-start", NULL);
1173 
1174   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1175 
1176   validate_event (2, "segment",
1177       "time", G_GUINT64_CONSTANT (0),
1178       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1179 
1180   validate_event (3, "caps",
1181       "media-type", "application/x-rtp", "play-scale", 2.0, NULL);
1182 
1183   validate_event (4, "flush-start", NULL);
1184 
1185   validate_event (5, "flush-stop", NULL);
1186 
1187   validate_event (6, "segment",
1188       "time", G_GUINT64_CONSTANT (0),
1189       "start", G_GUINT64_CONSTANT (0),
1190       "stop", G_MAXUINT64, "rate", 1.0, "applied-rate", 2.0, NULL);
1191 
1192   destroy_depayloader (state);
1193 }
1194 
1195 GST_END_TEST
1196 /* when a depayloader receives a new caps event with play-speed it should save
1197  * this rate as it should affect the next segment event being pushed by the
1198  * depayloader. a new segment event is not pushed by the depayloader until a
1199  * flush_stop event and a succeeding segment event are received. of course the
1200  * intial event are unaffected, as is the incoming caps event.
1201  */
GST_START_TEST(rtp_base_depayload_play_speed_test)1202 GST_START_TEST (rtp_base_depayload_play_speed_test)
1203 {
1204   State *state;
1205 
1206   state = create_depayloader ("application/x-rtp", NULL);
1207 
1208   set_state (state, GST_STATE_PLAYING);
1209 
1210   push_rtp_buffer (state,
1211       "pts", 0 * GST_SECOND,
1212       "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1213 
1214   reconfigure_caps (state, "application/x-rtp, play-speed=(double)2.0");
1215 
1216   flush_pipeline (state);
1217 
1218   push_rtp_buffer (state,
1219       "pts", 1 * GST_SECOND,
1220       "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1221       "seq", 0x4242 + 1, NULL);
1222 
1223   set_state (state, GST_STATE_NULL);
1224 
1225   validate_buffers_received (2);
1226 
1227   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1228 
1229   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1230 
1231   validate_events_received (7);
1232 
1233   validate_event (0, "stream-start", NULL);
1234 
1235   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1236 
1237   validate_event (2, "segment",
1238       "time", G_GUINT64_CONSTANT (0),
1239       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1240 
1241   validate_event (3, "caps",
1242       "media-type", "application/x-rtp", "play-speed", 2.0, NULL);
1243 
1244   validate_event (4, "flush-start", NULL);
1245 
1246   validate_event (5, "flush-stop", NULL);
1247 
1248   validate_event (6, "segment",
1249       "time", G_GUINT64_CONSTANT (0),
1250       "start", G_GUINT64_CONSTANT (0),
1251       "stop", G_MAXUINT64, "rate", 2.0, "applied-rate", 1.0, NULL);
1252 
1253   destroy_depayloader (state);
1254 }
1255 
1256 GST_END_TEST
1257 /* when a depayloader receives new caps events with npt-start, npt-stop and
1258  * clock-base it should save these timestamps as they should affect the next
1259  * segment event being pushed by the depayloader. the produce segment should
1260  * make the positon of the stream reflect the postion form clock-base instead
1261  * of reflecting the running time (for RTSP).
1262  */
GST_START_TEST(rtp_base_depayload_clock_base_test)1263 GST_START_TEST (rtp_base_depayload_clock_base_test)
1264 {
1265   State *state;
1266 
1267   state = create_depayloader ("application/x-rtp", NULL);
1268 
1269   set_state (state, GST_STATE_PLAYING);
1270 
1271   push_rtp_buffer (state,
1272       "pts", 0 * GST_SECOND,
1273       "rtptime", G_GUINT64_CONSTANT (1234), "seq", 0x4242, NULL);
1274 
1275   reconfigure_caps (state,
1276       "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321, clock-base=(guint)1234");
1277 
1278   flush_pipeline (state);
1279 
1280   push_rtp_buffer (state,
1281       "pts", 1 * GST_SECOND,
1282       "rtptime", G_GUINT64_CONSTANT (1234) + 1 * DEFAULT_CLOCK_RATE,
1283       "seq", 0x4242 + 1, NULL);
1284 
1285   set_state (state, GST_STATE_NULL);
1286 
1287   validate_buffers_received (2);
1288 
1289   validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1290 
1291   validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1292 
1293   validate_events_received (7);
1294 
1295   validate_event (0, "stream-start", NULL);
1296 
1297   validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1298 
1299   validate_event (2, "segment",
1300       "time", G_GUINT64_CONSTANT (0),
1301       "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1302 
1303   validate_event (3, "caps",
1304       "media-type", "application/x-rtp",
1305       "npt-start", G_GUINT64_CONSTANT (1234),
1306       "npt-stop", G_GUINT64_CONSTANT (4321), "clock-base", 1234, NULL);
1307 
1308   validate_event (4, "flush-start", NULL);
1309 
1310   validate_event (5, "flush-stop", NULL);
1311 
1312   validate_event (6, "segment",
1313       "time", G_GUINT64_CONSTANT (1234),
1314       "start", GST_SECOND,
1315       "stop", GST_SECOND + G_GUINT64_CONSTANT (4321 - 1234),
1316       "base", GST_SECOND, NULL);
1317 
1318   destroy_depayloader (state);
1319 }
1320 
1321 GST_END_TEST
1322 /* basedepayloader has a property source-info that will add
1323  * GstRTPSourceMeta to the output buffer with RTP source information, such as
1324  * SSRC and CSRCs. The is useful for letting downstream know about the origin
1325  * of the stream. */
GST_START_TEST(rtp_base_depayload_source_info_test)1326 GST_START_TEST (rtp_base_depayload_source_info_test)
1327 {
1328   GstHarness *h;
1329   GstRtpDummyDepay *depay;
1330   GstBuffer *buffer;
1331   GstRTPSourceMeta *meta;
1332   guint seq = 0;
1333 
1334   depay = rtp_dummy_depay_new ();
1335   h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1336   gst_harness_set_src_caps_str (h, "application/x-rtp");
1337 
1338   /* Property enabled should always add meta, also when there is only SSRC and
1339    * no CSRC. */
1340   g_object_set (depay, "source-info", TRUE, NULL);
1341   buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1342   rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1343   buffer = gst_harness_push_and_pull (h, buffer);
1344   fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1345   fail_unless (meta->ssrc_valid);
1346   fail_unless_equals_int (meta->ssrc, 0x11);
1347   fail_unless_equals_int (meta->csrc_count, 0);
1348   gst_buffer_unref (buffer);
1349 
1350   /* Both SSRC and CSRC should be added to the meta */
1351   buffer = gst_rtp_buffer_new_allocate (0, 0, 2);
1352   rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, "csrc", 0, 0x22,
1353       "csrc", 1, 0x33, NULL);
1354   buffer = gst_harness_push_and_pull (h, buffer);
1355   fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1356   fail_unless (meta->ssrc_valid);
1357   fail_unless_equals_int (meta->ssrc, 0x11);
1358   fail_unless_equals_int (meta->csrc_count, 2);
1359   fail_unless_equals_int (meta->csrc[0], 0x22);
1360   fail_unless_equals_int (meta->csrc[1], 0x33);
1361   gst_buffer_unref (buffer);
1362 
1363   /* Property disabled should never add meta */
1364   g_object_set (depay, "source-info", FALSE, NULL);
1365   buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1366   rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1367   buffer = gst_harness_push_and_pull (h, buffer);
1368   fail_if (gst_buffer_get_rtp_source_meta (buffer));
1369   gst_buffer_unref (buffer);
1370 
1371   g_object_unref (depay);
1372   gst_harness_teardown (h);
1373 }
1374 
1375 GST_END_TEST;
1376 
1377 
1378 static Suite *
rtp_basepayloading_suite(void)1379 rtp_basepayloading_suite (void)
1380 {
1381   Suite *s = suite_create ("rtp_base_depayloading_test");
1382   TCase *tc_chain = tcase_create ("depayloading tests");
1383 
1384   tcase_set_timeout (tc_chain, 60);
1385 
1386   suite_add_tcase (s, tc_chain);
1387   tcase_add_test (tc_chain, rtp_base_depayload_buffer_test);
1388 
1389   tcase_add_test (tc_chain, rtp_base_depayload_invalid_rtp_packet_test);
1390   tcase_add_test (tc_chain, rtp_base_depayload_with_gap_test);
1391   tcase_add_test (tc_chain, rtp_base_depayload_reversed_test);
1392   tcase_add_test (tc_chain, rtp_base_depayload_ssrc_changed_test);
1393   tcase_add_test (tc_chain, rtp_base_depayload_old_reversed_test);
1394 
1395   tcase_add_test (tc_chain, rtp_base_depayload_without_negotiation_test);
1396 
1397   tcase_add_test (tc_chain, rtp_base_depayload_packet_lost_test);
1398   tcase_add_test (tc_chain,
1399       rtp_base_depayload_packet_lost_before_first_buffer_test);
1400   tcase_add_test (tc_chain, rtp_base_depayload_seq_discont_test);
1401 
1402   tcase_add_test (tc_chain, rtp_base_depayload_repeated_caps_test);
1403   tcase_add_test (tc_chain, rtp_base_depayload_npt_test);
1404   tcase_add_test (tc_chain, rtp_base_depayload_play_scale_test);
1405   tcase_add_test (tc_chain, rtp_base_depayload_play_speed_test);
1406   tcase_add_test (tc_chain, rtp_base_depayload_clock_base_test);
1407 
1408   tcase_add_test (tc_chain, rtp_base_depayload_source_info_test);
1409 
1410   return s;
1411 }
1412 
1413 GST_CHECK_MAIN (rtp_basepayloading)
1414