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, &timestamp, &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, &timestamp, &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", &timestamp, 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", &timestamp, 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