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