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 #define DEFAULT_CLOCK_RATE (42)
31 /* GstRtpDummyDepay */
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))
44 typedef struct _GstRtpDummyDepay GstRtpDummyDepay;
45 typedef struct _GstRtpDummyDepayClass GstRtpDummyDepayClass;
47 struct _GstRtpDummyDepay
49 GstRTPBaseDepayload depayload;
53 struct _GstRtpDummyDepayClass
55 GstRTPBaseDepayloadClass parent_class;
58 GType gst_rtp_dummy_depay_get_type (void);
60 G_DEFINE_TYPE (GstRtpDummyDepay, gst_rtp_dummy_depay,
61 GST_TYPE_RTP_BASE_DEPAYLOAD);
63 static GstBuffer *gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload,
65 static gboolean gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter,
68 static GstStaticPadTemplate gst_rtp_dummy_depay_sink_template =
69 GST_STATIC_PAD_TEMPLATE ("sink",
74 static GstStaticPadTemplate gst_rtp_dummy_depay_src_template =
75 GST_STATIC_PAD_TEMPLATE ("src",
81 gst_rtp_dummy_depay_class_init (GstRtpDummyDepayClass * klass)
83 GstElementClass *gstelement_class;
84 GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
86 gstelement_class = GST_ELEMENT_CLASS (klass);
87 gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
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);
94 gstrtpbasedepayload_class->process = gst_rtp_dummy_depay_process;
95 gstrtpbasedepayload_class->set_caps = gst_rtp_dummy_depay_set_caps;
99 gst_rtp_dummy_depay_init (GstRtpDummyDepay * depay)
104 static GstRtpDummyDepay *
105 rtp_dummy_depay_new (void)
107 return g_object_new (GST_TYPE_RTP_DUMMY_DEPAY, NULL);
111 gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
113 GstRTPBuffer rtp = { NULL };
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));
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);
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);
136 GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
137 GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
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));
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);
157 gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter, GstCaps * caps)
160 event = gst_event_new_caps (caps);
161 gst_pad_push_event (filter->srcpad, event);
165 /* Helper functions and global state */
167 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
170 GST_STATIC_CAPS_ANY);
172 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
175 GST_STATIC_CAPS_ANY);
177 typedef struct State State;
186 static GList *events;
189 event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
191 events = g_list_append (events, gst_event_ref (event));
192 return gst_pad_event_default (pad, noparent, event);
198 while (events != NULL) {
199 gst_event_unref (GST_EVENT (events->data));
200 events = g_list_delete_link (events, events);
205 validate_events_received (guint received)
207 fail_unless_equals_int (g_list_length (events), received);
211 validate_event (guint index, const gchar * name, const gchar * field, ...)
216 fail_if (index >= g_list_length (events));
217 event = GST_EVENT (g_list_nth_data (events, index));
218 fail_if (event == NULL);
220 GST_TRACE ("%" GST_PTR_FORMAT, event);
222 fail_unless_equals_string (GST_EVENT_TYPE_NAME (event), name);
224 va_start (var_args, 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, ×tamp, &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, ×tamp, &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 *);
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);
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);
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);
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);
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);
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);
315 fail ("test cannot validate unknown event field '%s'", field);
317 field = va_arg (var_args, const gchar *);
323 rtp_buffer_set_valist (GstBuffer * buf, const gchar * field, va_list var_args,
324 gboolean * extra_ref_)
326 GstRTPBuffer rtp = { NULL };
327 gboolean mapped = FALSE;
328 gboolean extra_ref = FALSE;
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);
340 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
342 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
346 gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
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);
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);
370 fail ("test cannot set unknown buffer field '%s'", field);
373 field = va_arg (var_args, const gchar *);
377 gst_rtp_buffer_unmap (&rtp);
381 gst_buffer_ref (buf);
385 rtp_buffer_set (GstBuffer * buf, const gchar * field, ...)
389 va_start (var_args, field);
390 rtp_buffer_set_valist (buf, field, var_args, NULL);
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__)
400 push_rtp_buffer_full (State * state, GstFlowReturn expected,
401 const gchar * field, ...)
403 GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
405 gboolean extra_ref = FALSE;
407 va_start (var_args, field);
408 rtp_buffer_set_valist (buf, field, var_args, &extra_ref);
411 fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
414 gst_buffer_unref (buf);
417 #define push_buffer(state, field, ...) \
418 push_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
421 push_buffer_full (State * state, GstFlowReturn expected,
422 const gchar * field, ...)
424 GstBuffer *buf = gst_buffer_new_allocate (0, 0, 0);
427 va_start (var_args, 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);
438 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
440 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
443 fail ("test cannot set unknown buffer field '%s'", field);
445 field = va_arg (var_args, const gchar *);
449 fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
453 validate_buffers_received (guint received)
455 fail_unless_equals_int (g_list_length (buffers), received);
459 validate_buffer (guint index, const gchar * field, ...)
464 fail_if (index >= g_list_length (buffers));
465 buf = GST_BUFFER (g_list_nth_data (buffers, (index)));
466 fail_if (buf == NULL);
468 GST_TRACE ("%" GST_PTR_FORMAT, buf);
470 va_start (var_args, 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);
481 fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
483 fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
486 fail ("test cannot validate unknown buffer field '%s'", field);
488 field = va_arg (var_args, const gchar *);
494 create_depayloader (const gchar * caps_str, const gchar * property, ...)
500 state = g_new0 (State, 1);
502 state->element = GST_ELEMENT (rtp_dummy_depay_new ());
503 fail_unless (GST_IS_RTP_DUMMY_DEPAY (state->element));
505 va_start (var_args, property);
506 g_object_set_valist (G_OBJECT (state->element), property, var_args);
509 state->srcpad = gst_check_setup_src_pad (state->element, &srctemplate);
510 state->sinkpad = gst_check_setup_sink_pad (state->element, &sinktemplate);
512 fail_unless (gst_pad_set_active (state->srcpad, TRUE));
513 fail_unless (gst_pad_set_active (state->sinkpad, TRUE));
516 caps = gst_caps_from_string (caps_str);
520 gst_check_setup_events (state->srcpad, state->element, caps, GST_FORMAT_TIME);
522 gst_caps_unref (caps);
525 gst_pad_set_chain_function (state->sinkpad, gst_check_chain_func);
526 gst_pad_set_event_function (state->sinkpad, event_func);
532 set_state (State * state, GstState new_state)
534 fail_unless_equals_int (gst_element_set_state (state->element, new_state),
535 GST_STATE_CHANGE_SUCCESS);
539 packet_lost (State * state, GstClockTime timestamp, GstClockTime duration,
540 gboolean might_have_been_fec)
543 guint seqnum = 0x4243;
544 gboolean late = TRUE;
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));
555 fail_unless (gst_pad_push_event (state->srcpad, event));
559 reconfigure_caps (State * state, const gchar * caps_str)
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));
570 flush_pipeline (State * state)
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));
584 destroy_depayloader (State * state)
586 gst_check_teardown_sink_pad (state->element);
587 gst_check_teardown_src_pad (state->element);
589 gst_check_drop_buffers ();
592 g_object_unref (state->element);
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.
606 GST_START_TEST (rtp_base_depayload_buffer_test)
610 state = create_depayloader ("application/x-rtp", NULL);
612 set_state (state, GST_STATE_PLAYING);
614 push_rtp_buffer (state,
615 "pts", 0 * GST_SECOND,
616 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
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);
623 set_state (state, GST_STATE_NULL);
625 validate_buffers_received (2);
627 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
629 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
631 validate_events_received (3);
633 validate_event (0, "stream-start", NULL);
635 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
637 validate_event (2, "segment",
638 "time", G_GUINT64_CONSTANT (0),
639 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
641 destroy_depayloader (state);
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.
650 GST_START_TEST (rtp_base_depayload_invalid_rtp_packet_test)
654 state = create_depayloader ("application/x-rtp", NULL);
656 set_state (state, GST_STATE_PLAYING);
659 "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
661 set_state (state, GST_STATE_NULL);
663 validate_buffers_received (0);
665 validate_events_received (2);
667 validate_event (0, "stream-start", NULL);
669 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
671 destroy_depayloader (state);
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.
683 GST_START_TEST (rtp_base_depayload_with_gap_test)
687 state = create_depayloader ("application/x-rtp", NULL);
689 set_state (state, GST_STATE_PLAYING);
691 push_rtp_buffer (state,
692 "pts", 0 * GST_SECOND,
693 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
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);
700 set_state (state, GST_STATE_NULL);
702 validate_buffers_received (2);
704 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
706 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
708 validate_events_received (3);
710 validate_event (0, "stream-start", NULL);
712 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
714 validate_event (2, "segment",
715 "time", G_GUINT64_CONSTANT (0),
716 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
718 destroy_depayloader (state);
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.
728 GST_START_TEST (rtp_base_depayload_reversed_test)
732 state = create_depayloader ("application/x-rtp", NULL);
734 set_state (state, GST_STATE_PLAYING);
736 push_rtp_buffer (state,
737 "pts", 0 * GST_SECOND,
738 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
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);
745 set_state (state, GST_STATE_NULL);
747 validate_buffers_received (1);
749 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
751 validate_events_received (3);
753 validate_event (0, "stream-start", NULL);
755 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
757 validate_event (2, "segment",
758 "time", G_GUINT64_CONSTANT (0),
759 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
761 destroy_depayloader (state);
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.
769 GST_START_TEST (rtp_base_depayload_ssrc_changed_test)
773 state = create_depayloader ("application/x-rtp", NULL);
775 set_state (state, GST_STATE_PLAYING);
777 push_rtp_buffer (state,
778 "pts", 0 * GST_SECOND,
779 "rtptime", G_GUINT64_CONSTANT (0x43214321),
780 "seq", 0x4242, "ssrc", 0xabe2b0b, NULL);
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);
787 set_state (state, GST_STATE_NULL);
789 validate_buffers_received (2);
791 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
793 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
795 validate_events_received (3);
797 validate_event (0, "stream-start", NULL);
799 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
801 validate_event (2, "segment",
802 "time", G_GUINT64_CONSTANT (0),
803 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
805 destroy_depayloader (state);
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.
817 GST_START_TEST (rtp_base_depayload_old_reversed_test)
821 state = create_depayloader ("application/x-rtp", NULL);
823 set_state (state, GST_STATE_PLAYING);
825 push_rtp_buffer (state,
826 "pts", 0 * GST_SECOND,
827 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
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);
834 set_state (state, GST_STATE_NULL);
836 validate_buffers_received (2);
838 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
840 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
842 validate_events_received (3);
844 validate_event (0, "stream-start", NULL);
846 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
848 validate_event (2, "segment",
849 "time", G_GUINT64_CONSTANT (0),
850 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
852 destroy_depayloader (state);
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.
860 GST_START_TEST (rtp_base_depayload_without_negotiation_test)
864 state = create_depayloader (NULL, NULL);
866 set_state (state, GST_STATE_PLAYING);
868 push_rtp_buffer_fails (state, GST_FLOW_NOT_NEGOTIATED,
869 "pts", 0 * GST_SECOND,
870 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
872 set_state (state, GST_STATE_NULL);
874 validate_buffers_received (0);
876 validate_events_received (1);
878 validate_event (0, "stream-start", NULL);
880 destroy_depayloader (state);
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
889 GST_START_TEST (rtp_base_depayload_packet_lost_test)
893 state = create_depayloader ("application/x-rtp", NULL);
895 set_state (state, GST_STATE_PLAYING);
897 push_rtp_buffer (state,
898 "pts", 0 * GST_SECOND,
899 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
901 packet_lost (state, 1 * GST_SECOND, GST_SECOND, FALSE);
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);
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);
912 set_state (state, GST_STATE_NULL);
914 validate_buffers_received (2);
916 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
918 validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
920 validate_events_received (4);
922 validate_event (0, "stream-start", NULL);
924 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
926 validate_event (2, "segment",
927 "time", G_GUINT64_CONSTANT (0),
928 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
930 validate_event (3, "gap",
931 "timestamp", 1 * GST_SECOND, "duration", GST_SECOND, NULL);
933 destroy_depayloader (state);
937 /* rtp base depayloader should set DISCONT flag on buffer in case of a large
938 * sequence number gap, and it's not set already by upstream. This tests a
939 * certain code path where the buffer needs to be made writable to set the
942 GST_START_TEST (rtp_base_depayload_seq_discont_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", 1, NULL);
954 push_rtp_buffer (state,
956 "pts", 2 * GST_SECOND,
957 "rtptime", G_GUINT64_CONSTANT (0x1234) + DEFAULT_CLOCK_RATE / 2,
960 set_state (state, GST_STATE_NULL);
962 validate_buffers_received (2);
964 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
966 validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
968 destroy_depayloader (state);
972 /* a depayloader that receives identical caps events simply ignores the latter
973 * events without propagating them downstream.
975 GST_START_TEST (rtp_base_depayload_repeated_caps_test)
979 state = create_depayloader ("application/x-rtp", NULL);
981 set_state (state, GST_STATE_PLAYING);
983 push_rtp_buffer (state,
984 "pts", 0 * GST_SECOND,
985 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
987 reconfigure_caps (state, "application/x-rtp");
989 push_rtp_buffer (state,
990 "pts", 1 * GST_SECOND,
991 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
992 "seq", 0x4242 + 1, NULL);
994 set_state (state, GST_STATE_NULL);
996 validate_buffers_received (2);
998 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1000 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1002 validate_events_received (3);
1004 validate_event (0, "stream-start", NULL);
1006 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1008 validate_event (2, "segment",
1009 "time", G_GUINT64_CONSTANT (0),
1010 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1012 destroy_depayloader (state);
1016 /* when a depayloader receives new caps events with npt-start and npt-stop times
1017 * it should save these timestamps as they should affect the next segment event
1018 * being pushed by the depayloader. a new segment event is not pushed by the
1019 * depayloader until a flush_stop event and a succeeding segment event are
1020 * received. of course the intial event are unaffected, as is the incoming caps
1023 GST_START_TEST (rtp_base_depayload_npt_test)
1027 state = create_depayloader ("application/x-rtp", NULL);
1029 set_state (state, GST_STATE_PLAYING);
1031 push_rtp_buffer (state,
1032 "pts", 0 * GST_SECOND,
1033 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1035 reconfigure_caps (state,
1036 "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321");
1038 flush_pipeline (state);
1040 push_rtp_buffer (state,
1041 "pts", 1 * GST_SECOND,
1042 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1043 "seq", 0x4242 + 1, NULL);
1045 set_state (state, GST_STATE_NULL);
1047 validate_buffers_received (2);
1049 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1051 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1053 validate_events_received (7);
1055 validate_event (0, "stream-start", NULL);
1057 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1059 validate_event (2, "segment",
1060 "time", G_GUINT64_CONSTANT (0),
1061 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1063 validate_event (3, "caps",
1064 "media-type", "application/x-rtp",
1065 "npt-start", G_GUINT64_CONSTANT (1234),
1066 "npt-stop", G_GUINT64_CONSTANT (4321), NULL);
1068 validate_event (4, "flush-start", NULL);
1070 validate_event (5, "flush-stop", NULL);
1072 validate_event (6, "segment",
1073 "time", G_GUINT64_CONSTANT (1234),
1074 "start", G_GUINT64_CONSTANT (0),
1075 "stop", G_GUINT64_CONSTANT (4321 - 1234), NULL);
1077 destroy_depayloader (state);
1081 /* when a depayloader receives a new caps event with play-scale it should save
1082 * this rate as it should affect the next segment event being pushed by the
1083 * depayloader. a new segment event is not pushed by the depayloader until a
1084 * flush_stop event and a succeeding segment event are received. of course the
1085 * intial event are unaffected, as is the incoming caps event.
1087 GST_START_TEST (rtp_base_depayload_play_scale_test)
1091 state = create_depayloader ("application/x-rtp", NULL);
1093 set_state (state, GST_STATE_PLAYING);
1095 push_rtp_buffer (state,
1096 "pts", 0 * GST_SECOND,
1097 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1099 reconfigure_caps (state, "application/x-rtp, play-scale=(double)2.0");
1101 flush_pipeline (state);
1103 push_rtp_buffer (state,
1104 "pts", 1 * GST_SECOND,
1105 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1106 "seq", 0x4242 + 1, NULL);
1108 set_state (state, GST_STATE_NULL);
1110 validate_buffers_received (2);
1112 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1114 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1116 validate_events_received (7);
1118 validate_event (0, "stream-start", NULL);
1120 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1122 validate_event (2, "segment",
1123 "time", G_GUINT64_CONSTANT (0),
1124 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1126 validate_event (3, "caps",
1127 "media-type", "application/x-rtp", "play-scale", 2.0, NULL);
1129 validate_event (4, "flush-start", NULL);
1131 validate_event (5, "flush-stop", NULL);
1133 validate_event (6, "segment",
1134 "time", G_GUINT64_CONSTANT (0),
1135 "start", G_GUINT64_CONSTANT (0),
1136 "stop", G_MAXUINT64, "rate", 1.0, "applied-rate", 2.0, NULL);
1138 destroy_depayloader (state);
1142 /* when a depayloader receives a new caps event with play-speed it should save
1143 * this rate as it should affect the next segment event being pushed by the
1144 * depayloader. a new segment event is not pushed by the depayloader until a
1145 * flush_stop event and a succeeding segment event are received. of course the
1146 * intial event are unaffected, as is the incoming caps event.
1148 GST_START_TEST (rtp_base_depayload_play_speed_test)
1152 state = create_depayloader ("application/x-rtp", NULL);
1154 set_state (state, GST_STATE_PLAYING);
1156 push_rtp_buffer (state,
1157 "pts", 0 * GST_SECOND,
1158 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1160 reconfigure_caps (state, "application/x-rtp, play-speed=(double)2.0");
1162 flush_pipeline (state);
1164 push_rtp_buffer (state,
1165 "pts", 1 * GST_SECOND,
1166 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1167 "seq", 0x4242 + 1, NULL);
1169 set_state (state, GST_STATE_NULL);
1171 validate_buffers_received (2);
1173 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1175 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1177 validate_events_received (7);
1179 validate_event (0, "stream-start", NULL);
1181 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1183 validate_event (2, "segment",
1184 "time", G_GUINT64_CONSTANT (0),
1185 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1187 validate_event (3, "caps",
1188 "media-type", "application/x-rtp", "play-speed", 2.0, NULL);
1190 validate_event (4, "flush-start", NULL);
1192 validate_event (5, "flush-stop", NULL);
1194 validate_event (6, "segment",
1195 "time", G_GUINT64_CONSTANT (0),
1196 "start", G_GUINT64_CONSTANT (0),
1197 "stop", G_MAXUINT64, "rate", 2.0, "applied-rate", 1.0, NULL);
1199 destroy_depayloader (state);
1203 /* when a depayloader receives new caps events with npt-start, npt-stop and
1204 * clock-base it should save these timestamps as they should affect the next
1205 * segment event being pushed by the depayloader. the produce segment should
1206 * make the positon of the stream reflect the postion form clock-base instead
1207 * of reflecting the running time (for RTSP).
1209 GST_START_TEST (rtp_base_depayload_clock_base_test)
1213 state = create_depayloader ("application/x-rtp", NULL);
1215 set_state (state, GST_STATE_PLAYING);
1217 push_rtp_buffer (state,
1218 "pts", 0 * GST_SECOND,
1219 "rtptime", G_GUINT64_CONSTANT (1234), "seq", 0x4242, NULL);
1221 reconfigure_caps (state,
1222 "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321, clock-base=(guint)1234");
1224 flush_pipeline (state);
1226 push_rtp_buffer (state,
1227 "pts", 1 * GST_SECOND,
1228 "rtptime", G_GUINT64_CONSTANT (1234) + 1 * DEFAULT_CLOCK_RATE,
1229 "seq", 0x4242 + 1, NULL);
1231 set_state (state, GST_STATE_NULL);
1233 validate_buffers_received (2);
1235 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1237 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1239 validate_events_received (7);
1241 validate_event (0, "stream-start", NULL);
1243 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1245 validate_event (2, "segment",
1246 "time", G_GUINT64_CONSTANT (0),
1247 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1249 validate_event (3, "caps",
1250 "media-type", "application/x-rtp",
1251 "npt-start", G_GUINT64_CONSTANT (1234),
1252 "npt-stop", G_GUINT64_CONSTANT (4321), "clock-base", 1234, NULL);
1254 validate_event (4, "flush-start", NULL);
1256 validate_event (5, "flush-stop", NULL);
1258 validate_event (6, "segment",
1259 "time", G_GUINT64_CONSTANT (1234),
1260 "start", GST_SECOND,
1261 "stop", GST_SECOND + G_GUINT64_CONSTANT (4321 - 1234),
1262 "base", GST_SECOND, NULL);
1264 destroy_depayloader (state);
1268 /* basedepayloader has a property source-info that will add
1269 * GstRTPSourceMeta to the output buffer with RTP source information, such as
1270 * SSRC and CSRCs. The is useful for letting downstream know about the origin
1272 GST_START_TEST (rtp_base_depayload_source_info_test)
1275 GstRtpDummyDepay *depay;
1277 GstRTPSourceMeta *meta;
1280 depay = rtp_dummy_depay_new ();
1281 h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1282 gst_harness_set_src_caps_str (h, "application/x-rtp");
1284 /* Property enabled should always add meta, also when there is only SSRC and
1286 g_object_set (depay, "source-info", TRUE, NULL);
1287 buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1288 rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1289 buffer = gst_harness_push_and_pull (h, buffer);
1290 fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1291 fail_unless (meta->ssrc_valid);
1292 fail_unless_equals_int (meta->ssrc, 0x11);
1293 fail_unless_equals_int (meta->csrc_count, 0);
1294 gst_buffer_unref (buffer);
1296 /* Both SSRC and CSRC should be added to the meta */
1297 buffer = gst_rtp_buffer_new_allocate (0, 0, 2);
1298 rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, "csrc", 0, 0x22,
1299 "csrc", 1, 0x33, NULL);
1300 buffer = gst_harness_push_and_pull (h, buffer);
1301 fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1302 fail_unless (meta->ssrc_valid);
1303 fail_unless_equals_int (meta->ssrc, 0x11);
1304 fail_unless_equals_int (meta->csrc_count, 2);
1305 fail_unless_equals_int (meta->csrc[0], 0x22);
1306 fail_unless_equals_int (meta->csrc[1], 0x33);
1307 gst_buffer_unref (buffer);
1309 /* Property disabled should never add meta */
1310 g_object_set (depay, "source-info", FALSE, NULL);
1311 buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1312 rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1313 buffer = gst_harness_push_and_pull (h, buffer);
1314 fail_if (gst_buffer_get_rtp_source_meta (buffer));
1315 gst_buffer_unref (buffer);
1317 g_object_unref (depay);
1318 gst_harness_teardown (h);
1325 rtp_basepayloading_suite (void)
1327 Suite *s = suite_create ("rtp_base_depayloading_test");
1328 TCase *tc_chain = tcase_create ("depayloading tests");
1330 tcase_set_timeout (tc_chain, 60);
1332 suite_add_tcase (s, tc_chain);
1333 tcase_add_test (tc_chain, rtp_base_depayload_buffer_test);
1335 tcase_add_test (tc_chain, rtp_base_depayload_invalid_rtp_packet_test);
1336 tcase_add_test (tc_chain, rtp_base_depayload_with_gap_test);
1337 tcase_add_test (tc_chain, rtp_base_depayload_reversed_test);
1338 tcase_add_test (tc_chain, rtp_base_depayload_ssrc_changed_test);
1339 tcase_add_test (tc_chain, rtp_base_depayload_old_reversed_test);
1341 tcase_add_test (tc_chain, rtp_base_depayload_without_negotiation_test);
1343 tcase_add_test (tc_chain, rtp_base_depayload_packet_lost_test);
1344 tcase_add_test (tc_chain, rtp_base_depayload_seq_discont_test);
1346 tcase_add_test (tc_chain, rtp_base_depayload_repeated_caps_test);
1347 tcase_add_test (tc_chain, rtp_base_depayload_npt_test);
1348 tcase_add_test (tc_chain, rtp_base_depayload_play_scale_test);
1349 tcase_add_test (tc_chain, rtp_base_depayload_play_speed_test);
1350 tcase_add_test (tc_chain, rtp_base_depayload_clock_base_test);
1352 tcase_add_test (tc_chain, rtp_base_depayload_source_info_test);
1357 GST_CHECK_MAIN (rtp_basepayloading)