1 /* GStreamer RTP base depayloader unit tests
2 * Copyright (C) 2014 Sebastian Rasmussen <sebras@hotmail.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General
15 * Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/gst.h>
25 #include <gst/check/gstcheck.h>
26 #include <gst/check/gstharness.h>
27 #include <gst/rtp/rtp.h>
28
29 #include "rtpdummyhdrextimpl.c"
30
31 #define DEFAULT_CLOCK_RATE (42)
32
33 /* GstRtpDummyDepay */
34
35 #define GST_TYPE_RTP_DUMMY_DEPAY \
36 (gst_rtp_dummy_depay_get_type())
37 #define GST_RTP_DUMMY_DEPAY(obj) \
38 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepay))
39 #define GST_RTP_DUMMY_DEPAY_CLASS(klass) \
40 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepayClass))
41 #define GST_IS_RTP_DUMMY_DEPAY(obj) \
42 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DUMMY_DEPAY))
43 #define GST_IS_RTP_DUMMY_DEPAY_CLASS(klass) \
44 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DUMMY_DEPAY))
45
46 typedef enum
47 {
48 GST_RTP_DUMMY_RETURN_TO_PUSH,
49 GST_RTP_DUMMY_USE_PUSH_FUNC,
50 GST_RTP_DUMMY_USE_PUSH_LIST_FUNC,
51 } GstRtpDummyPushMethod;
52
53 typedef struct _GstRtpDummyDepay GstRtpDummyDepay;
54 typedef struct _GstRtpDummyDepayClass GstRtpDummyDepayClass;
55
56 struct _GstRtpDummyDepay
57 {
58 GstRTPBaseDepayload depayload;
59 guint64 rtptime;
60
61 GstRtpDummyPushMethod push_method;
62 guint num_buffers_in_blist;
63 };
64
65 struct _GstRtpDummyDepayClass
66 {
67 GstRTPBaseDepayloadClass parent_class;
68 };
69
70 GType gst_rtp_dummy_depay_get_type (void);
71
72 G_DEFINE_TYPE (GstRtpDummyDepay, gst_rtp_dummy_depay,
73 GST_TYPE_RTP_BASE_DEPAYLOAD);
74
75 static GstBuffer *gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload,
76 GstBuffer * buf);
77 static gboolean gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter,
78 GstCaps * caps);
79
80 static GstStaticPadTemplate gst_rtp_dummy_depay_sink_template =
81 GST_STATIC_PAD_TEMPLATE ("sink",
82 GST_PAD_SINK,
83 GST_PAD_ALWAYS,
84 GST_STATIC_CAPS_ANY);
85
86 static GstStaticPadTemplate gst_rtp_dummy_depay_src_template =
87 GST_STATIC_PAD_TEMPLATE ("src",
88 GST_PAD_SRC,
89 GST_PAD_ALWAYS,
90 GST_STATIC_CAPS_ANY);
91
92 static void
gst_rtp_dummy_depay_class_init(GstRtpDummyDepayClass * klass)93 gst_rtp_dummy_depay_class_init (GstRtpDummyDepayClass * klass)
94 {
95 GstElementClass *gstelement_class;
96 GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
97
98 gstelement_class = GST_ELEMENT_CLASS (klass);
99 gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
100
101 gst_element_class_add_static_pad_template (gstelement_class,
102 &gst_rtp_dummy_depay_sink_template);
103 gst_element_class_add_static_pad_template (gstelement_class,
104 &gst_rtp_dummy_depay_src_template);
105
106 gstrtpbasedepayload_class->process = gst_rtp_dummy_depay_process;
107 gstrtpbasedepayload_class->set_caps = gst_rtp_dummy_depay_set_caps;
108 }
109
110 static void
gst_rtp_dummy_depay_init(GstRtpDummyDepay * depay)111 gst_rtp_dummy_depay_init (GstRtpDummyDepay * depay)
112 {
113 depay->rtptime = 0;
114 depay->num_buffers_in_blist = 1;
115 }
116
117 static GstRtpDummyDepay *
rtp_dummy_depay_new(void)118 rtp_dummy_depay_new (void)
119 {
120 return g_object_new (GST_TYPE_RTP_DUMMY_DEPAY, NULL);
121 }
122
123 static GstBuffer *
gst_rtp_dummy_depay_process(GstRTPBaseDepayload * depayload,GstBuffer * buf)124 gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
125 {
126 GstRtpDummyDepay *self = GST_RTP_DUMMY_DEPAY (depayload);
127 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
128 GstBuffer *outbuf;
129 guint32 rtptime;
130 guint i;
131
132 GST_LOG ("depayloading buffer pts=%" GST_TIME_FORMAT " offset=%"
133 G_GUINT64_FORMAT " memories=%d", GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
134 GST_BUFFER_OFFSET (buf), gst_buffer_n_memory (buf));
135
136 for (i = 0; i < gst_buffer_n_memory (buf); i++) {
137 GstMemory *mem = gst_buffer_get_memory (buf, 0);
138 gsize size, offset, maxsize;
139 size = gst_memory_get_sizes (mem, &offset, &maxsize);
140 GST_LOG ("\tsize=%" G_GSIZE_FORMAT " offset=%" G_GSIZE_FORMAT " maxsize=%"
141 G_GSIZE_FORMAT, size, offset, maxsize);
142 gst_memory_unref (mem);
143 }
144
145 gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
146 outbuf = gst_rtp_buffer_get_payload_buffer (&rtp);
147 rtptime = gst_rtp_buffer_get_timestamp (&rtp);
148 gst_rtp_buffer_unmap (&rtp);
149
150 GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
151 GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
152
153 GST_LOG ("depayloaded buffer pts=%" GST_TIME_FORMAT " offset=%"
154 G_GUINT64_FORMAT " rtptime=%" G_GUINT32_FORMAT " memories=%d",
155 GST_TIME_ARGS (GST_BUFFER_PTS (outbuf)),
156 GST_BUFFER_OFFSET (outbuf), rtptime, gst_buffer_n_memory (buf));
157
158 for (i = 0; i < gst_buffer_n_memory (buf); i++) {
159 GstMemory *mem = gst_buffer_get_memory (buf, 0);
160 gsize size, offset, maxsize;
161 size = gst_memory_get_sizes (mem, &offset, &maxsize);
162 GST_LOG ("\tsize=%" G_GSIZE_FORMAT " offset=%" G_GSIZE_FORMAT " maxsize=%"
163 G_GSIZE_FORMAT, size, offset, maxsize);
164 gst_memory_unref (mem);
165 }
166
167 switch (self->push_method) {
168 case GST_RTP_DUMMY_USE_PUSH_FUNC:
169 gst_rtp_base_depayload_push (depayload, outbuf);
170 outbuf = NULL;
171 break;
172 case GST_RTP_DUMMY_USE_PUSH_LIST_FUNC:{
173 GstBufferList *blist = gst_buffer_list_new ();
174 gint i;
175 gst_buffer_list_add (blist, outbuf);
176 for (i = 0; i != self->num_buffers_in_blist - 1; ++i) {
177 gst_buffer_list_add (blist, gst_buffer_copy (outbuf));
178 }
179 outbuf = NULL;
180 gst_rtp_base_depayload_push_list (depayload, blist);
181 break;
182 }
183 case GST_RTP_DUMMY_RETURN_TO_PUSH:
184 break;
185 }
186
187 return outbuf;
188 }
189
190 static gboolean
gst_rtp_dummy_depay_set_caps(GstRTPBaseDepayload * filter,GstCaps * caps)191 gst_rtp_dummy_depay_set_caps (GstRTPBaseDepayload * filter, GstCaps * caps)
192 {
193 GstEvent *event;
194 event = gst_event_new_caps (caps);
195 gst_pad_push_event (filter->srcpad, event);
196 return TRUE;
197 }
198
199 /* Helper functions and global state */
200
201 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
202 GST_PAD_SRC,
203 GST_PAD_ALWAYS,
204 GST_STATIC_CAPS_ANY);
205
206 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
207 GST_PAD_SINK,
208 GST_PAD_ALWAYS,
209 GST_STATIC_CAPS_ANY);
210
211 typedef struct State State;
212
213 struct State
214 {
215 GstElement *element;
216 GstPad *sinkpad;
217 GstPad *srcpad;
218 };
219
220 static GList *events;
221
222 static gboolean
event_func(GstPad * pad,GstObject * noparent,GstEvent * event)223 event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
224 {
225 events = g_list_append (events, gst_event_ref (event));
226 return gst_pad_event_default (pad, noparent, event);
227 }
228
229 static void
drop_events(void)230 drop_events (void)
231 {
232 while (events != NULL) {
233 gst_event_unref (GST_EVENT (events->data));
234 events = g_list_delete_link (events, events);
235 }
236 }
237
238 static void
validate_events_received(guint received)239 validate_events_received (guint received)
240 {
241 fail_unless_equals_int (g_list_length (events), received);
242 }
243
244 static void
validate_event(guint index,const gchar * name,const gchar * field,...)245 validate_event (guint index, const gchar * name, const gchar * field, ...)
246 {
247 GstEvent *event;
248 va_list var_args;
249
250 fail_if (index >= g_list_length (events));
251 event = GST_EVENT (g_list_nth_data (events, index));
252 fail_if (event == NULL);
253
254 GST_TRACE ("%" GST_PTR_FORMAT, event);
255
256 fail_unless_equals_string (GST_EVENT_TYPE_NAME (event), name);
257
258 va_start (var_args, field);
259 while (field) {
260 if (!g_strcmp0 (field, "timestamp")) {
261 GstClockTime expected = va_arg (var_args, GstClockTime);
262 GstClockTime timestamp, duration;
263 gst_event_parse_gap (event, ×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 *);
302 GstCaps *caps;
303 const gchar *media_type;
304 gst_event_parse_caps (event, &caps);
305 media_type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
306 fail_unless_equals_string (media_type, expected);
307 } else if (!g_strcmp0 (field, "npt-start")) {
308 GstClockTime expected = va_arg (var_args, GstClockTime);
309 GstCaps *caps;
310 GstClockTime start;
311 gst_event_parse_caps (event, &caps);
312 fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
313 0), "npt-start", &start));
314 fail_unless_equals_uint64 (start, expected);
315 } else if (!g_strcmp0 (field, "npt-stop")) {
316 GstClockTime expected = va_arg (var_args, GstClockTime);
317 GstCaps *caps;
318 GstClockTime stop;
319 gst_event_parse_caps (event, &caps);
320 fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
321 0), "npt-stop", &stop));
322 fail_unless_equals_uint64 (stop, expected);
323 } else if (!g_strcmp0 (field, "play-speed")) {
324 gdouble expected = va_arg (var_args, gdouble);
325 GstCaps *caps;
326 gdouble speed;
327 gst_event_parse_caps (event, &caps);
328 fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
329 "play-speed", &speed));
330 fail_unless (speed == expected);
331 } else if (!g_strcmp0 (field, "play-scale")) {
332 gdouble expected = va_arg (var_args, gdouble);
333 GstCaps *caps;
334 gdouble scale;
335 gst_event_parse_caps (event, &caps);
336 fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
337 "play-scale", &scale));
338 fail_unless (scale == expected);
339 } else if (!g_strcmp0 (field, "clock-base")) {
340 guint expected = va_arg (var_args, guint);
341 GstCaps *caps;
342 guint clock_base;
343 gst_event_parse_caps (event, &caps);
344 fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
345 "clock-base", &clock_base));
346 fail_unless (clock_base == expected);
347
348 } else {
349 fail ("test cannot validate unknown event field '%s'", field);
350 }
351 field = va_arg (var_args, const gchar *);
352 }
353 va_end (var_args);
354 }
355
356 static void
rtp_buffer_set_valist(GstBuffer * buf,const gchar * field,va_list var_args,gboolean * extra_ref_)357 rtp_buffer_set_valist (GstBuffer * buf, const gchar * field, va_list var_args,
358 gboolean * extra_ref_)
359 {
360 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
361 gboolean mapped = FALSE;
362 gboolean extra_ref = FALSE;
363
364 while (field) {
365 if (!g_strcmp0 (field, "pts")) {
366 GstClockTime pts = va_arg (var_args, GstClockTime);
367 GST_BUFFER_PTS (buf) = pts;
368 } else if (!g_strcmp0 (field, "offset")) {
369 guint64 offset = va_arg (var_args, guint64);
370 GST_BUFFER_OFFSET (buf) = offset;
371 } else if (!g_strcmp0 (field, "discont")) {
372 gboolean discont = va_arg (var_args, gboolean);
373 if (discont) {
374 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
375 } else {
376 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
377 }
378 } else {
379 if (!mapped) {
380 gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
381 mapped = TRUE;
382 }
383 if (!g_strcmp0 (field, "rtptime")) {
384 guint32 rtptime = va_arg (var_args, guint64);
385 gst_rtp_buffer_set_timestamp (&rtp, rtptime);
386 } else if (!g_strcmp0 (field, "payload-type")) {
387 guint payload_type = va_arg (var_args, guint);
388 gst_rtp_buffer_set_payload_type (&rtp, payload_type);
389 } else if (!g_strcmp0 (field, "seq")) {
390 guint seq = va_arg (var_args, guint);
391 gst_rtp_buffer_set_seq (&rtp, seq);
392 } else if (!g_strcmp0 (field, "ssrc")) {
393 guint32 ssrc = va_arg (var_args, guint);
394 gst_rtp_buffer_set_ssrc (&rtp, ssrc);
395 } else if (!g_strcmp0 (field, "extra-ref")) {
396 extra_ref = va_arg (var_args, gboolean);
397 if (extra_ref_)
398 *extra_ref_ = extra_ref;
399 } else if (!g_strcmp0 (field, "csrc")) {
400 guint idx = va_arg (var_args, guint);
401 guint csrc = va_arg (var_args, guint);
402 gst_rtp_buffer_set_csrc (&rtp, idx, csrc);
403 } else if (g_str_has_prefix (field, "hdrext-")) {
404 GstRTPHeaderExtension *ext = va_arg (var_args, GstRTPHeaderExtension *);
405 guint id = gst_rtp_header_extension_get_id (ext);
406 gsize size = gst_rtp_header_extension_get_max_size (ext, buf);
407 guint8 *data = g_malloc0 (size);
408
409 if (!g_strcmp0 (field, "hdrext-1")) {
410 fail_unless (gst_rtp_header_extension_write (ext, buf,
411 GST_RTP_HEADER_EXTENSION_ONE_BYTE, buf, data, size) > 0);
412 fail_unless (gst_rtp_buffer_add_extension_onebyte_header (&rtp, id,
413 data, size));
414 } else if (!g_strcmp0 (field, "hdrext-2")) {
415 fail_unless (gst_rtp_header_extension_write (ext, buf,
416 GST_RTP_HEADER_EXTENSION_TWO_BYTE, buf, data, size) > 0);
417 fail_unless (gst_rtp_buffer_add_extension_twobytes_header (&rtp, 0,
418 id, data, size));
419 }
420
421 g_free (data);
422 } else {
423 fail ("test cannot set unknown buffer field '%s'", field);
424 }
425 }
426 field = va_arg (var_args, const gchar *);
427 }
428
429 if (mapped) {
430 gst_rtp_buffer_unmap (&rtp);
431 }
432
433 if (extra_ref)
434 gst_buffer_ref (buf);
435 }
436
437 static void
rtp_buffer_set(GstBuffer * buf,const gchar * field,...)438 rtp_buffer_set (GstBuffer * buf, const gchar * field, ...)
439 {
440 va_list var_args;
441
442 va_start (var_args, field);
443 rtp_buffer_set_valist (buf, field, var_args, NULL);
444 va_end (var_args);
445 }
446
447 #define push_rtp_buffer(state, field, ...) \
448 push_rtp_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
449 #define push_rtp_buffer_fails(state, error, field, ...) \
450 push_rtp_buffer_full ((state), (error), (field), __VA_ARGS__)
451
452 static void
push_rtp_buffer_full(State * state,GstFlowReturn expected,const gchar * field,...)453 push_rtp_buffer_full (State * state, GstFlowReturn expected,
454 const gchar * field, ...)
455 {
456 GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
457 va_list var_args;
458 gboolean extra_ref = FALSE;
459
460 va_start (var_args, field);
461 rtp_buffer_set_valist (buf, field, var_args, &extra_ref);
462 va_end (var_args);
463
464 fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
465
466 if (extra_ref)
467 gst_buffer_unref (buf);
468 }
469
470 #define push_buffer(state, field, ...) \
471 push_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
472
473 static void
push_buffer_full(State * state,GstFlowReturn expected,const gchar * field,...)474 push_buffer_full (State * state, GstFlowReturn expected,
475 const gchar * field, ...)
476 {
477 GstBuffer *buf = gst_buffer_new_allocate (0, 0, 0);
478 va_list var_args;
479
480 va_start (var_args, field);
481 while (field) {
482 if (!g_strcmp0 (field, "pts")) {
483 GstClockTime pts = va_arg (var_args, GstClockTime);
484 GST_BUFFER_PTS (buf) = pts;
485 } else if (!g_strcmp0 (field, "offset")) {
486 guint64 offset = va_arg (var_args, guint64);
487 GST_BUFFER_OFFSET (buf) = offset;
488 } else if (!g_strcmp0 (field, "discont")) {
489 gboolean discont = va_arg (var_args, gboolean);
490 if (discont) {
491 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
492 } else {
493 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
494 }
495 } else {
496 fail ("test cannot set unknown buffer field '%s'", field);
497 }
498 field = va_arg (var_args, const gchar *);
499 }
500 va_end (var_args);
501
502 fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
503 }
504
505 static void
validate_buffers_received(guint received)506 validate_buffers_received (guint received)
507 {
508 fail_unless_equals_int (g_list_length (buffers), received);
509 }
510
511 static void
validate_buffer(guint index,const gchar * field,...)512 validate_buffer (guint index, const gchar * field, ...)
513 {
514 GstBuffer *buf;
515 va_list var_args;
516
517 fail_if (index >= g_list_length (buffers));
518 buf = GST_BUFFER (g_list_nth_data (buffers, (index)));
519 fail_if (buf == NULL);
520
521 GST_TRACE ("%" GST_PTR_FORMAT, buf);
522
523 va_start (var_args, field);
524 while (field) {
525 if (!g_strcmp0 (field, "pts")) {
526 GstClockTime pts = va_arg (var_args, GstClockTime);
527 fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), pts);
528 } else if (!g_strcmp0 (field, "offset")) {
529 guint64 offset = va_arg (var_args, guint64);
530 fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buf), offset);
531 } else if (!g_strcmp0 (field, "discont")) {
532 gboolean discont = va_arg (var_args, gboolean);
533 if (discont) {
534 fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
535 } else {
536 fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
537 }
538 } else {
539 fail ("test cannot validate unknown buffer field '%s'", field);
540 }
541 field = va_arg (var_args, const gchar *);
542 }
543 va_end (var_args);
544 }
545
546 static State *
create_depayloader(const gchar * caps_str,const gchar * property,...)547 create_depayloader (const gchar * caps_str, const gchar * property, ...)
548 {
549 va_list var_args;
550 GstCaps *caps;
551 State *state;
552
553 state = g_new0 (State, 1);
554
555 state->element = GST_ELEMENT (rtp_dummy_depay_new ());
556 fail_unless (GST_IS_RTP_DUMMY_DEPAY (state->element));
557
558 va_start (var_args, property);
559 g_object_set_valist (G_OBJECT (state->element), property, var_args);
560 va_end (var_args);
561
562 state->srcpad = gst_check_setup_src_pad (state->element, &srctemplate);
563 state->sinkpad = gst_check_setup_sink_pad (state->element, &sinktemplate);
564
565 fail_unless (gst_pad_set_active (state->srcpad, TRUE));
566 fail_unless (gst_pad_set_active (state->sinkpad, TRUE));
567
568 if (caps_str) {
569 caps = gst_caps_from_string (caps_str);
570 } else {
571 caps = NULL;
572 }
573 gst_check_setup_events (state->srcpad, state->element, caps, GST_FORMAT_TIME);
574 if (caps) {
575 gst_caps_unref (caps);
576 }
577
578 gst_pad_set_chain_function (state->sinkpad, gst_check_chain_func);
579 gst_pad_set_event_function (state->sinkpad, event_func);
580
581 return state;
582 }
583
584 static void
set_state(State * state,GstState new_state)585 set_state (State * state, GstState new_state)
586 {
587 fail_unless_equals_int (gst_element_set_state (state->element, new_state),
588 GST_STATE_CHANGE_SUCCESS);
589 }
590
591 static void
packet_lost(State * state,GstClockTime timestamp,GstClockTime duration,gboolean might_have_been_fec)592 packet_lost (State * state, GstClockTime timestamp, GstClockTime duration,
593 gboolean might_have_been_fec)
594 {
595 GstEvent *event;
596 guint seqnum = 0x4243;
597 gboolean late = TRUE;
598 guint retries = 42;
599
600 event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
601 gst_structure_new ("GstRTPPacketLost",
602 "seqnum", G_TYPE_UINT, seqnum,
603 "timestamp", G_TYPE_UINT64, timestamp,
604 "duration", G_TYPE_UINT64, duration,
605 "might-have-been-fec", G_TYPE_BOOLEAN, might_have_been_fec,
606 "late", G_TYPE_BOOLEAN, late, "retry", G_TYPE_UINT, retries, NULL));
607
608 fail_unless (gst_pad_push_event (state->srcpad, event));
609 }
610
611 static void
reconfigure_caps(State * state,const gchar * caps_str)612 reconfigure_caps (State * state, const gchar * caps_str)
613 {
614 GstCaps *newcaps;
615 GstEvent *event;
616 newcaps = gst_caps_from_string (caps_str);
617 event = gst_event_new_caps (newcaps);
618 gst_caps_unref (newcaps);
619 fail_unless (gst_pad_push_event (state->srcpad, event));
620 }
621
622 static void
flush_pipeline(State * state)623 flush_pipeline (State * state)
624 {
625 GstEvent *event;
626 GstSegment segment;
627 event = gst_event_new_flush_start ();
628 fail_unless (gst_pad_push_event (state->srcpad, event));
629 event = gst_event_new_flush_stop (TRUE);
630 fail_unless (gst_pad_push_event (state->srcpad, event));
631 gst_segment_init (&segment, GST_FORMAT_TIME);
632 event = gst_event_new_segment (&segment);
633 fail_unless (gst_pad_push_event (state->srcpad, event));
634 }
635
636 static void
destroy_depayloader(State * state)637 destroy_depayloader (State * state)
638 {
639 gst_check_teardown_sink_pad (state->element);
640 gst_check_teardown_src_pad (state->element);
641
642 gst_check_drop_buffers ();
643 drop_events ();
644
645 g_object_unref (state->element);
646
647 g_free (state);
648 }
649
650 /* Tests */
651
652 /* send two RTP packets having sequential sequence numbers and timestamps
653 * differing by DEFAULT_CLOCK_RATE. the depayloader first pushes the normal
654 * stream-start, caps and segment events downstream before processing each RTP
655 * packet and pushing a corresponding buffer. PTS will be carried over from the
656 * RTP packets by the payloader to the buffers. because the sequence numbers are
657 * sequential then GST_BUFFER_FLAG_DISCONT will not be set for either buffer.
658 */
GST_START_TEST(rtp_base_depayload_buffer_test)659 GST_START_TEST (rtp_base_depayload_buffer_test)
660 {
661 State *state;
662
663 state = create_depayloader ("application/x-rtp", NULL);
664
665 set_state (state, GST_STATE_PLAYING);
666
667 push_rtp_buffer (state,
668 "pts", 0 * GST_SECOND,
669 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
670
671 push_rtp_buffer (state,
672 "pts", 1 * GST_SECOND,
673 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
674 "seq", 0x4242 + 1, NULL);
675
676 set_state (state, GST_STATE_NULL);
677
678 validate_buffers_received (2);
679
680 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
681
682 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
683
684 validate_events_received (3);
685
686 validate_event (0, "stream-start", NULL);
687
688 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
689
690 validate_event (2, "segment",
691 "time", G_GUINT64_CONSTANT (0),
692 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
693
694 destroy_depayloader (state);
695 }
696
697 GST_END_TEST
698 /* the intent with this test is to provide the depayloader with a buffer that
699 * does not contain an RTP header. this makes it impossible for the depayloader
700 * to depayload the incoming RTP packet, yet the stream-start and caps events
701 * will still be pushed.
702 */
GST_START_TEST(rtp_base_depayload_invalid_rtp_packet_test)703 GST_START_TEST (rtp_base_depayload_invalid_rtp_packet_test)
704 {
705 State *state;
706
707 state = create_depayloader ("application/x-rtp", NULL);
708
709 set_state (state, GST_STATE_PLAYING);
710
711 push_buffer (state,
712 "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
713
714 set_state (state, GST_STATE_NULL);
715
716 validate_buffers_received (0);
717
718 validate_events_received (2);
719
720 validate_event (0, "stream-start", NULL);
721
722 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
723
724 destroy_depayloader (state);
725 }
726
727 GST_END_TEST
728 /* validate what happens when a depayloader is provided with two RTP packets
729 * sent after each other that do not have sequential sequence numbers. in this
730 * case the depayloader should be able to depayload both first and the second
731 * buffer, but the second buffer will have GST_BUFFER_FLAG_DISCONT set to
732 * indicate that the was a discontinuity in the stream. the initial events are
733 * pushed prior to the buffers arriving so they should be unaffected by the gap
734 * in sequence numbers.
735 */
GST_START_TEST(rtp_base_depayload_with_gap_test)736 GST_START_TEST (rtp_base_depayload_with_gap_test)
737 {
738 State *state;
739
740 state = create_depayloader ("application/x-rtp", NULL);
741
742 set_state (state, GST_STATE_PLAYING);
743
744 push_rtp_buffer (state,
745 "pts", 0 * GST_SECOND,
746 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
747
748 push_rtp_buffer (state,
749 "pts", 1 * GST_SECOND,
750 "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
751 "seq", 0x4242 + 2, NULL);
752
753 set_state (state, GST_STATE_NULL);
754
755 validate_buffers_received (2);
756
757 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
758
759 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
760
761 validate_events_received (3);
762
763 validate_event (0, "stream-start", NULL);
764
765 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
766
767 validate_event (2, "segment",
768 "time", G_GUINT64_CONSTANT (0),
769 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
770
771 destroy_depayloader (state);
772 }
773
774 GST_END_TEST
775 /* two RTP packets are pushed in this test, and while the sequence numbers are
776 * sequential they are reversed. the expectation is that the depayloader will be
777 * able to depayload the first RTP packet, but once the second RTP packet
778 * arrives it will be discarded because it arrived too late. the initial events
779 * should be unaffected by the reversed buffers.
780 */
GST_START_TEST(rtp_base_depayload_reversed_test)781 GST_START_TEST (rtp_base_depayload_reversed_test)
782 {
783 State *state;
784
785 state = create_depayloader ("application/x-rtp", NULL);
786
787 set_state (state, GST_STATE_PLAYING);
788
789 push_rtp_buffer (state,
790 "pts", 0 * GST_SECOND,
791 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
792
793 push_rtp_buffer (state,
794 "pts", 1 * GST_SECOND,
795 "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
796 "seq", 0x4242 - 1, NULL);
797
798 set_state (state, GST_STATE_NULL);
799
800 validate_buffers_received (1);
801
802 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
803
804 validate_events_received (3);
805
806 validate_event (0, "stream-start", NULL);
807
808 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
809
810 validate_event (2, "segment",
811 "time", G_GUINT64_CONSTANT (0),
812 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
813
814 destroy_depayloader (state);
815 }
816
817 GST_END_TEST
818 /* The same scenario as in rtp_base_depayload_reversed_test
819 * except that SSRC is changed for the 2nd packet that is why
820 * it should not be discarded.
821 */
GST_START_TEST(rtp_base_depayload_ssrc_changed_test)822 GST_START_TEST (rtp_base_depayload_ssrc_changed_test)
823 {
824 State *state;
825
826 state = create_depayloader ("application/x-rtp", NULL);
827
828 set_state (state, GST_STATE_PLAYING);
829
830 push_rtp_buffer (state,
831 "pts", 0 * GST_SECOND,
832 "rtptime", G_GUINT64_CONSTANT (0x43214321),
833 "seq", 0x4242, "ssrc", 0xabe2b0b, NULL);
834
835 push_rtp_buffer (state,
836 "pts", 1 * GST_SECOND,
837 "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
838 "seq", 0x4242 - 1, "ssrc", 0xcafebabe, NULL);
839
840 set_state (state, GST_STATE_NULL);
841
842 validate_buffers_received (2);
843
844 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
845
846 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
847
848 validate_events_received (3);
849
850 validate_event (0, "stream-start", NULL);
851
852 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
853
854 validate_event (2, "segment",
855 "time", G_GUINT64_CONSTANT (0),
856 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
857
858 destroy_depayloader (state);
859 }
860
861 GST_END_TEST
862 /* the intent of this test is to push two RTP packets that have reverse sequence
863 * numbers that differ significantly. the depayloader will consider RTP packets
864 * where the sequence numbers differ by more than 1000 to indicate that the
865 * source of the RTP packets has been restarted. therefore it will let both
866 * depayloaded buffers through, but the latter buffer marked
867 * GST_BUFFER_FLAG_DISCONT to indicate the discontinuity in the stream. the
868 * initial events should be unaffected by the reversed buffers.
869 */
GST_START_TEST(rtp_base_depayload_old_reversed_test)870 GST_START_TEST (rtp_base_depayload_old_reversed_test)
871 {
872 State *state;
873
874 state = create_depayloader ("application/x-rtp", NULL);
875
876 set_state (state, GST_STATE_PLAYING);
877
878 push_rtp_buffer (state,
879 "pts", 0 * GST_SECOND,
880 "rtptime", G_GUINT64_CONSTANT (0x43214321), "seq", 0x4242, NULL);
881
882 push_rtp_buffer (state,
883 "pts", 1 * GST_SECOND,
884 "rtptime", G_GUINT64_CONSTANT (0x43214321) + 1 * DEFAULT_CLOCK_RATE,
885 "seq", 0x4242 - 1000, NULL);
886
887 set_state (state, GST_STATE_NULL);
888
889 validate_buffers_received (2);
890
891 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
892
893 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", TRUE, NULL);
894
895 validate_events_received (3);
896
897 validate_event (0, "stream-start", NULL);
898
899 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
900
901 validate_event (2, "segment",
902 "time", G_GUINT64_CONSTANT (0),
903 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
904
905 destroy_depayloader (state);
906 }
907
908 GST_END_TEST
909 /* a depayloader that has not received any caps event will not be able to
910 * process any incoming RTP packet. instead pushing an RTP packet should result
911 * in the expected error.
912 */
GST_START_TEST(rtp_base_depayload_without_negotiation_test)913 GST_START_TEST (rtp_base_depayload_without_negotiation_test)
914 {
915 State *state;
916
917 state = create_depayloader (NULL, NULL);
918
919 set_state (state, GST_STATE_PLAYING);
920
921 push_rtp_buffer_fails (state, GST_FLOW_NOT_NEGOTIATED,
922 "pts", 0 * GST_SECOND,
923 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
924
925 set_state (state, GST_STATE_NULL);
926
927 validate_buffers_received (0);
928
929 validate_events_received (1);
930
931 validate_event (0, "stream-start", NULL);
932
933 destroy_depayloader (state);
934 }
935
936 GST_END_TEST
937 /* a depayloader that receives the downstream event GstRTPPacketLost should
938 * respond by emitting a gap event with the corresponding timestamp and
939 * duration. the initial events are unaffected, but are succeeded by the added
940 * gap event.
941 */
GST_START_TEST(rtp_base_depayload_packet_lost_test)942 GST_START_TEST (rtp_base_depayload_packet_lost_test)
943 {
944 State *state;
945
946 state = create_depayloader ("application/x-rtp", NULL);
947
948 set_state (state, GST_STATE_PLAYING);
949
950 push_rtp_buffer (state,
951 "pts", 0 * GST_SECOND,
952 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
953
954 packet_lost (state, 1 * GST_SECOND, GST_SECOND, FALSE);
955
956 /* If a packet was lost but we don't know whether it was a FEC packet,
957 * the depayloader should not generate gap events */
958 packet_lost (state, 2 * GST_SECOND, GST_SECOND, TRUE);
959
960 push_rtp_buffer (state,
961 "pts", 2 * GST_SECOND,
962 "rtptime", G_GUINT64_CONSTANT (0x1234) + 2 * DEFAULT_CLOCK_RATE,
963 "seq", 0x4242 + 2, NULL);
964
965 set_state (state, GST_STATE_NULL);
966
967 validate_buffers_received (2);
968
969 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
970
971 validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
972
973 validate_events_received (4);
974
975 validate_event (0, "stream-start", NULL);
976
977 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
978
979 validate_event (2, "segment",
980 "time", G_GUINT64_CONSTANT (0),
981 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
982
983 validate_event (3, "gap",
984 "timestamp", 1 * GST_SECOND, "duration", GST_SECOND, NULL);
985
986 destroy_depayloader (state);
987 }
988
989 GST_END_TEST
990 /* If a lost event is received before the first buffer, the rtp base
991 * depayloader will not send a gap event downstream. Alternatively it should
992 * make sure that stream-start, caps and segment events are sent in correct
993 * order before the gap event so that packet loss concealment can take place
994 * downstream, but this is more complicated and without any real benefit since
995 * concealment before any data is received is not very useful. */
GST_START_TEST(rtp_base_depayload_packet_lost_before_first_buffer_test)996 GST_START_TEST (rtp_base_depayload_packet_lost_before_first_buffer_test)
997 {
998 GstHarness *h;
999 GstEvent *event;
1000 GstRtpDummyDepay *depay;
1001 const GstEventType etype[] = {
1002 GST_EVENT_STREAM_START, GST_EVENT_CAPS, GST_EVENT_SEGMENT
1003 };
1004 gint i;
1005
1006 depay = rtp_dummy_depay_new ();
1007 h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1008 gst_harness_set_src_caps_str (h, "application/x-rtp");
1009
1010 /* Verify that depayloader has received setup events */
1011 for (i = 0; i < 3; i++) {
1012 event = gst_pad_get_sticky_event (h->srcpad, etype[i], 0);
1013 fail_unless (event != NULL);
1014 gst_event_unref (event);
1015 }
1016
1017 /* Send loss event to depayloader */
1018 gst_harness_push_event (h, gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
1019 gst_structure_new ("GstRTPPacketLost",
1020 "seqnum", G_TYPE_UINT, (guint) 0,
1021 "timestamp", G_TYPE_UINT64, (guint64) 0,
1022 "duration", G_TYPE_UINT64, (guint64) 10 * GST_MSECOND, NULL)));
1023
1024 /* When a buffer is pushed, an updated (and more accurate) segment event
1025 * should also be sent. */
1026 gst_harness_push (h, gst_rtp_buffer_new_allocate (0, 0, 0));
1027
1028 /* Verify that setup events are sent before gap event */
1029 for (i = 0; i < 3; i++) {
1030 fail_unless (event = gst_harness_pull_event (h));
1031 fail_unless_equals_int (GST_EVENT_TYPE (event), etype[i]);
1032 gst_event_unref (event);
1033 }
1034 fail_unless_equals_int (gst_harness_events_in_queue (h), 0);
1035
1036 gst_buffer_unref (gst_harness_pull (h));
1037 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1038
1039 g_object_unref (depay);
1040 gst_harness_teardown (h);
1041 }
1042
1043 GST_END_TEST;
1044 /* rtp base depayloader should set DISCONT flag on buffer in case of a large
1045 * sequence number gap, and it's not set already by upstream. This tests a
1046 * certain code path where the buffer needs to be made writable to set the
1047 * DISCONT flag.
1048 */
GST_START_TEST(rtp_base_depayload_seq_discont_test)1049 GST_START_TEST (rtp_base_depayload_seq_discont_test)
1050 {
1051 State *state;
1052
1053 state = create_depayloader ("application/x-rtp", NULL);
1054
1055 set_state (state, GST_STATE_PLAYING);
1056
1057 push_rtp_buffer (state,
1058 "pts", 0 * GST_SECOND,
1059 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 1, NULL);
1060
1061 push_rtp_buffer (state,
1062 "extra-ref", TRUE,
1063 "pts", 2 * GST_SECOND,
1064 "rtptime", G_GUINT64_CONSTANT (0x1234) + DEFAULT_CLOCK_RATE / 2,
1065 "seq", 33333, NULL);
1066
1067 set_state (state, GST_STATE_NULL);
1068
1069 validate_buffers_received (2);
1070
1071 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1072
1073 validate_buffer (1, "pts", 2 * GST_SECOND, "discont", TRUE, NULL);
1074
1075 destroy_depayloader (state);
1076 }
1077
1078 GST_END_TEST
1079 /* a depayloader that receives identical caps events simply ignores the latter
1080 * events without propagating them downstream.
1081 */
GST_START_TEST(rtp_base_depayload_repeated_caps_test)1082 GST_START_TEST (rtp_base_depayload_repeated_caps_test)
1083 {
1084 State *state;
1085
1086 state = create_depayloader ("application/x-rtp", NULL);
1087
1088 set_state (state, GST_STATE_PLAYING);
1089
1090 push_rtp_buffer (state,
1091 "pts", 0 * GST_SECOND,
1092 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1093
1094 reconfigure_caps (state, "application/x-rtp");
1095
1096 push_rtp_buffer (state,
1097 "pts", 1 * GST_SECOND,
1098 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1099 "seq", 0x4242 + 1, NULL);
1100
1101 set_state (state, GST_STATE_NULL);
1102
1103 validate_buffers_received (2);
1104
1105 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1106
1107 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1108
1109 validate_events_received (3);
1110
1111 validate_event (0, "stream-start", NULL);
1112
1113 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1114
1115 validate_event (2, "segment",
1116 "time", G_GUINT64_CONSTANT (0),
1117 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1118
1119 destroy_depayloader (state);
1120 }
1121
1122 GST_END_TEST
1123 /* when a depayloader receives new caps events with npt-start and npt-stop times
1124 * it should save these timestamps as they should affect the next segment event
1125 * being pushed by the depayloader. a new segment event is not pushed by the
1126 * depayloader until a flush_stop event and a succeeding segment event are
1127 * received. of course the initial event are unaffected, as is the incoming caps
1128 * event.
1129 */
GST_START_TEST(rtp_base_depayload_npt_test)1130 GST_START_TEST (rtp_base_depayload_npt_test)
1131 {
1132 State *state;
1133
1134 state = create_depayloader ("application/x-rtp", NULL);
1135
1136 set_state (state, GST_STATE_PLAYING);
1137
1138 push_rtp_buffer (state,
1139 "pts", 0 * GST_SECOND,
1140 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1141
1142 reconfigure_caps (state,
1143 "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321");
1144
1145 flush_pipeline (state);
1146
1147 push_rtp_buffer (state,
1148 "pts", 1 * GST_SECOND,
1149 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1150 "seq", 0x4242 + 1, NULL);
1151
1152 set_state (state, GST_STATE_NULL);
1153
1154 validate_buffers_received (2);
1155
1156 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1157
1158 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1159
1160 validate_events_received (7);
1161
1162 validate_event (0, "stream-start", NULL);
1163
1164 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1165
1166 validate_event (2, "segment",
1167 "time", G_GUINT64_CONSTANT (0),
1168 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1169
1170 validate_event (3, "caps",
1171 "media-type", "application/x-rtp",
1172 "npt-start", G_GUINT64_CONSTANT (1234),
1173 "npt-stop", G_GUINT64_CONSTANT (4321), NULL);
1174
1175 validate_event (4, "flush-start", NULL);
1176
1177 validate_event (5, "flush-stop", NULL);
1178
1179 validate_event (6, "segment",
1180 "time", G_GUINT64_CONSTANT (1234),
1181 "start", G_GUINT64_CONSTANT (0),
1182 "stop", G_GUINT64_CONSTANT (4321 - 1234), NULL);
1183
1184 destroy_depayloader (state);
1185 }
1186
1187 GST_END_TEST
1188 /* when a depayloader receives a new caps event with play-scale it should save
1189 * this rate as it should affect the next segment event being pushed by the
1190 * depayloader. a new segment event is not pushed by the depayloader until a
1191 * flush_stop event and a succeeding segment event are received. of course the
1192 * initial event are unaffected, as is the incoming caps event.
1193 */
GST_START_TEST(rtp_base_depayload_play_scale_test)1194 GST_START_TEST (rtp_base_depayload_play_scale_test)
1195 {
1196 State *state;
1197
1198 state = create_depayloader ("application/x-rtp", NULL);
1199
1200 set_state (state, GST_STATE_PLAYING);
1201
1202 push_rtp_buffer (state,
1203 "pts", 0 * GST_SECOND,
1204 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1205
1206 reconfigure_caps (state, "application/x-rtp, play-scale=(double)2.0");
1207
1208 flush_pipeline (state);
1209
1210 push_rtp_buffer (state,
1211 "pts", 1 * GST_SECOND,
1212 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1213 "seq", 0x4242 + 1, NULL);
1214
1215 set_state (state, GST_STATE_NULL);
1216
1217 validate_buffers_received (2);
1218
1219 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1220
1221 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1222
1223 validate_events_received (7);
1224
1225 validate_event (0, "stream-start", NULL);
1226
1227 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1228
1229 validate_event (2, "segment",
1230 "time", G_GUINT64_CONSTANT (0),
1231 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1232
1233 validate_event (3, "caps",
1234 "media-type", "application/x-rtp", "play-scale", 2.0, NULL);
1235
1236 validate_event (4, "flush-start", NULL);
1237
1238 validate_event (5, "flush-stop", NULL);
1239
1240 validate_event (6, "segment",
1241 "time", G_GUINT64_CONSTANT (0),
1242 "start", G_GUINT64_CONSTANT (0),
1243 "stop", G_MAXUINT64, "rate", 1.0, "applied-rate", 2.0, NULL);
1244
1245 destroy_depayloader (state);
1246 }
1247
1248 GST_END_TEST
1249 /* when a depayloader receives a new caps event with play-speed it should save
1250 * this rate as it should affect the next segment event being pushed by the
1251 * depayloader. a new segment event is not pushed by the depayloader until a
1252 * flush_stop event and a succeeding segment event are received. of course the
1253 * initial event are unaffected, as is the incoming caps event.
1254 */
GST_START_TEST(rtp_base_depayload_play_speed_test)1255 GST_START_TEST (rtp_base_depayload_play_speed_test)
1256 {
1257 State *state;
1258
1259 state = create_depayloader ("application/x-rtp", NULL);
1260
1261 set_state (state, GST_STATE_PLAYING);
1262
1263 push_rtp_buffer (state,
1264 "pts", 0 * GST_SECOND,
1265 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1266
1267 reconfigure_caps (state, "application/x-rtp, play-speed=(double)2.0");
1268
1269 flush_pipeline (state);
1270
1271 push_rtp_buffer (state,
1272 "pts", 1 * GST_SECOND,
1273 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1274 "seq", 0x4242 + 1, NULL);
1275
1276 set_state (state, GST_STATE_NULL);
1277
1278 validate_buffers_received (2);
1279
1280 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1281
1282 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1283
1284 validate_events_received (7);
1285
1286 validate_event (0, "stream-start", NULL);
1287
1288 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1289
1290 validate_event (2, "segment",
1291 "time", G_GUINT64_CONSTANT (0),
1292 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1293
1294 validate_event (3, "caps",
1295 "media-type", "application/x-rtp", "play-speed", 2.0, NULL);
1296
1297 validate_event (4, "flush-start", NULL);
1298
1299 validate_event (5, "flush-stop", NULL);
1300
1301 validate_event (6, "segment",
1302 "time", G_GUINT64_CONSTANT (0),
1303 "start", G_GUINT64_CONSTANT (0),
1304 "stop", G_MAXUINT64, "rate", 2.0, "applied-rate", 1.0, NULL);
1305
1306 destroy_depayloader (state);
1307 }
1308
1309 GST_END_TEST
1310 /* when a depayloader receives new caps events with npt-start, npt-stop and
1311 * clock-base it should save these timestamps as they should affect the next
1312 * segment event being pushed by the depayloader. the produced segment should
1313 * make the position of the stream reflect the position from clock-base instead
1314 * of reflecting the running time (for RTSP).
1315 */
GST_START_TEST(rtp_base_depayload_clock_base_test)1316 GST_START_TEST (rtp_base_depayload_clock_base_test)
1317 {
1318 State *state;
1319
1320 state = create_depayloader ("application/x-rtp", NULL);
1321
1322 set_state (state, GST_STATE_PLAYING);
1323
1324 push_rtp_buffer (state,
1325 "pts", 0 * GST_SECOND,
1326 "rtptime", G_GUINT64_CONSTANT (1234), "seq", 0x4242, NULL);
1327
1328 reconfigure_caps (state,
1329 "application/x-rtp, npt-start=(guint64)1234, npt-stop=(guint64)4321, clock-base=(guint)1234");
1330
1331 flush_pipeline (state);
1332
1333 push_rtp_buffer (state,
1334 "pts", 1 * GST_SECOND,
1335 "rtptime", G_GUINT64_CONSTANT (1234) + 1 * DEFAULT_CLOCK_RATE,
1336 "seq", 0x4242 + 1, NULL);
1337
1338 set_state (state, GST_STATE_NULL);
1339
1340 validate_buffers_received (2);
1341
1342 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1343
1344 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1345
1346 validate_events_received (7);
1347
1348 validate_event (0, "stream-start", NULL);
1349
1350 validate_event (1, "caps", "media-type", "application/x-rtp", NULL);
1351
1352 validate_event (2, "segment",
1353 "time", G_GUINT64_CONSTANT (0),
1354 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
1355
1356 validate_event (3, "caps",
1357 "media-type", "application/x-rtp",
1358 "npt-start", G_GUINT64_CONSTANT (1234),
1359 "npt-stop", G_GUINT64_CONSTANT (4321), "clock-base", 1234, NULL);
1360
1361 validate_event (4, "flush-start", NULL);
1362
1363 validate_event (5, "flush-stop", NULL);
1364
1365 validate_event (6, "segment",
1366 "time", G_GUINT64_CONSTANT (1234),
1367 "start", GST_SECOND,
1368 "stop", GST_SECOND + G_GUINT64_CONSTANT (4321 - 1234),
1369 "base", GST_SECOND, NULL);
1370
1371 destroy_depayloader (state);
1372 }
1373
1374 GST_END_TEST
1375 /* basedepayloader has a property source-info that will add
1376 * GstRTPSourceMeta to the output buffer with RTP source information, such as
1377 * SSRC and CSRCs. The is useful for letting downstream know about the origin
1378 * of the stream. */
GST_START_TEST(rtp_base_depayload_source_info_test)1379 GST_START_TEST (rtp_base_depayload_source_info_test)
1380 {
1381 GstHarness *h;
1382 GstRtpDummyDepay *depay;
1383 GstBuffer *buffer;
1384 GstRTPSourceMeta *meta;
1385 guint seq = 0;
1386
1387 depay = rtp_dummy_depay_new ();
1388 h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1389 gst_harness_set_src_caps_str (h, "application/x-rtp");
1390
1391 /* Property enabled should always add meta, also when there is only SSRC and
1392 * no CSRC. */
1393 g_object_set (depay, "source-info", TRUE, NULL);
1394 buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1395 rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1396 buffer = gst_harness_push_and_pull (h, buffer);
1397 fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1398 fail_unless (meta->ssrc_valid);
1399 fail_unless_equals_int (meta->ssrc, 0x11);
1400 fail_unless_equals_int (meta->csrc_count, 0);
1401 gst_buffer_unref (buffer);
1402
1403 /* Both SSRC and CSRC should be added to the meta */
1404 buffer = gst_rtp_buffer_new_allocate (0, 0, 2);
1405 rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, "csrc", 0, 0x22,
1406 "csrc", 1, 0x33, NULL);
1407 buffer = gst_harness_push_and_pull (h, buffer);
1408 fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1409 fail_unless (meta->ssrc_valid);
1410 fail_unless_equals_int (meta->ssrc, 0x11);
1411 fail_unless_equals_int (meta->csrc_count, 2);
1412 fail_unless_equals_int (meta->csrc[0], 0x22);
1413 fail_unless_equals_int (meta->csrc[1], 0x33);
1414 gst_buffer_unref (buffer);
1415
1416 /* Property disabled should never add meta */
1417 g_object_set (depay, "source-info", FALSE, NULL);
1418 buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1419 rtp_buffer_set (buffer, "seq", seq++, "ssrc", 0x11, NULL);
1420 buffer = gst_harness_push_and_pull (h, buffer);
1421 fail_if (gst_buffer_get_rtp_source_meta (buffer));
1422 gst_buffer_unref (buffer);
1423
1424 g_object_unref (depay);
1425 gst_harness_teardown (h);
1426 }
1427
1428 GST_END_TEST;
1429
1430 /* verify that if a buffer arriving in the depayloader already has source-info
1431 meta on it, that this does not affect the source-info coming out of the
1432 depayloder, which should be all derived from the rtp-header */
GST_START_TEST(rtp_base_depayload_source_info_from_rtp_only)1433 GST_START_TEST (rtp_base_depayload_source_info_from_rtp_only)
1434 {
1435 GstHarness *h;
1436 GstRtpDummyDepay *depay;
1437 GstBuffer *buffer;
1438 GstRTPSourceMeta *meta;
1439 guint rtp_ssrc = 0x11;
1440 guint rtp_csrc = 0x22;
1441 guint32 meta_ssrc = 0x55;
1442 guint32 meta_csrc = 0x66;
1443
1444 depay = rtp_dummy_depay_new ();
1445 h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1446 gst_harness_set_src_caps_str (h, "application/x-rtp");
1447
1448 g_object_set (depay, "source-info", TRUE, NULL);
1449 buffer = gst_rtp_buffer_new_allocate (0, 0, 1);
1450 rtp_buffer_set (buffer, "seq", 0, "ssrc", rtp_ssrc, "csrc", 0, rtp_csrc,
1451 NULL);
1452 meta = gst_buffer_add_rtp_source_meta (buffer, &meta_ssrc, &meta_csrc, 1);
1453
1454 buffer = gst_harness_push_and_pull (h, buffer);
1455 fail_unless ((meta = gst_buffer_get_rtp_source_meta (buffer)));
1456 fail_unless (meta->ssrc_valid);
1457 fail_unless_equals_int (meta->ssrc, rtp_ssrc);
1458 fail_unless_equals_int (meta->csrc_count, 1);
1459 fail_unless_equals_int (meta->csrc[0], rtp_csrc);
1460 gst_buffer_unref (buffer);
1461
1462 g_object_unref (depay);
1463 gst_harness_teardown (h);
1464 }
1465
1466 GST_END_TEST;
1467
1468 /* Test max-reorder property. Reordered packets with a gap less than
1469 * max-reordered will be dropped, reordered packets with gap larger than
1470 * max-reorder is considered coming fra a restarted sender and should not be
1471 * dropped. */
GST_START_TEST(rtp_base_depayload_max_reorder)1472 GST_START_TEST (rtp_base_depayload_max_reorder)
1473 {
1474 GstHarness *h;
1475 GstRtpDummyDepay *depay;
1476 guint seq = 1000;
1477
1478 depay = rtp_dummy_depay_new ();
1479 h = gst_harness_new_with_element (GST_ELEMENT_CAST (depay), "sink", "src");
1480 gst_harness_set_src_caps_str (h, "application/x-rtp");
1481
1482 #define PUSH_AND_CHECK(seqnum, pushed) G_STMT_START { \
1483 GstBuffer *buffer = gst_rtp_buffer_new_allocate (0, 0, 0); \
1484 rtp_buffer_set (buffer, "seq", seqnum, "ssrc", 0x11, NULL); \
1485 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, buffer)); \
1486 fail_unless_equals_int (gst_harness_buffers_in_queue (h), pushed); \
1487 if (pushed) \
1488 gst_buffer_unref (gst_harness_pull (h)); \
1489 } G_STMT_END;
1490
1491 /* By default some reordering is accepted. Old seqnums should be
1492 * dropped, but not too old */
1493 PUSH_AND_CHECK (seq, TRUE);
1494 PUSH_AND_CHECK (seq - 50, FALSE);
1495 PUSH_AND_CHECK (seq - 100, TRUE);
1496
1497 /* Update property to allow less reordering */
1498 g_object_set (depay, "max-reorder", 3, NULL);
1499
1500 /* Gaps up to max allowed reordering is dropped. */
1501 PUSH_AND_CHECK (seq, TRUE);
1502 PUSH_AND_CHECK (seq - 2, FALSE);
1503 PUSH_AND_CHECK (seq - 3, TRUE);
1504
1505 /* After a push the initial state should be reset, so a duplicate of the
1506 * last packet should be dropped */
1507 PUSH_AND_CHECK (seq - 3, FALSE);
1508
1509 /* Update property to minimum value. Should never drop buffers. */
1510 g_object_set (depay, "max-reorder", 0, NULL);
1511
1512 /* Duplicate buffer should now be pushed. */
1513 PUSH_AND_CHECK (seq, TRUE);
1514 PUSH_AND_CHECK (seq, TRUE);
1515
1516 g_object_unref (depay);
1517 gst_harness_teardown (h);
1518 }
1519
1520 GST_END_TEST;
1521
GST_START_TEST(rtp_base_depayload_flow_return_push_func)1522 GST_START_TEST (rtp_base_depayload_flow_return_push_func)
1523 {
1524 State *state;
1525
1526 state = create_depayloader ("application/x-rtp", NULL);
1527
1528 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1529 GST_RTP_DUMMY_USE_PUSH_LIST_FUNC;
1530
1531 set_state (state, GST_STATE_PLAYING);
1532
1533 GST_PAD_SET_FLUSHING (state->sinkpad);
1534
1535 push_rtp_buffer_fails (state, GST_FLOW_FLUSHING,
1536 "pts", 0 * GST_SECOND,
1537 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1538
1539 set_state (state, GST_STATE_NULL);
1540
1541 destroy_depayloader (state);
1542 }
1543
1544 GST_END_TEST;
1545
GST_START_TEST(rtp_base_depayload_flow_return_push_list_func)1546 GST_START_TEST (rtp_base_depayload_flow_return_push_list_func)
1547 {
1548 State *state;
1549
1550 state = create_depayloader ("application/x-rtp", NULL);
1551
1552 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1553 GST_RTP_DUMMY_USE_PUSH_FUNC;
1554
1555 set_state (state, GST_STATE_PLAYING);
1556
1557 GST_PAD_SET_FLUSHING (state->sinkpad);
1558
1559 push_rtp_buffer_fails (state, GST_FLOW_FLUSHING,
1560 "pts", 0 * GST_SECOND,
1561 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1562
1563 set_state (state, GST_STATE_NULL);
1564
1565 destroy_depayloader (state);
1566 }
1567
1568 GST_END_TEST;
1569
GST_START_TEST(rtp_base_depayload_one_byte_hdr_ext)1570 GST_START_TEST (rtp_base_depayload_one_byte_hdr_ext)
1571 {
1572 GstRTPHeaderExtension *ext;
1573 State *state;
1574
1575 state = create_depayloader ("application/x-rtp", NULL);
1576 ext = rtp_dummy_hdr_ext_new ();
1577 gst_rtp_header_extension_set_id (ext, 1);
1578
1579 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1580 GST_RTP_DUMMY_RETURN_TO_PUSH;
1581
1582 g_signal_emit_by_name (state->element, "add-extension", ext);
1583
1584 set_state (state, GST_STATE_PLAYING);
1585
1586 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1587 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1588 NULL);
1589
1590 set_state (state, GST_STATE_NULL);
1591
1592 validate_buffers_received (1);
1593
1594 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1595
1596 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1597
1598 gst_object_unref (ext);
1599 destroy_depayloader (state);
1600 }
1601
1602 GST_END_TEST;
1603
GST_START_TEST(rtp_base_depayload_two_byte_hdr_ext)1604 GST_START_TEST (rtp_base_depayload_two_byte_hdr_ext)
1605 {
1606 GstRTPHeaderExtension *ext;
1607 State *state;
1608
1609 state = create_depayloader ("application/x-rtp", NULL);
1610 ext = rtp_dummy_hdr_ext_new ();
1611 gst_rtp_header_extension_set_id (ext, 1);
1612
1613 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1614 GST_RTP_DUMMY_RETURN_TO_PUSH;
1615
1616 g_signal_emit_by_name (state->element, "add-extension", ext);
1617
1618 set_state (state, GST_STATE_PLAYING);
1619
1620 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1621 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-2", ext,
1622 NULL);
1623
1624 set_state (state, GST_STATE_NULL);
1625
1626 validate_buffers_received (1);
1627
1628 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1629
1630 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1631
1632 gst_object_unref (ext);
1633 destroy_depayloader (state);
1634 }
1635
1636 GST_END_TEST;
1637
1638 static GstRTPHeaderExtension *
request_extension(GstRTPBaseDepayload * depayload,guint ext_id,const gchar * ext_uri,gpointer user_data)1639 request_extension (GstRTPBaseDepayload * depayload, guint ext_id,
1640 const gchar * ext_uri, gpointer user_data)
1641 {
1642 GstRTPHeaderExtension *ext = user_data;
1643
1644 if (ext && gst_rtp_header_extension_get_id (ext) == ext_id
1645 && g_strcmp0 (ext_uri, gst_rtp_header_extension_get_uri (ext)) == 0)
1646 return gst_object_ref (ext);
1647
1648 return NULL;
1649 }
1650
GST_START_TEST(rtp_base_depayload_request_extension)1651 GST_START_TEST (rtp_base_depayload_request_extension)
1652 {
1653 GstRTPHeaderExtension *ext;
1654 GstRTPDummyHdrExt *dummy;
1655 State *state;
1656
1657 state =
1658 create_depayloader ("application/x-rtp,extmap-3=(string)"
1659 DUMMY_HDR_EXT_URI, NULL);
1660 ext = rtp_dummy_hdr_ext_new ();
1661 dummy = GST_RTP_DUMMY_HDR_EXT (ext);
1662 gst_rtp_header_extension_set_id (ext, 3);
1663
1664 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1665 GST_RTP_DUMMY_RETURN_TO_PUSH;
1666
1667 g_signal_connect (state->element, "request-extension",
1668 G_CALLBACK (request_extension), ext);
1669
1670 fail_unless (dummy->set_attributes_count == 0);
1671
1672 set_state (state, GST_STATE_PLAYING);
1673
1674 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1675 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1676 NULL);
1677
1678 set_state (state, GST_STATE_NULL);
1679
1680 validate_buffers_received (1);
1681
1682 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1683
1684 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1685 fail_unless (dummy->set_attributes_count == 1);
1686
1687 gst_object_unref (ext);
1688 destroy_depayloader (state);
1689 }
1690
1691 GST_END_TEST;
1692
GST_START_TEST(rtp_base_depayload_clear_extensions)1693 GST_START_TEST (rtp_base_depayload_clear_extensions)
1694 {
1695 GstRTPHeaderExtension *ext;
1696 State *state;
1697
1698 state = create_depayloader ("application/x-rtp", NULL);
1699 ext = rtp_dummy_hdr_ext_new ();
1700 gst_rtp_header_extension_set_id (ext, 1);
1701
1702 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1703 GST_RTP_DUMMY_RETURN_TO_PUSH;
1704
1705 g_signal_emit_by_name (state->element, "add-extension", ext);
1706
1707 set_state (state, GST_STATE_PLAYING);
1708
1709 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1710 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1711 NULL);
1712
1713 g_signal_emit_by_name (state->element, "clear-extensions");
1714
1715 push_rtp_buffer (state, "pts", 1 * GST_SECOND,
1716 "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE,
1717 "seq", 0x4242 + 1, "hdrext-1", ext, NULL);
1718
1719 set_state (state, GST_STATE_NULL);
1720
1721 validate_buffers_received (2);
1722
1723 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1724 validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL);
1725
1726 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1);
1727
1728 gst_object_unref (ext);
1729 destroy_depayloader (state);
1730 }
1731
1732 GST_END_TEST;
1733
GST_START_TEST(rtp_base_depayload_multiple_exts)1734 GST_START_TEST (rtp_base_depayload_multiple_exts)
1735 {
1736 GstRTPHeaderExtension *ext1;
1737 GstRTPHeaderExtension *ext2;
1738 State *state;
1739
1740 state = create_depayloader ("application/x-rtp", NULL);
1741 ext1 = rtp_dummy_hdr_ext_new ();
1742 gst_rtp_header_extension_set_id (ext1, 1);
1743 ext2 = rtp_dummy_hdr_ext_new ();
1744 gst_rtp_header_extension_set_id (ext2, 2);
1745
1746 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1747 GST_RTP_DUMMY_RETURN_TO_PUSH;
1748
1749 g_signal_emit_by_name (state->element, "add-extension", ext1);
1750 g_signal_emit_by_name (state->element, "add-extension", ext2);
1751
1752 set_state (state, GST_STATE_PLAYING);
1753
1754 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1755 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext1,
1756 "hdrext-1", ext2, NULL);
1757
1758 set_state (state, GST_STATE_NULL);
1759
1760 validate_buffers_received (1);
1761
1762 validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL);
1763
1764 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext1)->read_count, 1);
1765 fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext2)->read_count, 1);
1766
1767 gst_object_unref (ext1);
1768 gst_object_unref (ext2);
1769 destroy_depayloader (state);
1770 }
1771
1772 GST_END_TEST;
1773
1774 static GstRTPHeaderExtension *
request_extension_ignored(GstRTPBaseDepayload * depayload,guint ext_id,const gchar * ext_uri,gpointer user_data)1775 request_extension_ignored (GstRTPBaseDepayload * depayload, guint ext_id,
1776 const gchar * ext_uri, gpointer user_data)
1777 {
1778 guint *request_counter = user_data;
1779
1780 *request_counter += 1;
1781
1782 return NULL;
1783 }
1784
GST_START_TEST(rtp_base_depayload_caps_request_ignored)1785 GST_START_TEST (rtp_base_depayload_caps_request_ignored)
1786 {
1787 State *state;
1788 guint request_counter = 0;
1789
1790 state =
1791 create_depayloader ("application/x-rtp,extmap-3=(string)"
1792 DUMMY_HDR_EXT_URI, NULL);
1793
1794 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1795 GST_RTP_DUMMY_RETURN_TO_PUSH;
1796 g_signal_connect (state->element, "request-extension",
1797 G_CALLBACK (request_extension_ignored), &request_counter);
1798
1799 set_state (state, GST_STATE_PLAYING);
1800
1801 push_rtp_buffer (state,
1802 "pts", 0 * GST_SECOND,
1803 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL);
1804
1805 fail_unless_equals_int (request_counter, 1);
1806
1807 set_state (state, GST_STATE_NULL);
1808
1809 validate_buffers_received (1);
1810
1811 destroy_depayloader (state);
1812 }
1813
1814 GST_END_TEST;
1815
1816 static GstFlowReturn
hdr_ext_caps_change_chain_func(GstPad * pad,GstObject * parent,GstBuffer * buffer)1817 hdr_ext_caps_change_chain_func (GstPad * pad, GstObject * parent,
1818 GstBuffer * buffer)
1819 {
1820 GstFlowReturn res;
1821 GstCaps *caps;
1822 guint val;
1823 static guint expected_caps_val = 0;
1824
1825 res = gst_check_chain_func (pad, parent, buffer);
1826 if (res != GST_FLOW_OK) {
1827 return res;
1828 }
1829
1830 caps = gst_pad_get_current_caps (pad);
1831
1832 fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
1833 "dummy-hdrext-val", &val));
1834
1835 /* Every fifth buffer increments "dummy-hdrext-val". */
1836 if (g_list_length (buffers) % 5 == 1) {
1837 expected_caps_val++;
1838 }
1839
1840 fail_unless_equals_int (expected_caps_val, val);
1841
1842 gst_caps_unref (caps);
1843
1844 return res;
1845 }
1846
GST_START_TEST(rtp_base_depayload_hdr_ext_caps_change)1847 GST_START_TEST (rtp_base_depayload_hdr_ext_caps_change)
1848 {
1849 GstRTPHeaderExtension *ext;
1850 State *state;
1851
1852 state = create_depayloader ("application/x-rtp", NULL);
1853 gst_pad_set_chain_function (state->sinkpad, hdr_ext_caps_change_chain_func);
1854
1855 ext = rtp_dummy_hdr_ext_new ();
1856 gst_rtp_header_extension_set_id (ext, 1);
1857
1858 GST_RTP_DUMMY_DEPAY (state->element)->push_method =
1859 GST_RTP_DUMMY_USE_PUSH_LIST_FUNC;
1860 GST_RTP_DUMMY_DEPAY (state->element)->num_buffers_in_blist = 15;
1861
1862 g_signal_emit_by_name (state->element, "add-extension", ext);
1863
1864 set_state (state, GST_STATE_PLAYING);
1865
1866 push_rtp_buffer (state, "pts", 0 * GST_SECOND,
1867 "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext,
1868 NULL);
1869
1870 set_state (state, GST_STATE_NULL);
1871
1872 validate_buffers_received (15);
1873
1874 gst_object_unref (ext);
1875 destroy_depayloader (state);
1876 }
1877
1878 GST_END_TEST;
1879
1880 static Suite *
rtp_basepayloading_suite(void)1881 rtp_basepayloading_suite (void)
1882 {
1883 Suite *s = suite_create ("rtp_base_depayloading_test");
1884 TCase *tc_chain = tcase_create ("depayloading tests");
1885
1886 tcase_set_timeout (tc_chain, 60);
1887
1888 suite_add_tcase (s, tc_chain);
1889 tcase_add_test (tc_chain, rtp_base_depayload_buffer_test);
1890
1891 tcase_add_test (tc_chain, rtp_base_depayload_invalid_rtp_packet_test);
1892 tcase_add_test (tc_chain, rtp_base_depayload_with_gap_test);
1893 tcase_add_test (tc_chain, rtp_base_depayload_reversed_test);
1894 tcase_add_test (tc_chain, rtp_base_depayload_ssrc_changed_test);
1895 tcase_add_test (tc_chain, rtp_base_depayload_old_reversed_test);
1896
1897 tcase_add_test (tc_chain, rtp_base_depayload_without_negotiation_test);
1898
1899 tcase_add_test (tc_chain, rtp_base_depayload_packet_lost_test);
1900 tcase_add_test (tc_chain,
1901 rtp_base_depayload_packet_lost_before_first_buffer_test);
1902 tcase_add_test (tc_chain, rtp_base_depayload_seq_discont_test);
1903
1904 tcase_add_test (tc_chain, rtp_base_depayload_repeated_caps_test);
1905 tcase_add_test (tc_chain, rtp_base_depayload_npt_test);
1906 tcase_add_test (tc_chain, rtp_base_depayload_play_scale_test);
1907 tcase_add_test (tc_chain, rtp_base_depayload_play_speed_test);
1908 tcase_add_test (tc_chain, rtp_base_depayload_clock_base_test);
1909
1910 tcase_add_test (tc_chain, rtp_base_depayload_source_info_test);
1911 tcase_add_test (tc_chain, rtp_base_depayload_source_info_from_rtp_only);
1912 tcase_add_test (tc_chain, rtp_base_depayload_max_reorder);
1913
1914 tcase_add_test (tc_chain, rtp_base_depayload_flow_return_push_func);
1915 tcase_add_test (tc_chain, rtp_base_depayload_flow_return_push_list_func);
1916
1917 tcase_add_test (tc_chain, rtp_base_depayload_one_byte_hdr_ext);
1918 tcase_add_test (tc_chain, rtp_base_depayload_two_byte_hdr_ext);
1919 tcase_add_test (tc_chain, rtp_base_depayload_request_extension);
1920 tcase_add_test (tc_chain, rtp_base_depayload_clear_extensions);
1921 tcase_add_test (tc_chain, rtp_base_depayload_multiple_exts);
1922 tcase_add_test (tc_chain, rtp_base_depayload_caps_request_ignored);
1923 tcase_add_test (tc_chain, rtp_base_depayload_hdr_ext_caps_change);
1924
1925 return s;
1926 }
1927
1928 GST_CHECK_MAIN (rtp_basepayloading)
1929