1 /* GStreamer RTP base depayloader unit tests
2 * Copyright (C) 2014 Sebastian Rasmussen <sebras@hotmail.com>
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.
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.
14 * You should have received a copy of the GNU Library General
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.
25 #include <gst/check/gstcheck.h>
26 #include <gst/check/gstharness.h>
27 #include <gst/rtp/rtp.h>
29 #include "rtpdummyhdrextimpl.c"
31 #define DEFAULT_CLOCK_RATE (42)
33 /* GstRtpDummyDepay */
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))
48 GST_RTP_DUMMY_RETURN_TO_PUSH,
49 GST_RTP_DUMMY_USE_PUSH_FUNC,
50 GST_RTP_DUMMY_USE_PUSH_LIST_FUNC,
51 } GstRtpDummyPushMethod;
53 typedef struct _GstRtpDummyDepay GstRtpDummyDepay;
54 typedef struct _GstRtpDummyDepayClass GstRtpDummyDepayClass;
56 struct _GstRtpDummyDepay
58 GstRTPBaseDepayload depayload;
61 GstRtpDummyPushMethod push_method;
62 guint num_buffers_in_blist;
65 struct _GstRtpDummyDepayClass
67 GstRTPBaseDepayloadClass parent_class;
70 GType gst_rtp_dummy_depay_get_type (void);
72 G_DEFINE_TYPE (GstRtpDummyDepay, gst_rtp_dummy_depay,
73 GST_TYPE_RTP_BASE_DEPAYLOAD);
75 static GstBuffer *gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload,
77 static gboolean gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter,
80 static GstStaticPadTemplate gst_rtp_dummy_depay_sink_template =
81 GST_STATIC_PAD_TEMPLATE ("sink",
86 static GstStaticPadTemplate gst_rtp_dummy_depay_src_template =
87 GST_STATIC_PAD_TEMPLATE ("src",
93 gst_rtp_dummy_depay_class_init (GstRtpDummyDepayClass * klass)
95 GstElementClass *gstelement_class;
96 GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
98 gstelement_class = GST_ELEMENT_CLASS (klass);
99 gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
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);
106 gstrtpbasedepayload_class->process = gst_rtp_dummy_depay_process;
107 gstrtpbasedepayload_class->set_caps = gst_rtp_dummy_depay_set_caps;
111 gst_rtp_dummy_depay_init (GstRtpDummyDepay * depay)
114 depay->num_buffers_in_blist = 1;
117 static GstRtpDummyDepay *
118 rtp_dummy_depay_new (void)
120 return g_object_new (GST_TYPE_RTP_DUMMY_DEPAY, NULL);
124 gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
126 GstRtpDummyDepay *self = GST_RTP_DUMMY_DEPAY (depayload);
127 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
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));
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);
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);
150 GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
151 GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
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));
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);
167 switch (self->push_method) {
168 case GST_RTP_DUMMY_USE_PUSH_FUNC:
169 gst_rtp_base_depayload_push (depayload, outbuf);
172 case GST_RTP_DUMMY_USE_PUSH_LIST_FUNC:{
173 GstBufferList *blist = gst_buffer_list_new ();
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));
180 gst_rtp_base_depayload_push_list (depayload, blist);
183 case GST_RTP_DUMMY_RETURN_TO_PUSH:
191 gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter, GstCaps * caps)
194 event = gst_event_new_caps (caps);
195 gst_pad_push_event (filter->srcpad, event);
199 /* Helper functions and global state */
201 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
204 GST_STATIC_CAPS_ANY);
206 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
209 GST_STATIC_CAPS_ANY);
211 typedef struct State State;
220 static GList *events;
223 event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
225 events = g_list_append (events, gst_event_ref (event));
226 return gst_pad_event_default (pad, noparent, event);
232 while (events != NULL) {
233 gst_event_unref (GST_EVENT (events->data));
234 events = g_list_delete_link (events, events);
239 validate_events_received (guint received)
241 fail_unless_equals_int (g_list_length (events), received);
245 validate_event (guint index, const gchar * name, const gchar * field, ...)
250 fail_if (index >= g_list_length (events));
251 event = GST_EVENT (g_list_nth_data (events, index));
252 fail_if (event == NULL);
254 GST_TRACE ("%" GST_PTR_FORMAT, event);
256 fail_unless_equals_string (GST_EVENT_TYPE_NAME (event), name);
258 va_start (var_args, 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, ×tamp, &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, ×tamp, &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 *);
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);
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);
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);
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);
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);
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);
349 fail ("test cannot validate unknown event field '%s'", field);
351 field = va_arg (var_args, const gchar *);
357 rtp_buffer_set_valist (GstBuffer * buf, const gchar * field, va_list var_args,
358 gboolean * extra_ref_)
360 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
361 gboolean mapped = FALSE;
362 gboolean extra_ref = FALSE;
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);
374 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
376 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
380 gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
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);
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);
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,
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,
423 fail ("test cannot set unknown buffer field '%s'", field);
426 field = va_arg (var_args, const gchar *);
430 gst_rtp_buffer_unmap (&rtp);
434 gst_buffer_ref (buf);
438 rtp_buffer_set (GstBuffer * buf, const gchar * field, ...)
442 va_start (var_args, field);
443 rtp_buffer_set_valist (buf, field, var_args, NULL);
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__)
453 push_rtp_buffer_full (State * state, GstFlowReturn expected,
454 const gchar * field, ...)
456 GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
458 gboolean extra_ref = FALSE;
460 va_start (var_args, field);
461 rtp_buffer_set_valist (buf, field, var_args, &extra_ref);
464 fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
467 gst_buffer_unref (buf);
470 #define push_buffer(state, field, ...) \
471 push_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
474 push_buffer_full (State * state, GstFlowReturn expected,
475 const gchar * field, ...)
477 GstBuffer *buf = gst_buffer_new_allocate (0, 0, 0);
480 va_start (var_args, 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);
491 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
493 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
496 fail ("test cannot set unknown buffer field '%s'", field);
498 field = va_arg (var_args, const gchar *);
502 fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
506 validate_buffers_received (guint received)
508 fail_unless_equals_int (g_list_length (buffers), received);
512 validate_buffer (guint index, const gchar * field, ...)
517 fail_if (index >= g_list_length (buffers));
518 buf = GST_BUFFER (g_list_nth_data (buffers, (index)));
519 fail_if (buf == NULL);
521 GST_TRACE ("%" GST_PTR_FORMAT, buf);
523 va_start (var_args, 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);
534 fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
536 fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
539 fail ("test cannot validate unknown buffer field '%s'", field);
541 field = va_arg (var_args, const gchar *);
547 create_depayloader (const gchar * caps_str, const gchar * property, ...)
553 state = g_new0 (State, 1);
555 state->element = GST_ELEMENT (rtp_dummy_depay_new ());
556 fail_unless (GST_IS_RTP_DUMMY_DEPAY (state->element));
558 va_start (var_args, property);
559 g_object_set_valist (G_OBJECT (state->element), property, var_args);
562 state->srcpad = gst_check_setup_src_pad (state->element, &srctemplate);
563 state->sinkpad = gst_check_setup_sink_pad (state->element, &sinktemplate);
565 fail_unless (gst_pad_set_active (state->srcpad, TRUE));
566 fail_unless (gst_pad_set_active (state->sinkpad, TRUE));
569 caps = gst_caps_from_string (caps_str);
573 gst_check_setup_events (state->srcpad, state->element, caps, GST_FORMAT_TIME);
575 gst_caps_unref (caps);
578 gst_pad_set_chain_function (state->sinkpad, gst_check_chain_func);
579 gst_pad_set_event_function (state->sinkpad, event_func);
585 set_state (State * state, GstState new_state)
587 fail_unless_equals_int (gst_element_set_state (state->element, new_state),
588 GST_STATE_CHANGE_SUCCESS);
592 packet_lost (State * state, GstClockTime timestamp, GstClockTime duration,
593 gboolean might_have_been_fec)
596 guint seqnum = 0x4243;
597 gboolean late = TRUE;
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));
608 fail_unless (gst_pad_push_event (state->srcpad, event));
612 reconfigure_caps (State * state, const gchar * caps_str)
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));
623 flush_pipeline (State * state)
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));
637 destroy_depayloader (State * state)
639 gst_check_teardown_sink_pad (state->element);
640 gst_check_teardown_src_pad (state->element);
642 gst_check_drop_buffers ();
645 g_object_unref (state->element);
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.
659 GST_START_TEST (rtp_base_depayload_buffer_test)
663 state = create_depayloader ("application/x-rtp", NULL);
665 set_state (state, GST_STATE_PLAYING);
667 push_rtp_buffer (state,
668 "pts", 0 * GST_SECOND,
669 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
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);
676 set_state (state, GST_STATE_NULL);
678 validate_buffers_received (2);
680 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
682 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
684 validate_events_received (3);
686 validate_event (0, "stream-start", NULL);
688 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
690 validate_event (2, "segment",
691 "time", G_GUINT64_CONSTANT (0),
692 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
694 destroy_depayloader (state);
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.
703 GST_START_TEST (rtp_base_depayload_invalid_rtp_packet_test)
707 state = create_depayloader ("application/x-rtp", NULL);
709 set_state (state, GST_STATE_PLAYING);
712 "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
714 set_state (state, GST_STATE_NULL);
716 validate_buffers_received (0);
718 validate_events_received (2);
720 validate_event (0, "stream-start", NULL);
722 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
724 destroy_depayloader (state);
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.
736 GST_START_TEST (rtp_base_depayload_with_gap_test)
740 state = create_depayloader ("application/x-rtp", NULL);
742 set_state (state, GST_STATE_PLAYING);
744 push_rtp_buffer (state,
745 "pts", 0 * GST_SECOND,
746 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
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);
753 set_state (state, GST_STATE_NULL);
755 validate_buffers_received (2);
757 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
759 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
761 validate_events_received (3);
763 validate_event (0, "stream-start", NULL);
765 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
767 validate_event (2, "segment",
768 "time", G_GUINT64_CONSTANT (0),
769 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
771 destroy_depayloader (state);
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.
781 GST_START_TEST (rtp_base_depayload_reversed_test)
785 state = create_depayloader ("application/x-rtp", NULL);
787 set_state (state, GST_STATE_PLAYING);
789 push_rtp_buffer (state,
790 "pts", 0 * GST_SECOND,
791 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
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);
798 set_state (state, GST_STATE_NULL);
800 validate_buffers_received (1);
802 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
804 validate_events_received (3);
806 validate_event (0, "stream-start", NULL);
808 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
810 validate_event (2, "segment",
811 "time", G_GUINT64_CONSTANT (0),
812 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
814 destroy_depayloader (state);
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.
822 GST_START_TEST (rtp_base_depayload_ssrc_changed_test)
826 state = create_depayloader ("application/x-rtp", NULL);
828 set_state (state, GST_STATE_PLAYING);
830 push_rtp_buffer (state,
831 "pts", 0 * GST_SECOND,
832 "rtptime", G_GUINT64_CONSTANT (0x43214321),
833 "seq", 0x4242, "ssrc", 0xabe2b0b, NULL);
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);
840 set_state (state, GST_STATE_NULL);
842 validate_buffers_received (2);
844 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
846 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
848 validate_events_received (3);
850 validate_event (0, "stream-start", NULL);
852 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
854 validate_event (2, "segment",
855 "time", G_GUINT64_CONSTANT (0),
856 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
858 destroy_depayloader (state);
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.
870 GST_START_TEST (rtp_base_depayload_old_reversed_test)
874 state = create_depayloader ("application/x-rtp", NULL);
876 set_state (state, GST_STATE_PLAYING);
878 push_rtp_buffer (state,
879 "pts", 0 * GST_SECOND,
880 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
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);
887 set_state (state, GST_STATE_NULL);
889 validate_buffers_received (2);
891 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
893 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
895 validate_events_received (3);
897 validate_event (0, "stream-start", NULL);
899 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
901 validate_event (2, "segment",
902 "time", G_GUINT64_CONSTANT (0),
903 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
905 destroy_depayloader (state);
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.
913 GST_START_TEST (rtp_base_depayload_without_negotiation_test)
917 state = create_depayloader (NULL, NULL);
919 set_state (state, GST_STATE_PLAYING);
921 push_rtp_buffer_fails (state, GST_FLOW_NOT_NEGOTIATED,
922 "pts", 0 * GST_SECOND,
923 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
925 set_state (state, GST_STATE_NULL);
927 validate_buffers_received (0);
929 validate_events_received (1);
931 validate_event (0, "stream-start", NULL);
933 destroy_depayloader (state);
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
942 GST_START_TEST (rtp_base_depayload_packet_lost_test)
946 state = create_depayloader ("application/x-rtp", NULL);
948 set_state (state, GST_STATE_PLAYING);
950 push_rtp_buffer (state,
951 "pts", 0 * GST_SECOND,
952 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
954 packet_lost (state, 1 * GST_SECOND, GST_SECOND, FALSE);
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);
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);
965 set_state (state, GST_STATE_NULL);
967 validate_buffers_received (2);
969 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
971 validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
973 validate_events_received (4);
975 validate_event (0, "stream-start", NULL);
977 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
979 validate_event (2, "segment",
980 "time", G_GUINT64_CONSTANT (0),
981 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
983 validate_event (3, "gap",
984 "timestamp", 1 * GST_SECOND, "duration", GST_SECOND, NULL);
986 destroy_depayloader (state);
990 /* If a lost event is received before the first buffer, the rtp base
991 * depayloader will not send a gap event downstream. Alternatively it should
992 * make sure that stream-start, caps and segment events are sent in correct
993 * order before the gap event so that packet loss concealment can take place
994 * downstream, but this is more complicated and without any real benefit since
995 * concealment before any data is received is not very useful. */
996 GST_START_TEST (rtp_base_depayload_packet_lost_before_first_buffer_test)
1000 GstRtpDummyDepay *depay;
1001 const GstEventType etype[] = {
1002 GST_EVENT_STREAM_START, GST_EVENT_CAPS, GST_EVENT_SEGMENT
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");
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);
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)));
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));
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);
1034 fail_unless_equals_int (gst_harness_events_in_queue (h), 0);
1036 gst_buffer_unref (gst_harness_pull (h));
1037 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1039 g_object_unref (depay);
1040 gst_harness_teardown (h);
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
1049 GST_START_TEST (rtp_base_depayload_seq_discont_test)
1053 state = create_depayloader ("application/x-rtp", NULL);
1055 set_state (state, GST_STATE_PLAYING);
1057 push_rtp_buffer (state,
1058 "pts", 0 * GST_SECOND,
1059 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 1, NULL);
1061 push_rtp_buffer (state,
1063 "pts", 2 * GST_SECOND,
1064 "rtptime", G_GUINT64_CONSTANT (0x1234) + DEFAULT_CLOCK_RATE / 2,
1065 "seq", 33333, NULL);
1067 set_state (state, GST_STATE_NULL);
1069 validate_buffers_received (2);
1071 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1073 validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
1075 destroy_depayloader (state);
1079 /* a depayloader that receives identical caps events simply ignores the latter
1080 * events without propagating them downstream.
1082 GST_START_TEST (rtp_base_depayload_repeated_caps_test)
1086 state = create_depayloader ("application/x-rtp", NULL);
1088 set_state (state, GST_STATE_PLAYING);
1090 push_rtp_buffer (state,
1091 "pts", 0 * GST_SECOND,
1092 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1094 reconfigure_caps (state, "application/x-rtp");
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);
1101 set_state (state, GST_STATE_NULL);
1103 validate_buffers_received (2);
1105 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1107 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1109 validate_events_received (3);
1111 validate_event (0, "stream-start", NULL);
1113 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1115 validate_event (2, "segment",
1116 "time", G_GUINT64_CONSTANT (0),
1117 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1119 destroy_depayloader (state);
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
1130 GST_START_TEST (rtp_base_depayload_npt_test)
1134 state = create_depayloader ("application/x-rtp", NULL);
1136 set_state (state, GST_STATE_PLAYING);
1138 push_rtp_buffer (state,
1139 "pts", 0 * GST_SECOND,
1140 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1142 reconfigure_caps (state,
1143 "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321");
1145 flush_pipeline (state);
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);
1152 set_state (state, GST_STATE_NULL);
1154 validate_buffers_received (2);
1156 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1158 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1160 validate_events_received (7);
1162 validate_event (0, "stream-start", NULL);
1164 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1166 validate_event (2, "segment",
1167 "time", G_GUINT64_CONSTANT (0),
1168 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
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);
1175 validate_event (4, "flush-start", NULL);
1177 validate_event (5, "flush-stop", NULL);
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);
1184 destroy_depayloader (state);
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.
1194 GST_START_TEST (rtp_base_depayload_play_scale_test)
1198 state = create_depayloader ("application/x-rtp", NULL);
1200 set_state (state, GST_STATE_PLAYING);
1202 push_rtp_buffer (state,
1203 "pts", 0 * GST_SECOND,
1204 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1206 reconfigure_caps (state, "application/x-rtp, play-scale=(double)2.0");
1208 flush_pipeline (state);
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);
1215 set_state (state, GST_STATE_NULL);
1217 validate_buffers_received (2);
1219 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1221 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1223 validate_events_received (7);
1225 validate_event (0, "stream-start", NULL);
1227 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1229 validate_event (2, "segment",
1230 "time", G_GUINT64_CONSTANT (0),
1231 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1233 validate_event (3, "caps",
1234 "media-type", "application/x-rtp", "play-scale", 2.0, NULL);
1236 validate_event (4, "flush-start", NULL);
1238 validate_event (5, "flush-stop", NULL);
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);
1245 destroy_depayloader (state);
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.
1255 GST_START_TEST (rtp_base_depayload_play_speed_test)
1259 state = create_depayloader ("application/x-rtp", NULL);
1261 set_state (state, GST_STATE_PLAYING);
1263 push_rtp_buffer (state,
1264 "pts", 0 * GST_SECOND,
1265 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1267 reconfigure_caps (state, "application/x-rtp, play-speed=(double)2.0");
1269 flush_pipeline (state);
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);
1276 set_state (state, GST_STATE_NULL);
1278 validate_buffers_received (2);
1280 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1282 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1284 validate_events_received (7);
1286 validate_event (0, "stream-start", NULL);
1288 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1290 validate_event (2, "segment",
1291 "time", G_GUINT64_CONSTANT (0),
1292 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1294 validate_event (3, "caps",
1295 "media-type", "application/x-rtp", "play-speed", 2.0, NULL);
1297 validate_event (4, "flush-start", NULL);
1299 validate_event (5, "flush-stop", NULL);
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);
1306 destroy_depayloader (state);
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).
1316 GST_START_TEST (rtp_base_depayload_clock_base_test)
1320 state = create_depayloader ("application/x-rtp", NULL);
1322 set_state (state, GST_STATE_PLAYING);
1324 push_rtp_buffer (state,
1325 "pts", 0 * GST_SECOND,
1326 "rtptime", G_GUINT64_CONSTANT (1234), "seq", 0x4242, NULL);
1328 reconfigure_caps (state,
1329 "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321, clock-base=(guint)1234");
1331 flush_pipeline (state);
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);
1338 set_state (state, GST_STATE_NULL);
1340 validate_buffers_received (2);
1342 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1344 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1346 validate_events_received (7);
1348 validate_event (0, "stream-start", NULL);
1350 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1352 validate_event (2, "segment",
1353 "time", G_GUINT64_CONSTANT (0),
1354 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
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);
1361 validate_event (4, "flush-start", NULL);
1363 validate_event (5, "flush-stop", NULL);
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);
1371 destroy_depayloader (state);
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
1379 GST_START_TEST (rtp_base_depayload_source_info_test)
1382 GstRtpDummyDepay *depay;
1384 GstRTPSourceMeta *meta;
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");
1391 /* Property enabled should always add meta, also when there is only SSRC and
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);
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);
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);
1424 g_object_unref (depay);
1425 gst_harness_teardown (h);
1430 /* verify that if a buffer arriving in the depayloader already has source-info
1431 meta on it, that this does not affect the source-info coming out of the
1432 depayloder, which should be all derived from the rtp-header */
1433 GST_START_TEST (rtp_base_depayload_source_info_from_rtp_only)
1436 GstRtpDummyDepay *depay;
1438 GstRTPSourceMeta *meta;
1439 guint rtp_ssrc = 0x11;
1440 guint rtp_csrc = 0x22;
1441 guint32 meta_ssrc = 0x55;
1442 guint32 meta_csrc = 0x66;
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");
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,
1452 meta = gst_buffer_add_rtp_source_meta (buffer, &meta_ssrc, &meta_csrc, 1);
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);
1462 g_object_unref (depay);
1463 gst_harness_teardown (h);
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
1472 GST_START_TEST (rtp_base_depayload_max_reorder)
1475 GstRtpDummyDepay *depay;
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");
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); \
1488 gst_buffer_unref (gst_harness_pull (h)); \
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);
1497 /* Update property to allow less reordering */
1498 g_object_set (depay, "max-reorder", 3, NULL);
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);
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);
1509 /* Update property to minimum value. Should never drop buffers. */
1510 g_object_set (depay, "max-reorder", 0, NULL);
1512 /* Duplicate buffer should now be pushed. */
1513 PUSH_AND_CHECK (seq, TRUE);
1514 PUSH_AND_CHECK (seq, TRUE);
1516 g_object_unref (depay);
1517 gst_harness_teardown (h);
1522 GST_START_TEST (rtp_base_depayload_flow_return_push_func)
1526 state = create_depayloader ("application/x-rtp", NULL);
1528 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1529 GST_RTP_DUMMY_USE_PUSH_LIST_FUNC;
1531 set_state (state, GST_STATE_PLAYING);
1533 GST_PAD_SET_FLUSHING (state->sinkpad);
1535 push_rtp_buffer_fails (state, GST_FLOW_FLUSHING,
1536 "pts", 0 * GST_SECOND,
1537 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1539 set_state (state, GST_STATE_NULL);
1541 destroy_depayloader (state);
1546 GST_START_TEST (rtp_base_depayload_flow_return_push_list_func)
1550 state = create_depayloader ("application/x-rtp", NULL);
1552 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1553 GST_RTP_DUMMY_USE_PUSH_FUNC;
1555 set_state (state, GST_STATE_PLAYING);
1557 GST_PAD_SET_FLUSHING (state->sinkpad);
1559 push_rtp_buffer_fails (state, GST_FLOW_FLUSHING,
1560 "pts", 0 * GST_SECOND,
1561 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1563 set_state (state, GST_STATE_NULL);
1565 destroy_depayloader (state);
1570 GST_START_TEST (rtp_base_depayload_one_byte_hdr_ext)
1572 GstRTPHeaderExtension *ext;
1575 state = create_depayloader ("application/x-rtp", NULL);
1576 ext = rtp_dummy_hdr_ext_new ();
1577 gst_rtp_header_extension_set_id (ext, 1);
1579 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1580 GST_RTP_DUMMY_RETURN_TO_PUSH;
1582 g_signal_emit_by_name (state->element, "add-extension", ext);
1584 set_state (state, GST_STATE_PLAYING);
1586 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1587 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1590 set_state (state, GST_STATE_NULL);
1592 validate_buffers_received (1);
1594 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1596 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1598 gst_object_unref (ext);
1599 destroy_depayloader (state);
1604 GST_START_TEST (rtp_base_depayload_two_byte_hdr_ext)
1606 GstRTPHeaderExtension *ext;
1609 state = create_depayloader ("application/x-rtp", NULL);
1610 ext = rtp_dummy_hdr_ext_new ();
1611 gst_rtp_header_extension_set_id (ext, 1);
1613 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1614 GST_RTP_DUMMY_RETURN_TO_PUSH;
1616 g_signal_emit_by_name (state->element, "add-extension", ext);
1618 set_state (state, GST_STATE_PLAYING);
1620 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1621 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-2", ext,
1624 set_state (state, GST_STATE_NULL);
1626 validate_buffers_received (1);
1628 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1630 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1632 gst_object_unref (ext);
1633 destroy_depayloader (state);
1638 static GstRTPHeaderExtension *
1639 request_extension (GstRTPBaseDepayload * depayload, guint ext_id,
1640 const gchar * ext_uri, gpointer user_data)
1642 GstRTPHeaderExtension *ext = user_data;
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);
1651 GST_START_TEST (rtp_base_depayload_request_extension)
1653 GstRTPHeaderExtension *ext;
1654 GstRTPDummyHdrExt *dummy;
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);
1664 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1665 GST_RTP_DUMMY_RETURN_TO_PUSH;
1667 g_signal_connect (state->element, "request-extension",
1668 G_CALLBACK (request_extension), ext);
1670 fail_unless (dummy->set_attributes_count == 0);
1672 set_state (state, GST_STATE_PLAYING);
1674 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1675 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1678 set_state (state, GST_STATE_NULL);
1680 validate_buffers_received (1);
1682 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1684 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1685 fail_unless (dummy->set_attributes_count == 1);
1687 gst_object_unref (ext);
1688 destroy_depayloader (state);
1693 GST_START_TEST (rtp_base_depayload_clear_extensions)
1695 GstRTPHeaderExtension *ext;
1698 state = create_depayloader ("application/x-rtp", NULL);
1699 ext = rtp_dummy_hdr_ext_new ();
1700 gst_rtp_header_extension_set_id (ext, 1);
1702 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1703 GST_RTP_DUMMY_RETURN_TO_PUSH;
1705 g_signal_emit_by_name (state->element, "add-extension", ext);
1707 set_state (state, GST_STATE_PLAYING);
1709 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1710 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1713 g_signal_emit_by_name (state->element, "clear-extensions");
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);
1719 set_state (state, GST_STATE_NULL);
1721 validate_buffers_received (2);
1723 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1724 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1726 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1728 gst_object_unref (ext);
1729 destroy_depayloader (state);
1734 GST_START_TEST (rtp_base_depayload_multiple_exts)
1736 GstRTPHeaderExtension *ext1;
1737 GstRTPHeaderExtension *ext2;
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);
1746 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1747 GST_RTP_DUMMY_RETURN_TO_PUSH;
1749 g_signal_emit_by_name (state->element, "add-extension", ext1);
1750 g_signal_emit_by_name (state->element, "add-extension", ext2);
1752 set_state (state, GST_STATE_PLAYING);
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);
1758 set_state (state, GST_STATE_NULL);
1760 validate_buffers_received (1);
1762 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
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);
1767 gst_object_unref (ext1);
1768 gst_object_unref (ext2);
1769 destroy_depayloader (state);
1774 static GstRTPHeaderExtension *
1775 request_extension_ignored (GstRTPBaseDepayload * depayload, guint ext_id,
1776 const gchar * ext_uri, gpointer user_data)
1778 guint *request_counter = user_data;
1780 *request_counter += 1;
1785 GST_START_TEST (rtp_base_depayload_caps_request_ignored)
1788 guint request_counter = 0;
1791 create_depayloader ("application/x-rtp,extmap-3=(string)"
1792 DUMMY_HDR_EXT_URI, NULL);
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);
1799 set_state (state, GST_STATE_PLAYING);
1801 push_rtp_buffer (state,
1802 "pts", 0 * GST_SECOND,
1803 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1805 fail_unless_equals_int (request_counter, 1);
1807 set_state (state, GST_STATE_NULL);
1809 validate_buffers_received (1);
1811 destroy_depayloader (state);
1816 static GstFlowReturn
1817 hdr_ext_caps_change_chain_func (GstPad * pad, GstObject * parent,
1823 static guint expected_caps_val = 0;
1825 res = gst_check_chain_func (pad, parent, buffer);
1826 if (res != GST_FLOW_OK) {
1830 caps = gst_pad_get_current_caps (pad);
1832 fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
1833 "dummy-hdrext-val", &val));
1835 /* Every fifth buffer increments "dummy-hdrext-val". */
1836 if (g_list_length (buffers) % 5 == 1) {
1837 expected_caps_val++;
1840 fail_unless_equals_int (expected_caps_val, val);
1842 gst_caps_unref (caps);
1847 GST_START_TEST (rtp_base_depayload_hdr_ext_caps_change)
1849 GstRTPHeaderExtension *ext;
1852 state = create_depayloader ("application/x-rtp", NULL);
1853 gst_pad_set_chain_function (state->sinkpad, hdr_ext_caps_change_chain_func);
1855 ext = rtp_dummy_hdr_ext_new ();
1856 gst_rtp_header_extension_set_id (ext, 1);
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;
1862 g_signal_emit_by_name (state->element, "add-extension", ext);
1864 set_state (state, GST_STATE_PLAYING);
1866 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1867 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1870 set_state (state, GST_STATE_NULL);
1872 validate_buffers_received (15);
1874 gst_object_unref (ext);
1875 destroy_depayloader (state);
1881 rtp_basepayloading_suite (void)
1883 Suite *s = suite_create ("rtp_base_depayloading_test");
1884 TCase *tc_chain = tcase_create ("depayloading tests");
1886 tcase_set_timeout (tc_chain, 60);
1888 suite_add_tcase (s, tc_chain);
1889 tcase_add_test (tc_chain, rtp_base_depayload_buffer_test);
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);
1897 tcase_add_test (tc_chain, rtp_base_depayload_without_negotiation_test);
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);
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);
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);
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);
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);
1928 GST_CHECK_MAIN (rtp_basepayloading)