1 /* GStreamer RTP base payloader 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 #define BUFFER_BEFORE_LIST (10)
31
32 /* GstRtpDummyPay */
33
34 #define GST_TYPE_RTP_DUMMY_PAY \
35 (gst_rtp_dummy_pay_get_type())
36 #define GST_RTP_DUMMY_PAY(obj) \
37 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DUMMY_PAY,GstRtpDummyPay))
38 #define GST_RTP_DUMMY_PAY_CLASS(klass) \
39 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DUMMY_PAY,GstRtpDummyPayClass))
40 #define GST_IS_RTP_DUMMY_PAY(obj) \
41 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DUMMY_PAY))
42 #define GST_IS_RTP_DUMMY_PAY_CLASS(klass) \
43 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DUMMY_PAY))
44
45 typedef struct _GstRtpDummyPay GstRtpDummyPay;
46 typedef struct _GstRtpDummyPayClass GstRtpDummyPayClass;
47
48 struct _GstRtpDummyPay
49 {
50 GstRTPBasePayload payload;
51 };
52
53 struct _GstRtpDummyPayClass
54 {
55 GstRTPBasePayloadClass parent_class;
56 };
57
58 GType gst_rtp_dummy_pay_get_type (void);
59
60 G_DEFINE_TYPE (GstRtpDummyPay, gst_rtp_dummy_pay, GST_TYPE_RTP_BASE_PAYLOAD);
61
62 static GstFlowReturn gst_rtp_dummy_pay_handle_buffer (GstRTPBasePayload * pay,
63 GstBuffer * buffer);
64
65 static GstStaticPadTemplate gst_rtp_dummy_pay_sink_template =
66 GST_STATIC_PAD_TEMPLATE ("sink",
67 GST_PAD_SINK,
68 GST_PAD_ALWAYS,
69 GST_STATIC_CAPS_ANY);
70
71 static GstStaticPadTemplate gst_rtp_dummy_pay_src_template =
72 GST_STATIC_PAD_TEMPLATE ("src",
73 GST_PAD_SRC,
74 GST_PAD_ALWAYS,
75 GST_STATIC_CAPS ("application/x-rtp"));
76
77 static void
gst_rtp_dummy_pay_class_init(GstRtpDummyPayClass * klass)78 gst_rtp_dummy_pay_class_init (GstRtpDummyPayClass * klass)
79 {
80 GstElementClass *gstelement_class;
81 GstRTPBasePayloadClass *gstrtpbasepayload_class;
82
83 gstelement_class = GST_ELEMENT_CLASS (klass);
84 gstrtpbasepayload_class = GST_RTP_BASE_PAYLOAD_CLASS (klass);
85
86 gst_element_class_add_static_pad_template (gstelement_class,
87 &gst_rtp_dummy_pay_sink_template);
88 gst_element_class_add_static_pad_template (gstelement_class,
89 &gst_rtp_dummy_pay_src_template);
90
91 gstrtpbasepayload_class->handle_buffer = gst_rtp_dummy_pay_handle_buffer;
92 }
93
94 static void
gst_rtp_dummy_pay_init(GstRtpDummyPay * pay)95 gst_rtp_dummy_pay_init (GstRtpDummyPay * pay)
96 {
97 gst_rtp_base_payload_set_options (GST_RTP_BASE_PAYLOAD (pay), "application",
98 TRUE, "dummy", DEFAULT_CLOCK_RATE);
99 }
100
101 static GstRtpDummyPay *
rtp_dummy_pay_new(void)102 rtp_dummy_pay_new (void)
103 {
104 return g_object_new (GST_TYPE_RTP_DUMMY_PAY, NULL);
105 }
106
107 static GstFlowReturn
gst_rtp_dummy_pay_handle_buffer(GstRTPBasePayload * pay,GstBuffer * buffer)108 gst_rtp_dummy_pay_handle_buffer (GstRTPBasePayload * pay, GstBuffer * buffer)
109 {
110 GstBuffer *paybuffer;
111
112 GST_LOG ("payloading buffer pts=%" GST_TIME_FORMAT " offset=%"
113 G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
114 GST_BUFFER_OFFSET (buffer));
115
116 if (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (pay))) {
117 if (!gst_rtp_base_payload_set_outcaps (GST_RTP_BASE_PAYLOAD (pay),
118 "custom-caps", G_TYPE_UINT, DEFAULT_CLOCK_RATE, NULL)) {
119 gst_buffer_unref (buffer);
120 return GST_FLOW_NOT_NEGOTIATED;
121 }
122 }
123
124 paybuffer =
125 gst_rtp_base_payload_allocate_output_buffer (GST_RTP_BASE_PAYLOAD (pay),
126 0, 0, 0);
127
128 GST_BUFFER_PTS (paybuffer) = GST_BUFFER_PTS (buffer);
129 GST_BUFFER_OFFSET (paybuffer) = GST_BUFFER_OFFSET (buffer);
130
131 gst_buffer_append (paybuffer, buffer);
132
133 GST_LOG ("payloaded buffer pts=%" GST_TIME_FORMAT " offset=%"
134 G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (paybuffer)),
135 GST_BUFFER_OFFSET (paybuffer));
136
137 if (GST_BUFFER_PTS (paybuffer) < BUFFER_BEFORE_LIST) {
138 return gst_rtp_base_payload_push (pay, paybuffer);
139 } else {
140 GstBufferList *list = gst_buffer_list_new ();
141 gst_buffer_list_add (list, paybuffer);
142 return gst_rtp_base_payload_push_list (pay, list);
143 }
144 }
145
146 /* Helper functions and global state */
147
148 static GstStaticPadTemplate srctmpl = GST_STATIC_PAD_TEMPLATE ("src",
149 GST_PAD_SRC,
150 GST_PAD_ALWAYS,
151 GST_STATIC_CAPS_ANY);
152
153 static GstStaticPadTemplate sinktmpl = GST_STATIC_PAD_TEMPLATE ("sink",
154 GST_PAD_SINK,
155 GST_PAD_ALWAYS,
156 GST_STATIC_CAPS_ANY);
157
158 static GstStaticPadTemplate special_sinktmpl = GST_STATIC_PAD_TEMPLATE ("sink",
159 GST_PAD_SINK,
160 GST_PAD_ALWAYS,
161 GST_STATIC_CAPS ("application/x-rtp, payload=(int)98, ssrc=(uint)24, "
162 "timestamp-offset=(uint)212, seqnum-offset=(uint)2424"));
163
164 typedef struct State State;
165
166 struct State
167 {
168 GstElement *element;
169 GstPad *sinkpad;
170 GstPad *srcpad;
171 };
172
173 static GList *events;
174
175 static gboolean
event_func(GstPad * pad,GstObject * noparent,GstEvent * event)176 event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
177 {
178 events = g_list_append (events, gst_event_ref (event));
179 return gst_pad_event_default (pad, noparent, event);
180 }
181
182 static void
drop_events(void)183 drop_events (void)
184 {
185 while (events != NULL) {
186 gst_event_unref (GST_EVENT (events->data));
187 events = g_list_delete_link (events, events);
188 }
189 }
190
191 static void
validate_events_received(guint received)192 validate_events_received (guint received)
193 {
194 fail_unless_equals_int (g_list_length (events), received);
195 }
196
197 static void
validate_event(guint index,const gchar * name,const gchar * field,...)198 validate_event (guint index, const gchar * name, const gchar * field, ...)
199 {
200 GstEvent *event;
201 va_list var_args;
202
203 fail_if (index >= g_list_length (events));
204 event = GST_EVENT (g_list_nth_data (events, index));
205 fail_if (event == NULL);
206
207 GST_TRACE ("%" GST_PTR_FORMAT, event);
208
209 fail_unless_equals_string (GST_EVENT_TYPE_NAME (event), name);
210
211 va_start (var_args, field);
212 while (field) {
213 if (!g_strcmp0 (field, "timestamp")) {
214 GstClockTime expected = va_arg (var_args, GstClockTime);
215 GstClockTime timestamp, duration;
216 gst_event_parse_gap (event, ×tamp, &duration);
217 fail_unless_equals_uint64 (timestamp, expected);
218 } else if (!g_strcmp0 (field, "duration")) {
219 GstClockTime expected = va_arg (var_args, GstClockTime);
220 GstClockTime timestamp, duration;
221 gst_event_parse_gap (event, ×tamp, &duration);
222 fail_unless_equals_uint64 (duration, expected);
223 } else if (!g_strcmp0 (field, "time")) {
224 GstClockTime expected = va_arg (var_args, GstClockTime);
225 const GstSegment *segment;
226 gst_event_parse_segment (event, &segment);
227 fail_unless_equals_uint64 (segment->time, expected);
228 } else if (!g_strcmp0 (field, "start")) {
229 GstClockTime expected = va_arg (var_args, GstClockTime);
230 const GstSegment *segment;
231 gst_event_parse_segment (event, &segment);
232 fail_unless_equals_uint64 (segment->start, expected);
233 } else if (!g_strcmp0 (field, "stop")) {
234 GstClockTime expected = va_arg (var_args, GstClockTime);
235 const GstSegment *segment;
236 gst_event_parse_segment (event, &segment);
237 fail_unless_equals_uint64 (segment->stop, expected);
238 } else if (!g_strcmp0 (field, "applied-rate")) {
239 gdouble expected = va_arg (var_args, gdouble);
240 const GstSegment *segment;
241 gst_event_parse_segment (event, &segment);
242 fail_unless_equals_uint64 (segment->applied_rate, expected);
243 } else if (!g_strcmp0 (field, "rate")) {
244 gdouble expected = va_arg (var_args, gdouble);
245 const GstSegment *segment;
246 gst_event_parse_segment (event, &segment);
247 fail_unless_equals_uint64 (segment->rate, expected);
248 } else if (!g_strcmp0 (field, "media-type")) {
249 const gchar *expected = va_arg (var_args, const gchar *);
250 GstCaps *caps;
251 const gchar *media_type;
252 gst_event_parse_caps (event, &caps);
253 media_type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
254 fail_unless_equals_string (media_type, expected);
255 } else if (!g_strcmp0 (field, "npt-start")) {
256 GstClockTime expected = va_arg (var_args, GstClockTime);
257 GstCaps *caps;
258 GstClockTime start;
259 gst_event_parse_caps (event, &caps);
260 fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
261 0), "npt-start", &start));
262 fail_unless_equals_uint64 (start, expected);
263 } else if (!g_strcmp0 (field, "npt-stop")) {
264 GstClockTime expected = va_arg (var_args, GstClockTime);
265 GstCaps *caps;
266 GstClockTime stop;
267 gst_event_parse_caps (event, &caps);
268 fail_unless (gst_structure_get_clock_time (gst_caps_get_structure (caps,
269 0), "npt-stop", &stop));
270 fail_unless_equals_uint64 (stop, expected);
271 } else if (!g_strcmp0 (field, "play-speed")) {
272 gdouble expected = va_arg (var_args, gdouble);
273 GstCaps *caps;
274 gdouble speed;
275 gst_event_parse_caps (event, &caps);
276 fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
277 "play-speed", &speed));
278 fail_unless (speed == expected);
279 } else if (!g_strcmp0 (field, "play-scale")) {
280 gdouble expected = va_arg (var_args, gdouble);
281 GstCaps *caps;
282 gdouble scale;
283 gst_event_parse_caps (event, &caps);
284 fail_unless (gst_structure_get_double (gst_caps_get_structure (caps, 0),
285 "play-scale", &scale));
286 fail_unless (scale == expected);
287 } else if (!g_strcmp0 (field, "ssrc")) {
288 guint expected = va_arg (var_args, guint);
289 GstCaps *caps;
290 guint ssrc;
291 gst_event_parse_caps (event, &caps);
292 fail_unless (gst_structure_get_uint (gst_caps_get_structure (caps, 0),
293 "ssrc", &ssrc));
294 fail_unless_equals_int (ssrc, expected);
295 } else if (!g_strcmp0 (field, "a-framerate")) {
296 const gchar *expected = va_arg (var_args, const gchar *);
297 GstCaps *caps;
298 const gchar *framerate;
299 gst_event_parse_caps (event, &caps);
300 framerate = gst_structure_get_string (gst_caps_get_structure (caps, 0),
301 "a-framerate");
302 fail_unless_equals_string (framerate, expected);
303 } else {
304 fail ("test cannot validate unknown event field '%s'", field);
305 }
306 field = va_arg (var_args, const gchar *);
307 }
308 va_end (var_args);
309 }
310
311 static void
validate_normal_start_events(guint index)312 validate_normal_start_events (guint index)
313 {
314 validate_event (index, "stream-start", NULL);
315
316 validate_event (index + 1, "caps", "media-type", "application/x-rtp", NULL);
317
318 validate_event (index + 2, "segment",
319 "time", G_GUINT64_CONSTANT (0),
320 "start", G_GUINT64_CONSTANT (0), "stop", G_MAXUINT64, NULL);
321 }
322
323 #define push_buffer(state, field, ...) \
324 push_buffer_full ((state), GST_FLOW_OK, (field), __VA_ARGS__)
325 #define push_buffer_fails(state, field, ...) \
326 push_buffer_full ((state), GST_FLOW_FLUSHING, (field), __VA_ARGS__)
327
328 static void
push_buffer_full(State * state,GstFlowReturn expected,const gchar * field,...)329 push_buffer_full (State * state, GstFlowReturn expected,
330 const gchar * field, ...)
331 {
332 GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
333 GstRTPBuffer rtp = { NULL };
334 gboolean mapped = FALSE;
335 va_list var_args;
336
337 va_start (var_args, field);
338 while (field) {
339 if (!g_strcmp0 (field, "pts")) {
340 GstClockTime pts = va_arg (var_args, GstClockTime);
341 GST_BUFFER_PTS (buf) = pts;
342 } else if (!g_strcmp0 (field, "offset")) {
343 guint64 offset = va_arg (var_args, guint64);
344 GST_BUFFER_OFFSET (buf) = offset;
345 } else if (!g_strcmp0 (field, "discont")) {
346 gboolean discont = va_arg (var_args, gboolean);
347 if (discont) {
348 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
349 } else {
350 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
351 }
352 } else {
353 if (!mapped) {
354 gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
355 mapped = TRUE;
356 }
357 if (!g_strcmp0 (field, "rtptime")) {
358 guint32 rtptime = va_arg (var_args, guint);
359 gst_rtp_buffer_set_timestamp (&rtp, rtptime);
360 } else if (!g_strcmp0 (field, "payload-type")) {
361 guint payload_type = va_arg (var_args, guint);
362 gst_rtp_buffer_set_payload_type (&rtp, payload_type);
363 } else if (!g_strcmp0 (field, "seq")) {
364 guint seq = va_arg (var_args, guint);
365 gst_rtp_buffer_set_seq (&rtp, seq);
366 } else if (!g_strcmp0 (field, "ssrc")) {
367 guint32 ssrc = va_arg (var_args, guint);
368 gst_rtp_buffer_set_ssrc (&rtp, ssrc);
369 } else {
370 fail ("test cannot set unknown buffer field '%s'", field);
371 }
372 }
373 field = va_arg (var_args, const gchar *);
374 }
375 va_end (var_args);
376
377 if (mapped) {
378 gst_rtp_buffer_unmap (&rtp);
379 }
380
381 fail_unless_equals_int (gst_pad_push (state->srcpad, buf), expected);
382 }
383
384 static void
push_buffer_list(State * state,const gchar * field,...)385 push_buffer_list (State * state, const gchar * field, ...)
386 {
387 GstBuffer *buf = gst_rtp_buffer_new_allocate (0, 0, 0);
388 GstRTPBuffer rtp = { NULL };
389 gboolean mapped = FALSE;
390 GstBufferList *list;
391 va_list var_args;
392
393 va_start (var_args, field);
394 while (field) {
395 if (!g_strcmp0 (field, "pts")) {
396 GstClockTime pts = va_arg (var_args, GstClockTime);
397 GST_BUFFER_PTS (buf) = pts;
398 } else if (!g_strcmp0 (field, "offset")) {
399 guint64 offset = va_arg (var_args, guint64);
400 GST_BUFFER_OFFSET (buf) = offset;
401 } else if (!g_strcmp0 (field, "discont")) {
402 gboolean discont = va_arg (var_args, gboolean);
403 if (discont) {
404 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
405 } else {
406 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
407 }
408 } else {
409 if (!mapped) {
410 gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
411 mapped = TRUE;
412 }
413 if (!g_strcmp0 (field, "rtptime")) {
414 guint32 rtptime = va_arg (var_args, guint);
415 gst_rtp_buffer_set_timestamp (&rtp, rtptime);
416 } else if (!g_strcmp0 (field, "payload-type")) {
417 guint payload_type = va_arg (var_args, guint);
418 gst_rtp_buffer_set_payload_type (&rtp, payload_type);
419 } else if (!g_strcmp0 (field, "seq")) {
420 guint seq = va_arg (var_args, guint);
421 gst_rtp_buffer_set_seq (&rtp, seq);
422 } else if (!g_strcmp0 (field, "ssrc")) {
423 guint32 ssrc = va_arg (var_args, guint);
424 gst_rtp_buffer_set_ssrc (&rtp, ssrc);
425 } else {
426 fail ("test cannot set unknown buffer field '%s'", field);
427 }
428 }
429 field = va_arg (var_args, const gchar *);
430 }
431 va_end (var_args);
432
433 if (mapped) {
434 gst_rtp_buffer_unmap (&rtp);
435 }
436
437 list = gst_buffer_list_new ();
438 gst_buffer_list_add (list, buf);
439 fail_unless_equals_int (gst_pad_push_list (state->srcpad, list), GST_FLOW_OK);
440 }
441
442 static void
validate_buffers_received(guint received_buffers)443 validate_buffers_received (guint received_buffers)
444 {
445 fail_unless_equals_int (g_list_length (buffers), received_buffers);
446 }
447
448 static void
validate_buffer_valist(GstBuffer * buf,const gchar * field,va_list var_args)449 validate_buffer_valist (GstBuffer * buf, const gchar * field, va_list var_args)
450 {
451 GstRTPBuffer rtp = { NULL };
452 gboolean mapped = FALSE;
453
454 while (field) {
455 if (!g_strcmp0 (field, "pts")) {
456 GstClockTime pts = va_arg (var_args, GstClockTime);
457 fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), pts);
458 } else if (!g_strcmp0 (field, "offset")) {
459 guint64 offset = va_arg (var_args, guint64);
460 fail_unless_equals_uint64 (GST_BUFFER_OFFSET (buf), offset);
461 } else if (!g_strcmp0 (field, "discont")) {
462 gboolean discont = va_arg (var_args, gboolean);
463 if (discont) {
464 fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
465 } else {
466 fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT));
467 }
468 } else {
469 if (!mapped) {
470 gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
471 mapped = TRUE;
472 }
473 if (!g_strcmp0 (field, "rtptime")) {
474 guint32 rtptime = va_arg (var_args, guint);
475 fail_unless_equals_int (gst_rtp_buffer_get_timestamp (&rtp), rtptime);
476 } else if (!g_strcmp0 (field, "payload-type")) {
477 guint pt = va_arg (var_args, guint);
478 fail_unless_equals_int (gst_rtp_buffer_get_payload_type (&rtp), pt);
479 } else if (!g_strcmp0 (field, "seq")) {
480 guint seq = va_arg (var_args, guint);
481 fail_unless_equals_int (gst_rtp_buffer_get_seq (&rtp), seq);
482 } else if (!g_strcmp0 (field, "ssrc")) {
483 guint32 ssrc = va_arg (var_args, guint);
484 fail_unless_equals_int (gst_rtp_buffer_get_ssrc (&rtp), ssrc);
485 } else if (!g_strcmp0 (field, "csrc")) {
486 guint idx = va_arg (var_args, guint);
487 guint csrc = va_arg (var_args, guint);
488 fail_unless_equals_int (gst_rtp_buffer_get_csrc (&rtp, idx), csrc);
489 } else if (!g_strcmp0 (field, "csrc-count")) {
490 guint csrc_count = va_arg (var_args, guint);
491 fail_unless_equals_int (gst_rtp_buffer_get_csrc_count (&rtp),
492 csrc_count);
493 } else {
494 fail ("test cannot validate unknown buffer field '%s'", field);
495 }
496 }
497 field = va_arg (var_args, const gchar *);
498 }
499
500 if (mapped) {
501 gst_rtp_buffer_unmap (&rtp);
502 }
503 }
504
505 static void
validate_buffer1(GstBuffer * buf,const gchar * field,...)506 validate_buffer1 (GstBuffer * buf, const gchar * field, ...)
507 {
508 va_list var_args;
509
510 va_start (var_args, field);
511 validate_buffer_valist (buf, field, var_args);
512 va_end (var_args);
513 }
514
515 static void
validate_buffer(guint index,const gchar * field,...)516 validate_buffer (guint index, const gchar * field, ...)
517 {
518 GstBuffer *buf;
519 va_list var_args;
520
521 fail_if (index >= g_list_length (buffers));
522 buf = GST_BUFFER (g_list_nth_data (buffers, index));
523 fail_if (buf == NULL);
524
525 GST_TRACE ("%" GST_PTR_FORMAT, buf);
526
527 va_start (var_args, field);
528 validate_buffer_valist (buf, field, var_args);
529 va_end (var_args);
530 }
531
532 static void
get_buffer_field(guint index,const gchar * field,...)533 get_buffer_field (guint index, const gchar * field, ...)
534 {
535 GstBuffer *buf;
536 GstRTPBuffer rtp = { NULL };
537 gboolean mapped = FALSE;
538 va_list var_args;
539
540 fail_if (index >= g_list_length (buffers));
541 buf = GST_BUFFER (g_list_nth_data (buffers, (index)));
542 fail_if (buf == NULL);
543
544 va_start (var_args, field);
545 while (field) {
546 if (!g_strcmp0 (field, "pts")) {
547 GstClockTime *pts = va_arg (var_args, GstClockTime *);
548 *pts = GST_BUFFER_PTS (buf);
549 } else if (!g_strcmp0 (field, "offset")) {
550 guint64 *offset = va_arg (var_args, guint64 *);
551 *offset = GST_BUFFER_OFFSET (buf);
552 } else if (!g_strcmp0 (field, "discont")) {
553 gboolean *discont = va_arg (var_args, gboolean *);
554 *discont = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT);
555 } else {
556 if (!mapped) {
557 gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
558 mapped = TRUE;
559 }
560 if (!g_strcmp0 (field, "rtptime")) {
561 guint32 *rtptime = va_arg (var_args, guint32 *);
562 *rtptime = gst_rtp_buffer_get_timestamp (&rtp);
563 } else if (!g_strcmp0 (field, "payload-type")) {
564 guint *pt = va_arg (var_args, guint *);
565 *pt = gst_rtp_buffer_get_payload_type (&rtp);
566 } else if (!g_strcmp0 (field, "seq")) {
567 guint16 *seq = va_arg (var_args, guint16 *);
568 *seq = gst_rtp_buffer_get_seq (&rtp);
569 } else if (!g_strcmp0 (field, "ssrc")) {
570 guint32 *ssrc = va_arg (var_args, guint32 *);
571 *ssrc = gst_rtp_buffer_get_ssrc (&rtp);
572 } else {
573 fail ("test retrieve validate unknown buffer field '%s'", field);
574 }
575 }
576 field = va_arg (var_args, const gchar *);
577 }
578 va_end (var_args);
579
580 if (mapped)
581 gst_rtp_buffer_unmap (&rtp);
582 }
583
584 static State *
create_payloader(const gchar * caps_str,GstStaticPadTemplate * sinktmpl,const gchar * property,...)585 create_payloader (const gchar * caps_str,
586 GstStaticPadTemplate * sinktmpl, const gchar * property, ...)
587 {
588 va_list var_args;
589 GstCaps *caps;
590 State *state;
591
592 state = g_new0 (State, 1);
593
594 state->element = GST_ELEMENT (rtp_dummy_pay_new ());
595 fail_unless (GST_IS_RTP_DUMMY_PAY (state->element));
596
597 va_start (var_args, property);
598 g_object_set_valist (G_OBJECT (state->element), property, var_args);
599 va_end (var_args);
600
601 state->srcpad = gst_check_setup_src_pad (state->element, &srctmpl);
602 state->sinkpad = gst_check_setup_sink_pad (state->element, sinktmpl);
603
604 fail_unless (gst_pad_set_active (state->srcpad, TRUE));
605 fail_unless (gst_pad_set_active (state->sinkpad, TRUE));
606
607 caps = gst_caps_from_string (caps_str);
608 gst_check_setup_events (state->srcpad, state->element, caps, GST_FORMAT_TIME);
609 gst_caps_unref (caps);
610
611 gst_pad_set_chain_function (state->sinkpad, gst_check_chain_func);
612 gst_pad_set_event_function (state->sinkpad, event_func);
613
614 return state;
615 }
616
617 static void
set_state(State * state,GstState new_state)618 set_state (State * state, GstState new_state)
619 {
620 fail_unless_equals_int (gst_element_set_state (state->element, new_state),
621 GST_STATE_CHANGE_SUCCESS);
622 }
623
624 static void
validate_would_not_be_filled(State * state,guint size,GstClockTime duration)625 validate_would_not_be_filled (State * state, guint size, GstClockTime duration)
626 {
627 GstRTPBasePayload *basepay;
628 basepay = GST_RTP_BASE_PAYLOAD (state->element);
629 fail_if (gst_rtp_base_payload_is_filled (basepay, size, duration));
630 }
631
632 static void
validate_would_be_filled(State * state,guint size,GstClockTime duration)633 validate_would_be_filled (State * state, guint size, GstClockTime duration)
634 {
635 GstRTPBasePayload *basepay;
636 basepay = GST_RTP_BASE_PAYLOAD (state->element);
637 fail_unless (gst_rtp_base_payload_is_filled (basepay, size, duration));
638 }
639
640 static void
ssrc_collision(State * state,guint ssrc,gboolean have_new_ssrc,guint new_ssrc)641 ssrc_collision (State * state, guint ssrc,
642 gboolean have_new_ssrc, guint new_ssrc)
643 {
644 GstStructure *s;
645 GstEvent *event;
646 if (have_new_ssrc) {
647 s = gst_structure_new ("GstRTPCollision",
648 "ssrc", G_TYPE_UINT, ssrc,
649 "suggested-ssrc", G_TYPE_UINT, new_ssrc, NULL);
650 } else {
651 s = gst_structure_new ("GstRTPCollision", "ssrc", G_TYPE_UINT, ssrc, NULL);
652 }
653 event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
654 fail_unless (gst_pad_push_event (state->sinkpad, event));
655 }
656
657 static void
reconfigure(State * state)658 reconfigure (State * state)
659 {
660 GstEvent *event;
661 event = gst_event_new_reconfigure ();
662 fail_unless (gst_pad_push_event (state->sinkpad, event));
663 }
664
665 static void
validate_stats(State * state,guint clock_rate,GstClockTime running_time,guint16 seq,guint32 rtptime)666 validate_stats (State * state, guint clock_rate,
667 GstClockTime running_time, guint16 seq, guint32 rtptime)
668 {
669 GstStructure *stats;
670
671 g_object_get (state->element, "stats", &stats, NULL);
672
673 fail_unless_equals_int (g_value_get_uint (gst_structure_get_value (stats,
674 "clock-rate")), clock_rate);
675 fail_unless_equals_uint64 (g_value_get_uint64 (gst_structure_get_value (stats,
676 "running-time")), running_time);
677 fail_unless_equals_int (g_value_get_uint (gst_structure_get_value (stats,
678 "seqnum")), seq);
679 fail_unless_equals_int (g_value_get_uint (gst_structure_get_value (stats,
680 "timestamp")), rtptime);
681
682 gst_structure_free (stats);
683 }
684
685 static void
destroy_payloader(State * state)686 destroy_payloader (State * state)
687 {
688 gst_check_teardown_sink_pad (state->element);
689 gst_check_teardown_src_pad (state->element);
690
691 gst_check_drop_buffers ();
692 drop_events ();
693
694 g_object_unref (state->element);
695
696 g_free (state);
697 }
698
699 /* Tests */
700
701 /* push two buffers to the payloader which should successfully payload them
702 * into RTP packets. the first packet will have a random rtptime and sequence
703 * number, but the last packet should have an rtptime incremented by
704 * DEFAULT_CLOCK_RATE and a sequence number incremented by one becuase the
705 * packets are sequential. besides the two payloaded RTP packets there should
706 * be the three events initial events: stream-start, caps and segment.
707 */
GST_START_TEST(rtp_base_payload_buffer_test)708 GST_START_TEST (rtp_base_payload_buffer_test)
709 {
710 State *state;
711 guint32 rtptime;
712 guint16 seq;
713
714 state = create_payloader ("application/x-rtp", &sinktmpl,
715 "perfect-rtptime", FALSE, NULL);
716
717 set_state (state, GST_STATE_PLAYING);
718
719 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
720
721 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
722
723 set_state (state, GST_STATE_NULL);
724
725 validate_buffers_received (2);
726
727 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
728 get_buffer_field (0, "rtptime", &rtptime, "seq", &seq, NULL);
729
730 validate_buffer (1,
731 "pts", 1 * GST_SECOND,
732 "rtptime", rtptime + 1 * DEFAULT_CLOCK_RATE, "seq", seq + 1, NULL);
733
734 validate_events_received (3);
735
736 validate_normal_start_events (0);
737
738 destroy_payloader (state);
739 }
740
741 GST_END_TEST;
742
743 /* push single buffers in buffer lists to the payloader to be payloaded into
744 * RTP packets. the dummy payloader will start pushing buffer lists itself
745 * after BUFFER_BEFORE_LIST payloaded RTP packets. any RTP packets included in
746 * buffer lists should have rtptime and sequence numbers incrementting in the
747 * same way as for separate RTP packets.
748 */
GST_START_TEST(rtp_base_payload_buffer_list_test)749 GST_START_TEST (rtp_base_payload_buffer_list_test)
750 {
751 State *state;
752 guint32 rtptime;
753 guint16 seq;
754 guint i;
755
756 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
757
758 set_state (state, GST_STATE_PLAYING);
759
760 for (i = 0; i < BUFFER_BEFORE_LIST + 1; i++) {
761 push_buffer_list (state, "pts", i * GST_SECOND, NULL);
762 }
763
764 set_state (state, GST_STATE_NULL);
765
766 validate_buffers_received (11);
767
768 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
769 get_buffer_field (0, "rtptime", &rtptime, "seq", &seq, NULL);
770
771 for (i = 1; i < BUFFER_BEFORE_LIST + 1; i++) {
772 validate_buffer (i,
773 "pts", i * GST_SECOND,
774 "rtptime", rtptime + i * DEFAULT_CLOCK_RATE, "seq", seq + i, NULL);
775 }
776
777 validate_events_received (3);
778
779 validate_normal_start_events (0);
780
781 destroy_payloader (state);
782 }
783
784 GST_END_TEST;
785
786 /* push two buffers. because the payloader is using non-perfect rtptime the
787 * second buffer will be timestamped with the default clock and ignore any
788 * offset set on the buffers being payloaded.
789 */
GST_START_TEST(rtp_base_payload_normal_rtptime_test)790 GST_START_TEST (rtp_base_payload_normal_rtptime_test)
791 {
792 guint32 rtptime;
793 State *state;
794
795 state = create_payloader ("application/x-rtp", &sinktmpl,
796 "perfect-rtptime", FALSE, NULL);
797
798 set_state (state, GST_STATE_PLAYING);
799
800 push_buffer (state,
801 "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
802
803 push_buffer (state,
804 "pts", 1 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
805
806 set_state (state, GST_STATE_NULL);
807
808 validate_buffers_received (2);
809
810 validate_buffer (0,
811 "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
812 get_buffer_field (0, "rtptime", &rtptime, NULL);
813
814 validate_buffer (1,
815 "pts", 1 * GST_SECOND,
816 "offset", GST_BUFFER_OFFSET_NONE,
817 "rtptime", rtptime + DEFAULT_CLOCK_RATE, NULL);
818
819 validate_events_received (3);
820
821 validate_normal_start_events (0);
822
823 destroy_payloader (state);
824 }
825
826 GST_END_TEST;
827
828 /* push two buffers. because the payloader is using perfect rtptime the
829 * second buffer will be timestamped with a timestamp incremented with the
830 * difference in offset between the first and second buffer. the pts will be
831 * ignored for any buffer after the first buffer.
832 */
GST_START_TEST(rtp_base_payload_perfect_rtptime_test)833 GST_START_TEST (rtp_base_payload_perfect_rtptime_test)
834 {
835 guint32 rtptime;
836 State *state;
837
838 state = create_payloader ("application/x-rtp", &sinktmpl,
839 "perfect-rtptime", TRUE, NULL);
840
841 set_state (state, GST_STATE_PLAYING);
842
843 push_buffer (state, "pts", 0 * GST_SECOND, "offset", G_GINT64_CONSTANT (0),
844 NULL);
845
846 push_buffer (state, "pts", GST_CLOCK_TIME_NONE, "offset",
847 G_GINT64_CONSTANT (21), NULL);
848
849 set_state (state, GST_STATE_NULL);
850
851 validate_buffers_received (2);
852
853 validate_buffer (0, "pts", 0 * GST_SECOND, "offset", G_GINT64_CONSTANT (0),
854 NULL);
855 get_buffer_field (0, "rtptime", &rtptime, NULL);
856
857 validate_buffer (1,
858 "pts", GST_CLOCK_TIME_NONE, "offset", G_GINT64_CONSTANT (21), "rtptime",
859 rtptime + 21, NULL);
860
861 validate_events_received (3);
862
863 validate_normal_start_events (0);
864
865 destroy_payloader (state);
866 }
867
868 GST_END_TEST;
869
870 /* validate that a payloader will re-use the last used timestamp when a buffer
871 * is using perfect rtptime and both the pushed buffers timestamp and the offset
872 * is NONE. the payloader is configuered to start with a specific timestamp.
873 * then a buffer is sent with a valid timestamp but without any offset. the
874 * payloded RTP packet is expected to use the specific timestamp. next another
875 * buffer is pushed with a normal timestamp set to illustrate that the payloaded
876 * RTP packet will have an increased timestamp. finally a buffer without any
877 * timestamp or offset is pushed. in this case the payloaded RTP packet is
878 * expected to have the same timestamp as the previously payloaded RTP packet.
879 */
GST_START_TEST(rtp_base_payload_no_pts_no_offset_test)880 GST_START_TEST (rtp_base_payload_no_pts_no_offset_test)
881 {
882 State *state;
883
884 state = create_payloader ("application/x-rtp", &sinktmpl,
885 "timestamp-offset", 0x42, NULL);
886
887 set_state (state, GST_STATE_PLAYING);
888
889 push_buffer (state,
890 "pts", 0 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
891
892 push_buffer (state,
893 "pts", 1 * GST_SECOND, "offset", GST_BUFFER_OFFSET_NONE, NULL);
894
895 push_buffer (state,
896 "pts", GST_CLOCK_TIME_NONE, "offset", GST_BUFFER_OFFSET_NONE, NULL);
897
898 set_state (state, GST_STATE_NULL);
899
900 validate_buffers_received (3);
901
902 validate_buffer (0,
903 "pts", 0 * GST_SECOND,
904 "offset", GST_BUFFER_OFFSET_NONE, "rtptime", 0x42, NULL);
905
906 validate_buffer (1,
907 "pts", 1 * GST_SECOND,
908 "offset", GST_BUFFER_OFFSET_NONE,
909 "rtptime", 0x42 + 1 * DEFAULT_CLOCK_RATE, NULL);
910
911 validate_buffer (2,
912 "pts", GST_CLOCK_TIME_NONE,
913 "offset", GST_BUFFER_OFFSET_NONE,
914 "rtptime", 0x42 + 1 * DEFAULT_CLOCK_RATE, NULL);
915
916 validate_events_received (3);
917
918 validate_normal_start_events (0);
919
920 destroy_payloader (state);
921 }
922
923 GST_END_TEST;
924
925 /* validate that a downstream element with caps on its sink pad can effectively
926 * configure the payloader's payload-type, ssrc, timestamp-offset and
927 * seqnum-offset properties and therefore also affect the payloaded RTP packets.
928 * this is done by connecting to a sink pad with template caps setting the
929 * relevant fields and then pushing a buffer and making sure that the payloaded
930 * RTP packet has the expected properties.
931 */
GST_START_TEST(rtp_base_payload_downstream_caps_test)932 GST_START_TEST (rtp_base_payload_downstream_caps_test)
933 {
934 State *state;
935
936 state = create_payloader ("application/x-rtp", &special_sinktmpl, NULL);
937
938 set_state (state, GST_STATE_PLAYING);
939
940 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
941
942 set_state (state, GST_STATE_NULL);
943
944 validate_buffers_received (1);
945
946 validate_buffer (0,
947 "pts", 0 * GST_SECOND,
948 "seq", 2424, "payload-type", 98, "ssrc", 24, "rtptime", 212, NULL);
949
950 validate_events_received (3);
951
952 validate_normal_start_events (0);
953
954 destroy_payloader (state);
955 }
956
957 GST_END_TEST;
958
959 /* when a payloader receives a GstRTPCollision upstream event it should try to
960 * switch to a new ssrc for the next payloaded RTP packets. GstRTPCollision can
961 * supply a suggested new ssrc. if a suggested new ssrc is supplied then the
962 * payloaded is supposed to use this new ssrc, otherwise it should generate a
963 * new random ssrc which is not identical to the one that collided.
964 *
965 * this is tested by first setting the ssrc to a specific value and pushing a
966 * buffer. the payloaded RTP packet is validate to have the set ssrc. then a
967 * GstRTPCollision event is generated to instruct the payloader that the
968 * previously set ssrc collided. this event suggests a new ssrc and it is
969 * verified that a pushed buffer results in a payloaded RTP packet that actually
970 * uses this new ssrc. finally a new GstRTPCollision event is generated to
971 * indicate another ssrc collision. this time the event does not suggest a new
972 * ssrc. the payloaded RTP packet is then expected to have a new random ssrc
973 * different from the collided one.
974 */
GST_START_TEST(rtp_base_payload_ssrc_collision_test)975 GST_START_TEST (rtp_base_payload_ssrc_collision_test)
976 {
977 State *state;
978 guint32 ssrc;
979
980 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
981
982 g_object_set (state->element, "ssrc", 0x4242, NULL);
983 g_object_get (state->element, "ssrc", &ssrc, NULL);
984 fail_unless_equals_int (ssrc, 0x4242);
985
986 set_state (state, GST_STATE_PLAYING);
987
988 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
989
990 ssrc_collision (state, 0x4242, TRUE, 0x4343);
991
992 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
993
994 ssrc_collision (state, 0x4343, FALSE, 0);
995
996 push_buffer (state, "pts", 2 * GST_SECOND, NULL);
997
998 set_state (state, GST_STATE_NULL);
999
1000 validate_buffers_received (3);
1001
1002 validate_buffer (0, "pts", 0 * GST_SECOND, "ssrc", 0x4242, NULL);
1003
1004 validate_buffer (1, "pts", 1 * GST_SECOND, "ssrc", 0x4343, NULL);
1005
1006 validate_buffer (2, "pts", 2 * GST_SECOND, NULL);
1007 get_buffer_field (2, "ssrc", &ssrc, NULL);
1008 fail_if (ssrc == 0x4343);
1009
1010 validate_events_received (5);
1011
1012 validate_normal_start_events (0);
1013
1014 validate_event (3, "caps",
1015 "media-type", "application/x-rtp", "ssrc", 0x4343, NULL);
1016
1017 validate_event (4, "caps",
1018 "media-type", "application/x-rtp", "ssrc", ssrc, NULL);
1019
1020 destroy_payloader (state);
1021 }
1022
1023 GST_END_TEST;
1024
1025 /* validate that an upstream event different from GstRTPCollision is succesfully
1026 * forwarded to upstream elements. in this test a caps reconfiguration event is
1027 * pushed upstream to validate the behaviour.
1028 */
GST_START_TEST(rtp_base_payload_reconfigure_test)1029 GST_START_TEST (rtp_base_payload_reconfigure_test)
1030 {
1031 State *state;
1032
1033 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1034
1035 set_state (state, GST_STATE_PLAYING);
1036
1037 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1038
1039 reconfigure (state);
1040
1041 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1042
1043 set_state (state, GST_STATE_NULL);
1044
1045 validate_buffers_received (2);
1046
1047 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
1048
1049 validate_buffer (1, "pts", 1 * GST_SECOND, NULL);
1050
1051 validate_events_received (4);
1052
1053 validate_normal_start_events (0);
1054
1055 destroy_payloader (state);
1056 }
1057
1058 GST_END_TEST;
1059
1060 /* validate that changing the mtu actually affects whether buffers are
1061 * considered to be filled. first detect the default mtu and check that having
1062 * buffers slightly less or equal to the size will not be considered to be
1063 * filled, and that going over this size will be filling the buffers. then
1064 * change the mtu slightly and validate that the boundary actually changed.
1065 * lastly try the boundary values and make sure that they work as expected.
1066 */
GST_START_TEST(rtp_base_payload_property_mtu_test)1067 GST_START_TEST (rtp_base_payload_property_mtu_test)
1068 {
1069 State *state;
1070 guint mtu, check;
1071
1072 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1073
1074 g_object_get (state->element, "mtu", &mtu, NULL);
1075 validate_would_not_be_filled (state, mtu - 1, GST_CLOCK_TIME_NONE);
1076 validate_would_not_be_filled (state, mtu, GST_CLOCK_TIME_NONE);
1077 validate_would_be_filled (state, mtu + 1, GST_CLOCK_TIME_NONE);
1078
1079 g_object_set (state->element, "mtu", mtu - 1, NULL);
1080 g_object_get (state->element, "mtu", &check, NULL);
1081 fail_unless_equals_int (check, mtu - 1);
1082 validate_would_not_be_filled (state, mtu - 1, GST_CLOCK_TIME_NONE);
1083 validate_would_be_filled (state, mtu, GST_CLOCK_TIME_NONE);
1084 validate_would_be_filled (state, mtu + 1, GST_CLOCK_TIME_NONE);
1085
1086 g_object_set (state->element, "mtu", 28, NULL);
1087 g_object_get (state->element, "mtu", &check, NULL);
1088 fail_unless_equals_int (check, 28);
1089 validate_would_not_be_filled (state, 28, GST_CLOCK_TIME_NONE);
1090 validate_would_be_filled (state, 29, GST_CLOCK_TIME_NONE);
1091
1092 g_object_set (state->element, "mtu", G_MAXUINT, NULL);
1093 g_object_get (state->element, "mtu", &check, NULL);
1094 fail_unless_equals_int (check, G_MAXUINT);
1095 validate_would_not_be_filled (state, G_MAXUINT - 1, GST_CLOCK_TIME_NONE);
1096 validate_would_not_be_filled (state, G_MAXUINT, GST_CLOCK_TIME_NONE);
1097
1098 destroy_payloader (state);
1099 }
1100
1101 GST_END_TEST;
1102
1103 /* validate that changing the payload-type will actually affect the
1104 * payload-type of the payloaded RTP packets. first get the default, then send
1105 * a buffer with this payload-type. increment the payload-type and send another
1106 * buffer. then test the boundary values for the payload-type and make sure
1107 * that these are all carried over to the payloaded RTP packets.
1108 */
GST_START_TEST(rtp_base_payload_property_pt_test)1109 GST_START_TEST (rtp_base_payload_property_pt_test)
1110 {
1111 State *state;
1112 guint payload_type, check;
1113
1114 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1115
1116 set_state (state, GST_STATE_PLAYING);
1117
1118 g_object_get (state->element, "pt", &payload_type, NULL);
1119 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1120
1121 g_object_set (state->element, "pt", payload_type + 1, NULL);
1122 g_object_get (state->element, "pt", &check, NULL);
1123 fail_unless_equals_int (check, payload_type + 1);
1124 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1125
1126 g_object_set (state->element, "pt", 0, NULL);
1127 g_object_get (state->element, "pt", &check, NULL);
1128 fail_unless_equals_int (check, 0);
1129 push_buffer (state, "pts", 2 * GST_SECOND, NULL);
1130
1131 g_object_set (state->element, "pt", 0x7f, NULL);
1132 g_object_get (state->element, "pt", &check, NULL);
1133 fail_unless_equals_int (check, 0x7f);
1134 push_buffer (state, "pts", 3 * GST_SECOND, NULL);
1135
1136 set_state (state, GST_STATE_NULL);
1137
1138 validate_buffers_received (4);
1139
1140 validate_buffer (0,
1141 "pts", 0 * GST_SECOND, "payload-type", payload_type, NULL);
1142
1143 validate_buffer (1,
1144 "pts", 1 * GST_SECOND, "payload-type", payload_type + 1, NULL);
1145
1146 validate_buffer (2, "pts", 2 * GST_SECOND, "payload-type", 0, NULL);
1147
1148 validate_buffer (3, "pts", 3 * GST_SECOND, "payload-type", 0x7f, NULL);
1149
1150 validate_events_received (3);
1151
1152 validate_normal_start_events (0);
1153
1154 destroy_payloader (state);
1155 }
1156
1157 GST_END_TEST;
1158
1159 /* validate that changing the ssrc will actually affect the ssrc of the
1160 * payloaded RTP packets. first get the current ssrc which should indicate
1161 * random ssrcs. send two buffers and expect their ssrcs to be random but
1162 * identical. since setting the ssrc will only take effect when the pipeline
1163 * goes READY->PAUSED, bring the pipeline to NULL state, set the ssrc to a given
1164 * value and make sure that this is carried over to the payloaded RTP packets.
1165 * the last step is to test the boundary values.
1166 */
GST_START_TEST(rtp_base_payload_property_ssrc_test)1167 GST_START_TEST (rtp_base_payload_property_ssrc_test)
1168 {
1169 State *state;
1170 guint32 ssrc;
1171
1172 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1173
1174 set_state (state, GST_STATE_PLAYING);
1175
1176 g_object_get (state->element, "ssrc", &ssrc, NULL);
1177 fail_unless_equals_int (ssrc, -1);
1178
1179 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1180
1181 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1182
1183 set_state (state, GST_STATE_NULL);
1184 g_object_set (state->element, "ssrc", 0x4242, NULL);
1185 g_object_get (state->element, "ssrc", &ssrc, NULL);
1186 fail_unless_equals_int (ssrc, 0x4242);
1187 set_state (state, GST_STATE_PLAYING);
1188
1189 push_buffer (state, "pts", 2 * GST_SECOND, NULL);
1190
1191 set_state (state, GST_STATE_NULL);
1192 g_object_set (state->element, "ssrc", 0, NULL);
1193 g_object_get (state->element, "ssrc", &ssrc, NULL);
1194 fail_unless_equals_int (ssrc, 0);
1195 set_state (state, GST_STATE_PLAYING);
1196
1197 push_buffer (state, "pts", 3 * GST_SECOND, NULL);
1198
1199 set_state (state, GST_STATE_NULL);
1200 g_object_set (state->element, "ssrc", G_MAXUINT32, NULL);
1201 g_object_get (state->element, "ssrc", &ssrc, NULL);
1202 fail_unless_equals_int (ssrc, G_MAXUINT32);
1203 set_state (state, GST_STATE_PLAYING);
1204
1205 push_buffer (state, "pts", 4 * GST_SECOND, NULL);
1206
1207 set_state (state, GST_STATE_NULL);
1208
1209 validate_buffers_received (5);
1210
1211 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
1212 get_buffer_field (0, "ssrc", &ssrc, NULL);
1213
1214 validate_buffer (1, "pts", 1 * GST_SECOND, "ssrc", ssrc, NULL);
1215
1216 validate_buffer (2, "pts", 2 * GST_SECOND, "ssrc", 0x4242, NULL);
1217
1218 validate_buffer (3, "pts", 3 * GST_SECOND, "ssrc", 0, NULL);
1219
1220 validate_buffer (4, "pts", 4 * GST_SECOND, "ssrc", G_MAXUINT32, NULL);
1221
1222 validate_events_received (12);
1223
1224 validate_normal_start_events (0);
1225
1226 validate_normal_start_events (3);
1227
1228 validate_normal_start_events (6);
1229
1230 validate_normal_start_events (9);
1231
1232 destroy_payloader (state);
1233 }
1234
1235 GST_END_TEST;
1236
1237 /* validate that changing the timestamp-offset will actually effect the rtptime
1238 * of the payloaded RTP packets. unfortunately setting the timestamp-offset
1239 * property will only take effect when the payloader goes from READY to PAUSED.
1240 * so the test starts by making sure that the default timestamp-offset indicates
1241 * random timestamps. then a buffer is pushed which is expected to be payloaded
1242 * as an RTP packet with a random timestamp. then the timestamp-offset is
1243 * modified without changing the state of the pipeline. therefore the next
1244 * buffer pushed is expected to result in an RTP packet with a timestamp equal
1245 * to the previous RTP packet incremented by DEFAULT_CLOCK_RATE. next the
1246 * pipeline is brought to NULL state and the timestamp-offset is set to a
1247 * specific value, the pipeline is then brought back to PLAYING state and the
1248 * two buffers pushed are expected to result in payloaded RTP packets that have
1249 * timestamps based on the set timestamp-offset incremented by multiples of
1250 * DEFAULT_CLOCK_RATE. next the boundary values of the timestamp-offset are
1251 * tested. again the pipeline state needs to be modified and buffers are pushed
1252 * and the resulting payloaded RTP packets' timestamps are validated. note that
1253 * the maximum timestamp-offset value will wrap around for the very last
1254 * payloaded RTP packet.
1255 */
GST_START_TEST(rtp_base_payload_property_timestamp_offset_test)1256 GST_START_TEST (rtp_base_payload_property_timestamp_offset_test)
1257 {
1258 guint32 rtptime;
1259 guint32 offset;
1260 State *state;
1261
1262 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1263
1264 set_state (state, GST_STATE_PLAYING);
1265
1266 g_object_get (state->element, "timestamp-offset", &offset, NULL);
1267 fail_unless_equals_int (offset, -1);
1268
1269 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1270
1271 g_object_set (state->element, "timestamp-offset", 0x42, NULL);
1272 g_object_get (state->element, "timestamp-offset", &offset, NULL);
1273 fail_unless_equals_int (offset, 0x42);
1274 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1275
1276 set_state (state, GST_STATE_NULL);
1277 g_object_set (state->element, "timestamp-offset", 0x4242, NULL);
1278 g_object_get (state->element, "timestamp-offset", &offset, NULL);
1279 fail_unless_equals_int (offset, 0x4242);
1280 set_state (state, GST_STATE_PLAYING);
1281
1282 push_buffer (state, "pts", 2 * GST_SECOND, NULL);
1283
1284 push_buffer (state, "pts", 3 * GST_SECOND, NULL);
1285
1286 set_state (state, GST_STATE_NULL);
1287 g_object_set (state->element, "timestamp-offset", 0, NULL);
1288 set_state (state, GST_STATE_PLAYING);
1289
1290 push_buffer (state, "pts", 4 * GST_SECOND, NULL);
1291
1292 push_buffer (state, "pts", 5 * GST_SECOND, NULL);
1293
1294 set_state (state, GST_STATE_NULL);
1295 g_object_set (state->element, "timestamp-offset", G_MAXUINT32, NULL);
1296 set_state (state, GST_STATE_PLAYING);
1297
1298 push_buffer (state, "pts", 6 * GST_SECOND, NULL);
1299
1300 push_buffer (state, "pts", 7 * GST_SECOND, NULL);
1301
1302 set_state (state, GST_STATE_NULL);
1303
1304 validate_buffers_received (8);
1305
1306 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
1307 get_buffer_field (0, "rtptime", &rtptime, NULL);
1308
1309 validate_buffer (1,
1310 "pts", 1 * GST_SECOND, "rtptime", rtptime + 1 * DEFAULT_CLOCK_RATE, NULL);
1311
1312 validate_buffer (2,
1313 "pts", 2 * GST_SECOND, "rtptime", 0x4242 + 2 * DEFAULT_CLOCK_RATE, NULL);
1314
1315 validate_buffer (3,
1316 "pts", 3 * GST_SECOND, "rtptime", 0x4242 + 3 * DEFAULT_CLOCK_RATE, NULL);
1317
1318 validate_buffer (4,
1319 "pts", 4 * GST_SECOND, "rtptime", 0 + 4 * DEFAULT_CLOCK_RATE, NULL);
1320
1321 validate_buffer (5,
1322 "pts", 5 * GST_SECOND, "rtptime", 0 + 5 * DEFAULT_CLOCK_RATE, NULL);
1323
1324 validate_buffer (6,
1325 "pts", 6 * GST_SECOND,
1326 "rtptime", G_MAXUINT32 + 6 * DEFAULT_CLOCK_RATE, NULL);
1327
1328 validate_buffer (7,
1329 "pts", 7 * GST_SECOND, "rtptime", 7 * DEFAULT_CLOCK_RATE - 1, NULL);
1330
1331 validate_events_received (12);
1332
1333 validate_normal_start_events (0);
1334
1335 validate_normal_start_events (3);
1336
1337 validate_normal_start_events (6);
1338
1339 validate_normal_start_events (9);
1340
1341 destroy_payloader (state);
1342 }
1343
1344 GST_END_TEST;
1345
1346 /* as for timestamp-offset above setting the seqnum-offset property of a
1347 * payloader will only take effect when the payloader goes from READY to PAUSED
1348 * state. this test starts by validating that seqnum-offset indicates random
1349 * sequence numbers and that the random sequence numbers increment by one for
1350 * each payloaded RTP packet. also it is verified that setting seqnum-offset
1351 * without bringing the pipeline to READY will not affect the payloaded RTP
1352 * packets' sequence numbers. next the pipeline is brought to NULL state,
1353 * seqnum-offset is set to a specific value before bringing the pipeline back to
1354 * PLAYING state. the next two buffers pushed are expected to resulting in
1355 * payloaded RTP packets that start with sequence numbers relating to the set
1356 * seqnum-offset value, and that again increment by one for each packet. finally
1357 * the boundary values of seqnum-offset are tested. this means bringing the
1358 * pipeline to NULL state, setting the seqnum-offset and bringing the pipeline
1359 * back to PLAYING state. note that for the very last payloded RTP packet the
1360 * sequence number will have wrapped around because the previous packet is
1361 * expected to have the maximum sequence number value.
1362 */
GST_START_TEST(rtp_base_payload_property_seqnum_offset_test)1363 GST_START_TEST (rtp_base_payload_property_seqnum_offset_test)
1364 {
1365 State *state;
1366 guint16 seq;
1367 gint offset;
1368
1369 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1370
1371 set_state (state, GST_STATE_PLAYING);
1372
1373 g_object_get (state->element, "seqnum-offset", &offset, NULL);
1374 fail_unless_equals_int (offset, -1);
1375
1376 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1377
1378 g_object_set (state->element, "seqnum-offset", 0x42, NULL);
1379 g_object_get (state->element, "seqnum-offset", &offset, NULL);
1380 fail_unless_equals_int (offset, 0x42);
1381 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1382
1383 set_state (state, GST_STATE_NULL);
1384 g_object_set (state->element, "seqnum-offset", 0x4242, NULL);
1385 g_object_get (state->element, "seqnum-offset", &offset, NULL);
1386 fail_unless_equals_int (offset, 0x4242);
1387 set_state (state, GST_STATE_PLAYING);
1388
1389 push_buffer (state, "pts", 2 * GST_SECOND, NULL);
1390
1391 push_buffer (state, "pts", 3 * GST_SECOND, NULL);
1392
1393 set_state (state, GST_STATE_NULL);
1394 g_object_set (state->element, "seqnum-offset", -1, NULL);
1395 set_state (state, GST_STATE_PLAYING);
1396
1397 push_buffer (state, "pts", 4 * GST_SECOND, NULL);
1398
1399 push_buffer (state, "pts", 5 * GST_SECOND, NULL);
1400
1401 set_state (state, GST_STATE_NULL);
1402 g_object_set (state->element, "seqnum-offset", G_MAXUINT16, NULL);
1403 set_state (state, GST_STATE_PLAYING);
1404
1405 push_buffer (state, "pts", 6 * GST_SECOND, NULL);
1406
1407 push_buffer (state, "pts", 7 * GST_SECOND, NULL);
1408
1409 set_state (state, GST_STATE_NULL);
1410
1411 validate_buffers_received (8);
1412
1413 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
1414 get_buffer_field (0, "seq", &seq, NULL);
1415
1416 validate_buffer (1, "pts", 1 * GST_SECOND, "seq", seq + 1, NULL);
1417
1418 validate_buffer (2, "pts", 2 * GST_SECOND, "seq", 0x4242, NULL);
1419
1420 validate_buffer (3, "pts", 3 * GST_SECOND, "seq", 0x4242 + 1, NULL);
1421
1422 validate_buffer (4, "pts", 4 * GST_SECOND, NULL);
1423 get_buffer_field (4, "seq", &seq, NULL);
1424
1425 validate_buffer (5, "pts", 5 * GST_SECOND, "seq", seq + 1, NULL);
1426
1427 validate_buffer (6, "pts", 6 * GST_SECOND, "seq", G_MAXUINT16, NULL);
1428
1429 validate_buffer (7, "pts", 7 * GST_SECOND, "seq", 0, NULL);
1430
1431 validate_events_received (12);
1432
1433 validate_normal_start_events (0);
1434
1435 validate_normal_start_events (3);
1436
1437 validate_normal_start_events (6);
1438
1439 validate_normal_start_events (9);
1440
1441 destroy_payloader (state);
1442 }
1443
1444 GST_END_TEST;
1445
1446 /* a payloader's max-ptime property is linked to its MTU property. whenever a
1447 * packet is larger than MTU or has a duration longer than max-ptime it will be
1448 * considered to be full. so this test first validates that the default value of
1449 * max-ptime is unspecified. then it retrieves the MTU and validates that a
1450 * packet of size MTU will not be considered full even if the duration is at its
1451 * maximum value. however incrementing the size to exceed the MTU will result in
1452 * the packet being full. next max-ptime is set to a value and it is verified
1453 * that only if both the size and duration are below the allowed values then the
1454 * packet will be considered not to be full, otherwise it will be reported as
1455 * being full. finally the boundary values of the property are tested in a
1456 * similar fashion.
1457 */
GST_START_TEST(rtp_base_payload_property_max_ptime_test)1458 GST_START_TEST (rtp_base_payload_property_max_ptime_test)
1459 {
1460 gint64 max_ptime;
1461 State *state;
1462 guint mtu;
1463
1464 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1465
1466 g_object_get (state->element, "max-ptime", &max_ptime, NULL);
1467 fail_unless_equals_int64 (max_ptime, -1);
1468 g_object_get (state->element, "mtu", &mtu, NULL);
1469 validate_would_not_be_filled (state, mtu, G_MAXINT64 - 1);
1470 validate_would_be_filled (state, mtu + 1, G_MAXINT64 - 1);
1471
1472 g_object_set (state->element, "max-ptime", GST_SECOND, NULL);
1473 g_object_get (state->element, "max-ptime", &max_ptime, NULL);
1474 fail_unless_equals_int64 (max_ptime, GST_SECOND);
1475 validate_would_not_be_filled (state, mtu, GST_SECOND - 1);
1476 validate_would_be_filled (state, mtu, GST_SECOND);
1477 validate_would_be_filled (state, mtu + 1, GST_SECOND - 1);
1478 validate_would_be_filled (state, mtu + 1, GST_SECOND);
1479
1480 g_object_set (state->element, "max-ptime", G_GUINT64_CONSTANT (-1), NULL);
1481 g_object_get (state->element, "max-ptime", &max_ptime, NULL);
1482 fail_unless_equals_int64 (max_ptime, G_GUINT64_CONSTANT (-1));
1483 validate_would_not_be_filled (state, mtu, G_MAXINT64 - 1);
1484 validate_would_be_filled (state, mtu + 1, G_MAXINT64 - 1);
1485
1486 g_object_set (state->element, "max-ptime", G_MAXINT64, NULL);
1487 g_object_get (state->element, "max-ptime", &max_ptime, NULL);
1488 fail_unless_equals_int64 (max_ptime, G_MAXINT64);
1489 validate_would_be_filled (state, mtu, G_MAXINT64);
1490
1491 destroy_payloader (state);
1492 }
1493
1494 GST_END_TEST;
1495
1496 /* a basepayloader has a min-ptime property with an allowed range, the property
1497 * itself is never checked by the payloader but is meant to be used by
1498 * inheriting classes. therefore this test only validates that setting the
1499 * property will mean that retrieveing the property results in the value
1500 * previously being set. first the default value is validated, then a new
1501 * specific value, before finally testing the boundary values.
1502 */
GST_START_TEST(rtp_base_payload_property_min_ptime_test)1503 GST_START_TEST (rtp_base_payload_property_min_ptime_test)
1504 {
1505 State *state;
1506 guint64 reference, min_ptime;
1507
1508 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1509
1510 g_object_get (state->element, "min-ptime", &reference, NULL);
1511 fail_unless_equals_int (reference, 0);
1512
1513 g_object_set (state->element, "min-ptime", reference + 1, NULL);
1514 g_object_get (state->element, "min-ptime", &min_ptime, NULL);
1515 fail_unless_equals_int (min_ptime, reference + 1);
1516
1517 g_object_set (state->element, "min-ptime", G_GUINT64_CONSTANT (0), NULL);
1518 g_object_get (state->element, "min-ptime", &min_ptime, NULL);
1519 fail_unless_equals_int (min_ptime, 0);
1520
1521 g_object_set (state->element, "min-ptime", G_MAXINT64, NULL);
1522 g_object_get (state->element, "min-ptime", &min_ptime, NULL);
1523 fail_unless_equals_int64 (min_ptime, G_MAXINT64);
1524
1525 destroy_payloader (state);
1526 }
1527
1528 GST_END_TEST;
1529
1530 /* paylaoders have a timestamp property that reflects the timestamp of the last
1531 * payloaded RTP packet. in this test the timestamp-offset is set to a specific
1532 * value so that when the first buffer is pushed its timestamp can be predicted
1533 * and thus that the timestamp property also has this value. (if
1534 * timestamp-offset was not set the timestamp would be random). another buffer
1535 * is then pushed and its timestamp is expected to increment by
1536 * DEFAULT_CLOCK_RATE.
1537 */
GST_START_TEST(rtp_base_payload_property_timestamp_test)1538 GST_START_TEST (rtp_base_payload_property_timestamp_test)
1539 {
1540 State *state;
1541 guint32 timestamp;
1542
1543 state = create_payloader ("application/x-rtp", &sinktmpl,
1544 "timestamp-offset", 0, NULL);
1545
1546 set_state (state, GST_STATE_PLAYING);
1547
1548 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1549 g_object_get (state->element, "timestamp", ×tamp, NULL);
1550 fail_unless_equals_int (timestamp, 0);
1551
1552 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1553 g_object_get (state->element, "timestamp", ×tamp, NULL);
1554 fail_unless_equals_int (timestamp, DEFAULT_CLOCK_RATE);
1555
1556 set_state (state, GST_STATE_NULL);
1557
1558 validate_buffers_received (2);
1559
1560 validate_buffer (0, "pts", 0 * GST_SECOND, "rtptime", 0, NULL);
1561
1562 validate_buffer (1,
1563 "pts", 1 * GST_SECOND, "rtptime", DEFAULT_CLOCK_RATE, NULL);
1564
1565 validate_events_received (3);
1566
1567 validate_normal_start_events (0);
1568
1569 destroy_payloader (state);
1570 }
1571
1572 GST_END_TEST;
1573
1574 /* basepayloaders have a seqnum property that is supposed to contain the
1575 * sequence number of the last payloaded RTP packet. so therefore this test
1576 * initializes the seqnum-offset property to a know value and pushes a buffer.
1577 * the payloaded RTP packet is expected to have a sequence number equal to the
1578 * set seqnum-offset, as is the seqnum property. next another buffer is pushed
1579 * and then both the payloaded RTP packet and the seqnum property value are
1580 * expected to increment by one compared to the previous packet.
1581 */
GST_START_TEST(rtp_base_payload_property_seqnum_test)1582 GST_START_TEST (rtp_base_payload_property_seqnum_test)
1583 {
1584 State *state;
1585 guint seq;
1586
1587 state = create_payloader ("application/x-rtp", &sinktmpl,
1588 "seqnum-offset", 0, NULL);
1589
1590 set_state (state, GST_STATE_PLAYING);
1591
1592 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1593 g_object_get (state->element, "seqnum", &seq, NULL);
1594 fail_unless_equals_int (seq, 0);
1595
1596 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1597 g_object_get (state->element, "seqnum", &seq, NULL);
1598 fail_unless_equals_int (seq, 1);
1599
1600 set_state (state, GST_STATE_NULL);
1601
1602 validate_buffers_received (2);
1603
1604 validate_buffer (0, "pts", 0 * GST_SECOND, "seq", 0, NULL);
1605
1606 validate_buffer (1, "pts", 1 * GST_SECOND, "seq", 1, NULL);
1607
1608 validate_events_received (3);
1609
1610 validate_normal_start_events (0);
1611
1612 destroy_payloader (state);
1613 }
1614
1615 GST_END_TEST;
1616
1617 /* basepayloader has a perfect-rtptime property when it is set to FALSE
1618 * the timestamps of payloaded RTP packets will determined by initial
1619 * timestamp-offset (usually random) as well as the clock-rate. when
1620 * perfect-rtptime is set to TRUE the timestamps of payloaded RTP packets are
1621 * instead determined by the timestamp of the first packet and then the
1622 * difference in offset of the input buffers.
1623 *
1624 * to verify that this test starts by setting the timestamp-offset to a specific
1625 * value to prevent random timestamps of the RTP packets. next perfect-rtptime
1626 * is set to FALSE. the two buffers pushed will result in two payloaded RTP
1627 * packets whose timestamps differ based on the current clock-rate
1628 * DEFAULT_CLOCK_RATE. the next step is to set perfect-rtptime to TRUE. the two
1629 * buffers that are pushed will result in two payloaded RTP packets. the first
1630 * of these RTP packets has a timestamp that relates to the previous packet and
1631 * the difference in offset between the middle two input buffers. the latter of
1632 * the two RTP packets has a timestamp that instead relates to the offset of the
1633 * last two input buffers.
1634 */
GST_START_TEST(rtp_base_payload_property_perfect_rtptime_test)1635 GST_START_TEST (rtp_base_payload_property_perfect_rtptime_test)
1636 {
1637 State *state;
1638 guint32 timestamp_base = 0;
1639 gboolean perfect;
1640
1641 state = create_payloader ("application/x-rtp", &sinktmpl,
1642 "timestamp-offset", timestamp_base, NULL);
1643
1644 set_state (state, GST_STATE_PLAYING);
1645
1646 g_object_set (state->element, "perfect-rtptime", FALSE, NULL);
1647 g_object_get (state->element, "perfect-rtptime", &perfect, NULL);
1648 fail_unless (!perfect);
1649
1650 push_buffer (state, "pts", 0 * GST_SECOND, "offset", G_GINT64_CONSTANT (0),
1651 NULL);
1652
1653 push_buffer (state, "pts", 1 * GST_SECOND, "offset", G_GINT64_CONSTANT (17),
1654 NULL);
1655
1656 g_object_set (state->element, "perfect-rtptime", TRUE, NULL);
1657 g_object_get (state->element, "perfect-rtptime", &perfect, NULL);
1658 fail_unless (perfect);
1659
1660 push_buffer (state, "pts", 2 * GST_SECOND, "offset", G_GINT64_CONSTANT (31),
1661 NULL);
1662
1663 push_buffer (state, "pts", 3 * GST_SECOND, "offset", G_GINT64_CONSTANT (67),
1664 NULL);
1665
1666 set_state (state, GST_STATE_NULL);
1667
1668 validate_buffers_received (4);
1669
1670 validate_buffer (0,
1671 "pts", 0 * GST_SECOND, "offset", G_GINT64_CONSTANT (0), "rtptime",
1672 timestamp_base, NULL);
1673
1674 validate_buffer (1,
1675 "pts", 1 * GST_SECOND,
1676 "offset", G_GINT64_CONSTANT (17), "rtptime",
1677 timestamp_base + 1 * DEFAULT_CLOCK_RATE, NULL);
1678
1679 validate_buffer (2,
1680 "pts", 2 * GST_SECOND,
1681 "offset", G_GINT64_CONSTANT (31),
1682 "rtptime", timestamp_base + 1 * DEFAULT_CLOCK_RATE + (31 - 17), NULL);
1683
1684 validate_buffer (3,
1685 "pts", 3 * GST_SECOND,
1686 "offset", G_GINT64_CONSTANT (67),
1687 "rtptime", timestamp_base + 1 * DEFAULT_CLOCK_RATE + (67 - 17), NULL);
1688
1689 validate_events_received (3);
1690
1691 validate_normal_start_events (0);
1692
1693 destroy_payloader (state);
1694 }
1695
1696 GST_END_TEST;
1697
1698 /* basepayloaders have a ptime-multiple property but its value does not affect
1699 * any payloaded RTP packets as this is supposed to be done by inherited
1700 * classes. therefore this test only validates the default value of the
1701 * property, makes sure that a set value actually sticks and that the boundary
1702 * values are indeed allowed to be set.
1703 */
GST_START_TEST(rtp_base_payload_property_ptime_multiple_test)1704 GST_START_TEST (rtp_base_payload_property_ptime_multiple_test)
1705 {
1706 State *state;
1707 gint64 multiple;
1708
1709 state = create_payloader ("application/x-rtp", &sinktmpl, NULL);
1710
1711 g_object_get (state->element, "ptime-multiple", &multiple, NULL);
1712 fail_unless_equals_int64 (multiple, 0);
1713
1714 g_object_set (state->element, "ptime-multiple", G_GINT64_CONSTANT (42), NULL);
1715 g_object_get (state->element, "ptime-multiple", &multiple, NULL);
1716 fail_unless_equals_int64 (multiple, 42);
1717
1718 g_object_set (state->element, "ptime-multiple", G_GINT64_CONSTANT (0), NULL);
1719 g_object_get (state->element, "ptime-multiple", &multiple, NULL);
1720 fail_unless_equals_int64 (multiple, 0);
1721
1722 g_object_set (state->element, "ptime-multiple", G_MAXINT64, NULL);
1723 g_object_get (state->element, "ptime-multiple", &multiple, NULL);
1724 fail_unless_equals_int64 (multiple, G_MAXINT64);
1725
1726 destroy_payloader (state);
1727 }
1728
1729 GST_END_TEST;
1730
1731 /* basepayloaders have a property called stats that is used to atomically
1732 * retrieve several values (clock-rate, running-time, seqnum and timestamp) that
1733 * relate to the stream and its current progress. this test is meant to test
1734 * retrieval of these values.
1735 *
1736 * first of all perfect-rtptime is set to TRUE, next the the test starts out by
1737 * setting seqnum-offset and timestamp-offset to known values to prevent that
1738 * sequence numbers and timestamps of payloaded RTP packets are random. next the
1739 * stats property is retrieved. the clock-rate must be at the default
1740 * DEFAULT_CLOCK_RATE, while running-time must be equal to the first buffers
1741 * PTS. the sequence number should be equal to the initialized value of
1742 * seqnum-offset and the timestamp should be equal to the initialized value of
1743 * timestamp-offset. after pushing a second buffer the stats property is
1744 * validate again. this time running-time, seqnum and timestamp should have
1745 * advanced as expected. next the pipeline is brought to NULL state to be able
1746 * to change the perfect-rtptime property to FALSE before going back to PLAYING
1747 * state. this is done to validate that the stats values reflect normal
1748 * timestamp updates that are not based on input buffer offsets as expected.
1749 * lastly two buffers are pushed and the stats property retrieved after each
1750 * time. here it is expected that the sequence numbers values are restarted at
1751 * the inital value while the timestamps and running-time reflect the input
1752 * buffers.
1753 */
GST_START_TEST(rtp_base_payload_property_stats_test)1754 GST_START_TEST (rtp_base_payload_property_stats_test)
1755 {
1756 State *state;
1757
1758 state = create_payloader ("application/x-rtp", &sinktmpl,
1759 "perfect-rtptime", TRUE, "seqnum-offset", 0, "timestamp-offset", 0, NULL);
1760
1761 set_state (state, GST_STATE_PLAYING);
1762
1763 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1764 validate_stats (state,
1765 DEFAULT_CLOCK_RATE, 0 * GST_SECOND, 0, 0 * DEFAULT_CLOCK_RATE);
1766
1767 push_buffer (state, "pts", 1 * GST_SECOND, NULL);
1768 validate_stats (state,
1769 DEFAULT_CLOCK_RATE, 1 * DEFAULT_CLOCK_RATE, 1, 1 * DEFAULT_CLOCK_RATE);
1770
1771 set_state (state, GST_STATE_NULL);
1772 g_object_set (state->element, "perfect-rtptime", FALSE, NULL);
1773 set_state (state, GST_STATE_PLAYING);
1774
1775 push_buffer (state, "pts", 2 * GST_SECOND, NULL);
1776 validate_stats (state,
1777 DEFAULT_CLOCK_RATE, 2 * GST_SECOND, 0, 2 * DEFAULT_CLOCK_RATE);
1778
1779 push_buffer (state, "pts", 3 * GST_SECOND, NULL);
1780 validate_stats (state,
1781 DEFAULT_CLOCK_RATE, 3 * GST_SECOND, 1, 3 * DEFAULT_CLOCK_RATE);
1782 set_state (state, GST_STATE_NULL);
1783
1784 validate_buffers_received (4);
1785
1786 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
1787
1788 validate_buffer (1, "pts", 1 * GST_SECOND, NULL);
1789
1790 validate_buffer (2, "pts", 2 * GST_SECOND, NULL);
1791
1792 validate_buffer (3, "pts", 3 * GST_SECOND, NULL);
1793
1794 validate_events_received (6);
1795
1796 validate_normal_start_events (0);
1797
1798 validate_normal_start_events (3);
1799
1800 destroy_payloader (state);
1801 }
1802
1803 GST_END_TEST;
1804
1805 /* basepayloader has a property source-info that makes it aware of RTP
1806 * source information passed as GstRTPSourceMeta on the input buffers. All
1807 * sources found in the meta will be added to the list of CSRCs in the RTP
1808 * header. A useful scenario for this is, for instance, to signal which
1809 * sources contributed to a mixed audio stream. */
GST_START_TEST(rtp_base_payload_property_source_info_test)1810 GST_START_TEST (rtp_base_payload_property_source_info_test)
1811 {
1812 GstHarness *h;
1813 GstRtpDummyPay *pay;
1814 GstBuffer *buffer;
1815 guint csrc_count = 2;
1816 const guint32 csrc[] = { 0x11, 0x22 };
1817 const guint32 ssrc = 0x33;
1818
1819 pay = rtp_dummy_pay_new ();
1820 h = gst_harness_new_with_element (GST_ELEMENT_CAST (pay), "sink", "src");
1821 gst_harness_set_src_caps_str (h, "application/x-rtp");
1822
1823 /* Input buffer has no meta, payloader should not add CSRC */
1824 g_object_set (pay, "source-info", TRUE, NULL);
1825 buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1826 buffer = gst_harness_push_and_pull (h, buffer);
1827 validate_buffer1 (buffer, "csrc-count", 0, NULL);
1828 fail_if (gst_buffer_get_rtp_source_meta (buffer));
1829 gst_buffer_unref (buffer);
1830
1831 /* Input buffer has meta, payloader should add CSRC */
1832 buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1833 fail_unless (gst_buffer_add_rtp_source_meta (buffer, &ssrc, csrc,
1834 csrc_count));
1835 buffer = gst_harness_push_and_pull (h, buffer);
1836 /* The meta SSRC should be added as the last contributing source */
1837 validate_buffer1 (buffer, "csrc-count", 3, "csrc", 0, csrc[0],
1838 "csrc", 1, csrc[1], "csrc", 2, ssrc, NULL);
1839 fail_if (gst_buffer_get_rtp_source_meta (buffer));
1840 gst_buffer_unref (buffer);
1841
1842 /* When property is disabled, the meta should be ignored and no CSRC
1843 * added. */
1844 g_object_set (pay, "source-info", FALSE, NULL);
1845 buffer = gst_rtp_buffer_new_allocate (0, 0, 0);
1846 fail_unless (gst_buffer_add_rtp_source_meta (buffer, NULL, csrc, csrc_count));
1847 buffer = gst_harness_push_and_pull (h, buffer);
1848 validate_buffer1 (buffer, "csrc-count", 0, NULL);
1849 fail_if (gst_buffer_get_rtp_source_meta (buffer));
1850 gst_buffer_unref (buffer);
1851
1852 g_object_unref (pay);
1853 gst_harness_teardown (h);
1854 }
1855
1856 GST_END_TEST;
1857
1858 /* push a single buffer to the payloader which should successfully payload it
1859 * into an RTP packet. besides the payloaded RTP packet there should be the
1860 * three events initial events: stream-start, caps and segment. because of that
1861 * the input caps has framerate this will be propagated to an a-framerate field
1862 * on the output caps.
1863 */
GST_START_TEST(rtp_base_payload_framerate_attribute)1864 GST_START_TEST (rtp_base_payload_framerate_attribute)
1865 {
1866 State *state;
1867
1868 state = create_payloader ("video/x-raw,framerate=(fraction)1/4", &sinktmpl,
1869 "perfect-rtptime", FALSE, NULL);
1870
1871 set_state (state, GST_STATE_PLAYING);
1872
1873 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1874
1875 set_state (state, GST_STATE_NULL);
1876
1877 validate_buffers_received (1);
1878
1879 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
1880
1881 validate_events_received (3);
1882
1883 validate_normal_start_events (0);
1884
1885 validate_event (1, "caps", "a-framerate", "0.25", NULL);
1886
1887 destroy_payloader (state);
1888 }
1889
1890 GST_END_TEST;
1891
1892 /* push a single buffer to the payloader which should successfully payload it
1893 * into an RTP packet. besides the payloaded RTP packet there should be the
1894 * three events initial events: stream-start, caps and segment. because of that
1895 * the input caps has both framerate and max-framerate set the a-framerate field
1896 * on the output caps will correspond to the value of the max-framerate field.
1897 */
GST_START_TEST(rtp_base_payload_max_framerate_attribute)1898 GST_START_TEST (rtp_base_payload_max_framerate_attribute)
1899 {
1900 State *state;
1901
1902 state =
1903 create_payloader
1904 ("video/x-raw,framerate=(fraction)0/1,max-framerate=(fraction)1/8",
1905 &sinktmpl, "perfect-rtptime", FALSE, NULL);
1906
1907 set_state (state, GST_STATE_PLAYING);
1908
1909 push_buffer (state, "pts", 0 * GST_SECOND, NULL);
1910
1911 set_state (state, GST_STATE_NULL);
1912
1913 validate_buffers_received (1);
1914
1915 validate_buffer (0, "pts", 0 * GST_SECOND, NULL);
1916
1917 validate_events_received (3);
1918
1919 validate_normal_start_events (0);
1920
1921 validate_event (1, "caps", "a-framerate", "0.125", NULL);
1922
1923 destroy_payloader (state);
1924 }
1925
1926 GST_END_TEST;
1927
1928 static Suite *
rtp_basepayloading_suite(void)1929 rtp_basepayloading_suite (void)
1930 {
1931 Suite *s = suite_create ("rtp_base_payloading_test");
1932 TCase *tc_chain = tcase_create ("payloading tests");
1933
1934 tcase_set_timeout (tc_chain, 60);
1935
1936 suite_add_tcase (s, tc_chain);
1937 tcase_add_test (tc_chain, rtp_base_payload_buffer_test);
1938 tcase_add_test (tc_chain, rtp_base_payload_buffer_list_test);
1939
1940 tcase_add_test (tc_chain, rtp_base_payload_normal_rtptime_test);
1941 tcase_add_test (tc_chain, rtp_base_payload_perfect_rtptime_test);
1942 tcase_add_test (tc_chain, rtp_base_payload_no_pts_no_offset_test);
1943
1944 tcase_add_test (tc_chain, rtp_base_payload_downstream_caps_test);
1945
1946 tcase_add_test (tc_chain, rtp_base_payload_ssrc_collision_test);
1947 tcase_add_test (tc_chain, rtp_base_payload_reconfigure_test);
1948
1949 tcase_add_test (tc_chain, rtp_base_payload_property_mtu_test);
1950 tcase_add_test (tc_chain, rtp_base_payload_property_pt_test);
1951 tcase_add_test (tc_chain, rtp_base_payload_property_ssrc_test);
1952 tcase_add_test (tc_chain, rtp_base_payload_property_timestamp_offset_test);
1953 tcase_add_test (tc_chain, rtp_base_payload_property_seqnum_offset_test);
1954 tcase_add_test (tc_chain, rtp_base_payload_property_max_ptime_test);
1955 tcase_add_test (tc_chain, rtp_base_payload_property_min_ptime_test);
1956 tcase_add_test (tc_chain, rtp_base_payload_property_timestamp_test);
1957 tcase_add_test (tc_chain, rtp_base_payload_property_seqnum_test);
1958 tcase_add_test (tc_chain, rtp_base_payload_property_perfect_rtptime_test);
1959 tcase_add_test (tc_chain, rtp_base_payload_property_ptime_multiple_test);
1960 tcase_add_test (tc_chain, rtp_base_payload_property_stats_test);
1961 tcase_add_test (tc_chain, rtp_base_payload_property_source_info_test);
1962
1963 tcase_add_test (tc_chain, rtp_base_payload_framerate_attribute);
1964 tcase_add_test (tc_chain, rtp_base_payload_max_framerate_attribute);
1965
1966 return s;
1967 }
1968
1969 GST_CHECK_MAIN (rtp_basepayloading)
1970