a0b7d6d13747eb4b437e9ccb4316fa83c123c06f
[platform/upstream/gst-plugins-base.git] / gst-libs / gst / rtp / gstrtpbasepayload.c
1 /* GStreamer
2  * Copyright (C) <2005> Wim Taymans <wim@fluendo.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
13  */
14
15 /**
16  * SECTION:gstrtpbasepayload
17  * @short_description: Base class for RTP payloader
18  *
19  * Provides a base class for RTP payloaders
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <string.h>
27
28 #include <gst/rtp/gstrtpbuffer.h>
29
30 #include "gstrtpbasepayload.h"
31
32 GST_DEBUG_CATEGORY_STATIC (rtpbasepayload_debug);
33 #define GST_CAT_DEFAULT (rtpbasepayload_debug)
34
35 #define GST_RTP_BASE_PAYLOAD_GET_PRIVATE(obj)  \
36    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTP_BASE_PAYLOAD, GstRTPBasePayloadPrivate))
37
38 struct _GstRTPBasePayloadPrivate
39 {
40   gboolean ts_offset_random;
41   gboolean seqnum_offset_random;
42   gboolean ssrc_random;
43   guint16 next_seqnum;
44   gboolean perfect_rtptime;
45   gint notified_first_timestamp;
46
47   guint64 base_offset;
48   gint64 base_rtime;
49   guint64 base_rtime_hz;
50   guint64 running_time;
51
52   gint64 prop_max_ptime;
53   gint64 caps_max_ptime;
54
55   gboolean negotiated;
56
57   gboolean delay_segment;
58   GstEvent *pending_segment;
59 };
60
61 /* RTPBasePayload signals and args */
62 enum
63 {
64   /* FILL ME */
65   LAST_SIGNAL
66 };
67
68 /* FIXME 0.11, a better default is the Ethernet MTU of
69  * 1500 - sizeof(headers) as pointed out by marcelm in IRC:
70  * So an Ethernet MTU of 1500, minus 60 for the max IP, minus 8 for UDP, gives
71  * 1432 bytes or so.  And that should be adjusted downward further for other
72  * encapsulations like PPPoE, so 1400 at most.
73  */
74 #define DEFAULT_MTU                     1400
75 #define DEFAULT_PT                      96
76 #define DEFAULT_SSRC                    -1
77 #define DEFAULT_TIMESTAMP_OFFSET        -1
78 #define DEFAULT_SEQNUM_OFFSET           -1
79 #define DEFAULT_MAX_PTIME               -1
80 #define DEFAULT_MIN_PTIME               0
81 #define DEFAULT_PERFECT_RTPTIME         TRUE
82 #define DEFAULT_PTIME_MULTIPLE          0
83 #define DEFAULT_RUNNING_TIME            GST_CLOCK_TIME_NONE
84
85 enum
86 {
87   PROP_0,
88   PROP_MTU,
89   PROP_PT,
90   PROP_SSRC,
91   PROP_TIMESTAMP_OFFSET,
92   PROP_SEQNUM_OFFSET,
93   PROP_MAX_PTIME,
94   PROP_MIN_PTIME,
95   PROP_TIMESTAMP,
96   PROP_SEQNUM,
97   PROP_PERFECT_RTPTIME,
98   PROP_PTIME_MULTIPLE,
99   PROP_STATS,
100   PROP_LAST
101 };
102
103 static void gst_rtp_base_payload_class_init (GstRTPBasePayloadClass * klass);
104 static void gst_rtp_base_payload_init (GstRTPBasePayload * rtpbasepayload,
105     gpointer g_class);
106 static void gst_rtp_base_payload_finalize (GObject * object);
107
108 static GstCaps *gst_rtp_base_payload_getcaps_default (GstRTPBasePayload *
109     rtpbasepayload, GstPad * pad, GstCaps * filter);
110
111 static gboolean gst_rtp_base_payload_sink_event_default (GstRTPBasePayload *
112     rtpbasepayload, GstEvent * event);
113 static gboolean gst_rtp_base_payload_sink_event (GstPad * pad,
114     GstObject * parent, GstEvent * event);
115 static gboolean gst_rtp_base_payload_src_event_default (GstRTPBasePayload *
116     rtpbasepayload, GstEvent * event);
117 static gboolean gst_rtp_base_payload_src_event (GstPad * pad,
118     GstObject * parent, GstEvent * event);
119 static gboolean gst_rtp_base_payload_query_default (GstRTPBasePayload *
120     rtpbasepayload, GstPad * pad, GstQuery * query);
121 static gboolean gst_rtp_base_payload_query (GstPad * pad, GstObject * parent,
122     GstQuery * query);
123 static GstFlowReturn gst_rtp_base_payload_chain (GstPad * pad,
124     GstObject * parent, GstBuffer * buffer);
125
126 static void gst_rtp_base_payload_set_property (GObject * object, guint prop_id,
127     const GValue * value, GParamSpec * pspec);
128 static void gst_rtp_base_payload_get_property (GObject * object, guint prop_id,
129     GValue * value, GParamSpec * pspec);
130
131 static GstStateChangeReturn gst_rtp_base_payload_change_state (GstElement *
132     element, GstStateChange transition);
133
134 static GstElementClass *parent_class = NULL;
135
136 GType
137 gst_rtp_base_payload_get_type (void)
138 {
139   static GType rtpbasepayload_type = 0;
140
141   if (g_once_init_enter ((gsize *) & rtpbasepayload_type)) {
142     static const GTypeInfo rtpbasepayload_info = {
143       sizeof (GstRTPBasePayloadClass),
144       NULL,
145       NULL,
146       (GClassInitFunc) gst_rtp_base_payload_class_init,
147       NULL,
148       NULL,
149       sizeof (GstRTPBasePayload),
150       0,
151       (GInstanceInitFunc) gst_rtp_base_payload_init,
152     };
153
154     g_once_init_leave ((gsize *) & rtpbasepayload_type,
155         g_type_register_static (GST_TYPE_ELEMENT, "GstRTPBasePayload",
156             &rtpbasepayload_info, G_TYPE_FLAG_ABSTRACT));
157   }
158   return rtpbasepayload_type;
159 }
160
161 static void
162 gst_rtp_base_payload_class_init (GstRTPBasePayloadClass * klass)
163 {
164   GObjectClass *gobject_class;
165   GstElementClass *gstelement_class;
166
167   gobject_class = (GObjectClass *) klass;
168   gstelement_class = (GstElementClass *) klass;
169
170   g_type_class_add_private (klass, sizeof (GstRTPBasePayloadPrivate));
171
172   parent_class = g_type_class_peek_parent (klass);
173
174   gobject_class->finalize = gst_rtp_base_payload_finalize;
175
176   gobject_class->set_property = gst_rtp_base_payload_set_property;
177   gobject_class->get_property = gst_rtp_base_payload_get_property;
178
179   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU,
180       g_param_spec_uint ("mtu", "MTU",
181           "Maximum size of one packet",
182           28, G_MAXUINT, DEFAULT_MTU,
183           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
184   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
185       g_param_spec_uint ("pt", "payload type",
186           "The payload type of the packets", 0, 0x7f, DEFAULT_PT,
187           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
188   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
189       g_param_spec_uint ("ssrc", "SSRC",
190           "The SSRC of the packets (default == random)", 0, G_MAXUINT32,
191           DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
192   g_object_class_install_property (G_OBJECT_CLASS (klass),
193       PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset",
194           "Timestamp Offset",
195           "Offset to add to all outgoing timestamps (default = random)", 0,
196           G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET,
197           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
199       g_param_spec_int ("seqnum-offset", "Sequence number Offset",
200           "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16,
201           DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
202   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME,
203       g_param_spec_int64 ("max-ptime", "Max packet time",
204           "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)",
205           -1, G_MAXINT64, DEFAULT_MAX_PTIME,
206           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
207   /**
208    * GstRTPBasePayload:min-ptime:
209    *
210    * Minimum duration of the packet data in ns (can't go above MTU)
211    **/
212   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME,
213       g_param_spec_int64 ("min-ptime", "Min packet time",
214           "Minimum duration of the packet data in ns (can't go above MTU)",
215           0, G_MAXINT64, DEFAULT_MIN_PTIME,
216           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
217
218   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
219       g_param_spec_uint ("timestamp", "Timestamp",
220           "The RTP timestamp of the last processed packet",
221           0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
222   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
223       g_param_spec_uint ("seqnum", "Sequence number",
224           "The RTP sequence number of the last processed packet",
225           0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
226
227   /**
228    * GstRTPBasePayload:perfect-rtptime:
229    *
230    * Try to use the offset fields to generate perfect RTP timestamps. When this
231    * option is disabled, RTP timestamps are generated from GST_BUFFER_PTS of
232    * each payloaded buffer. The PTSes of buffers may not necessarily increment
233    * with the amount of data in each input buffer, consider e.g. the case where
234    * the buffer arrives from a network which means that the PTS is unrelated to
235    * the amount of data. Because the RTP timestamps are generated from
236    * GST_BUFFER_PTS this can result in RTP timestamps that also don't increment
237    * with the amount of data in the payloaded packet. To circumvent this it is
238    * possible to set the perfect rtptime option enabled. When this option is
239    * enabled the payloader will increment the RTP timestamps based on
240    * GST_BUFFER_OFFSET which relates to the amount of data in each packet
241    * rather than the GST_BUFFER_PTS of each buffer and therefore the RTP
242    * timestamps will more closely correlate with the amount of data in each
243    * buffer. Currently GstRTPBasePayload is limited to handling perfect RTP
244    * timestamps for audio streams.
245    */
246   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PERFECT_RTPTIME,
247       g_param_spec_boolean ("perfect-rtptime", "Perfect RTP Time",
248           "Generate perfect RTP timestamps when possible",
249           DEFAULT_PERFECT_RTPTIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
250   /**
251    * GstRTPBasePayload:ptime-multiple:
252    *
253    * Force buffers to be multiples of this duration in ns (0 disables)
254    **/
255   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PTIME_MULTIPLE,
256       g_param_spec_int64 ("ptime-multiple", "Packet time multiple",
257           "Force buffers to be multiples of this duration in ns (0 disables)",
258           0, G_MAXINT64, DEFAULT_PTIME_MULTIPLE,
259           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
260
261   /**
262    * GstRTPBasePayload:stats:
263    *
264    * Various payloader statistics retrieved atomically (and are therefore
265    * synchroized with each other), these can be used e.g. to generate an
266    * RTP-Info header. This property return a GstStructure named
267    * application/x-rtp-payload-stats containing the following fields relating to
268    * the last processed buffer and current state of the stream being payloaded:
269    *
270    * <variablelist>
271    *   <varlistentry>
272    *     <term>clock-rate</term>
273    *     <listitem><para>#G_TYPE_UINT, clock-rate of the
274    *     stream</para></listitem>
275    *   </varlistentry>
276    *   <varlistentry>
277    *     <term>running-time</term>
278    *     <listitem><para>#G_TYPE_UINT64, running time
279    *     </para></listitem>
280    *   </varlistentry>
281    *   <varlistentry>
282    *     <term>seqnum</term>
283    *     <listitem><para>#G_TYPE_UINT, sequence number, same as
284    *     #GstRTPBasePayload:seqnum</para></listitem>
285    *   </varlistentry>
286    *   <varlistentry>
287    *     <term>timestamp</term>
288    *     <listitem><para>#G_TYPE_UINT, RTP timestamp, same as
289    *     #GstRTPBasePayload:timestamp</para></listitem>
290    *   </varlistentry>
291    *   <varlistentry>
292    *     <term>ssrc</term>
293    *     <listitem><para>#G_TYPE_UINT, The SSRC in use
294    *     </para></listitem>
295    *   </varlistentry>
296    *   <varlistentry>
297    *     <term>pt</term>
298    *     <listitem><para>#G_TYPE_UINT, The Payload type in use, same as
299    *     #GstRTPBasePayload:pt</para></listitem>
300    *   </varlistentry>
301    *   <varlistentry>
302    *     <term>seqnum-offset</term>
303    *     <listitem><para>#G_TYPE_UINT, The current offset added to the
304    *     seqnum</para></listitem>
305    *   </varlistentry>
306    *   <varlistentry>
307    *     <term>timestamp-offset</term>
308    *     <listitem><para>#G_TYPE_UINT, The current offset added to the
309    *     timestamp</para></listitem>
310    *   </varlistentry>
311    * </variablelist>
312    **/
313   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATS,
314       g_param_spec_boxed ("stats", "Statistics", "Various statistics",
315           GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
316
317   gstelement_class->change_state = gst_rtp_base_payload_change_state;
318
319   klass->get_caps = gst_rtp_base_payload_getcaps_default;
320   klass->sink_event = gst_rtp_base_payload_sink_event_default;
321   klass->src_event = gst_rtp_base_payload_src_event_default;
322   klass->query = gst_rtp_base_payload_query_default;
323
324   GST_DEBUG_CATEGORY_INIT (rtpbasepayload_debug, "rtpbasepayload", 0,
325       "Base class for RTP Payloaders");
326 }
327
328 static void
329 gst_rtp_base_payload_init (GstRTPBasePayload * rtpbasepayload, gpointer g_class)
330 {
331   GstPadTemplate *templ;
332   GstRTPBasePayloadPrivate *priv;
333
334   rtpbasepayload->priv = priv =
335       GST_RTP_BASE_PAYLOAD_GET_PRIVATE (rtpbasepayload);
336
337   templ =
338       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
339   g_return_if_fail (templ != NULL);
340
341   rtpbasepayload->srcpad = gst_pad_new_from_template (templ, "src");
342   gst_pad_set_event_function (rtpbasepayload->srcpad,
343       gst_rtp_base_payload_src_event);
344   gst_element_add_pad (GST_ELEMENT (rtpbasepayload), rtpbasepayload->srcpad);
345
346   templ =
347       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink");
348   g_return_if_fail (templ != NULL);
349
350   rtpbasepayload->sinkpad = gst_pad_new_from_template (templ, "sink");
351   gst_pad_set_chain_function (rtpbasepayload->sinkpad,
352       gst_rtp_base_payload_chain);
353   gst_pad_set_event_function (rtpbasepayload->sinkpad,
354       gst_rtp_base_payload_sink_event);
355   gst_pad_set_query_function (rtpbasepayload->sinkpad,
356       gst_rtp_base_payload_query);
357   gst_element_add_pad (GST_ELEMENT (rtpbasepayload), rtpbasepayload->sinkpad);
358
359   rtpbasepayload->mtu = DEFAULT_MTU;
360   rtpbasepayload->pt = DEFAULT_PT;
361   rtpbasepayload->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
362   rtpbasepayload->ssrc = DEFAULT_SSRC;
363   rtpbasepayload->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
364   priv->running_time = DEFAULT_RUNNING_TIME;
365   priv->seqnum_offset_random = (rtpbasepayload->seqnum_offset == -1);
366   priv->ts_offset_random = (rtpbasepayload->ts_offset == -1);
367   priv->ssrc_random = (rtpbasepayload->ssrc == -1);
368
369   rtpbasepayload->max_ptime = DEFAULT_MAX_PTIME;
370   rtpbasepayload->min_ptime = DEFAULT_MIN_PTIME;
371   rtpbasepayload->priv->perfect_rtptime = DEFAULT_PERFECT_RTPTIME;
372   rtpbasepayload->ptime_multiple = DEFAULT_PTIME_MULTIPLE;
373   rtpbasepayload->priv->base_offset = GST_BUFFER_OFFSET_NONE;
374   rtpbasepayload->priv->base_rtime_hz = GST_BUFFER_OFFSET_NONE;
375
376   rtpbasepayload->media = NULL;
377   rtpbasepayload->encoding_name = NULL;
378
379   rtpbasepayload->clock_rate = 0;
380
381   rtpbasepayload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
382   rtpbasepayload->priv->prop_max_ptime = DEFAULT_MAX_PTIME;
383 }
384
385 static void
386 gst_rtp_base_payload_finalize (GObject * object)
387 {
388   GstRTPBasePayload *rtpbasepayload;
389
390   rtpbasepayload = GST_RTP_BASE_PAYLOAD (object);
391
392   g_free (rtpbasepayload->media);
393   rtpbasepayload->media = NULL;
394   g_free (rtpbasepayload->encoding_name);
395   rtpbasepayload->encoding_name = NULL;
396
397   G_OBJECT_CLASS (parent_class)->finalize (object);
398 }
399
400 static GstCaps *
401 gst_rtp_base_payload_getcaps_default (GstRTPBasePayload * rtpbasepayload,
402     GstPad * pad, GstCaps * filter)
403 {
404   GstCaps *caps;
405
406   caps = GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
407   GST_DEBUG_OBJECT (pad,
408       "using pad template %p with caps %p %" GST_PTR_FORMAT,
409       GST_PAD_PAD_TEMPLATE (pad), caps, caps);
410
411   if (filter)
412     caps = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
413   else
414     caps = gst_caps_ref (caps);
415
416   return caps;
417 }
418
419 static gboolean
420 gst_rtp_base_payload_sink_event_default (GstRTPBasePayload * rtpbasepayload,
421     GstEvent * event)
422 {
423   GstObject *parent = GST_OBJECT_CAST (rtpbasepayload);
424   gboolean res = FALSE;
425
426   switch (GST_EVENT_TYPE (event)) {
427     case GST_EVENT_FLUSH_START:
428       res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
429       break;
430     case GST_EVENT_FLUSH_STOP:
431       res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
432       gst_segment_init (&rtpbasepayload->segment, GST_FORMAT_UNDEFINED);
433       gst_event_replace (&rtpbasepayload->priv->pending_segment, NULL);
434       break;
435     case GST_EVENT_CAPS:
436     {
437       GstRTPBasePayloadClass *rtpbasepayload_class;
438       GstCaps *caps;
439
440       gst_event_parse_caps (event, &caps);
441       GST_DEBUG_OBJECT (rtpbasepayload, "setting caps %" GST_PTR_FORMAT, caps);
442
443       rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
444       if (rtpbasepayload_class->set_caps)
445         res = rtpbasepayload_class->set_caps (rtpbasepayload, caps);
446       else
447         res = TRUE;
448
449       rtpbasepayload->priv->negotiated = res;
450
451       gst_event_unref (event);
452       break;
453     }
454     case GST_EVENT_SEGMENT:
455     {
456       GstSegment *segment;
457
458       segment = &rtpbasepayload->segment;
459       gst_event_copy_segment (event, segment);
460
461       rtpbasepayload->priv->base_offset = GST_BUFFER_OFFSET_NONE;
462
463       GST_DEBUG_OBJECT (rtpbasepayload,
464           "configured SEGMENT %" GST_SEGMENT_FORMAT, segment);
465       if (rtpbasepayload->priv->delay_segment) {
466         gst_event_replace (&rtpbasepayload->priv->pending_segment, event);
467         gst_event_unref (event);
468         res = TRUE;
469       } else {
470         res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
471       }
472       break;
473     }
474     default:
475       res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
476       break;
477   }
478   return res;
479 }
480
481 static gboolean
482 gst_rtp_base_payload_sink_event (GstPad * pad, GstObject * parent,
483     GstEvent * event)
484 {
485   GstRTPBasePayload *rtpbasepayload;
486   GstRTPBasePayloadClass *rtpbasepayload_class;
487   gboolean res = FALSE;
488
489   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
490   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
491
492   if (rtpbasepayload_class->sink_event)
493     res = rtpbasepayload_class->sink_event (rtpbasepayload, event);
494   else
495     gst_event_unref (event);
496
497   return res;
498 }
499
500 static gboolean
501 gst_rtp_base_payload_src_event_default (GstRTPBasePayload * rtpbasepayload,
502     GstEvent * event)
503 {
504   GstObject *parent = GST_OBJECT_CAST (rtpbasepayload);
505   gboolean res = TRUE, forward = TRUE;
506
507   switch (GST_EVENT_TYPE (event)) {
508     case GST_EVENT_CUSTOM_UPSTREAM:
509     {
510       const GstStructure *s = gst_event_get_structure (event);
511
512       if (gst_structure_has_name (s, "GstRTPCollision")) {
513         guint ssrc = 0;
514
515         if (!gst_structure_get_uint (s, "ssrc", &ssrc))
516           ssrc = -1;
517
518         GST_DEBUG_OBJECT (rtpbasepayload, "collided ssrc: %" G_GUINT32_FORMAT,
519             ssrc);
520
521         /* choose another ssrc for our stream */
522         if (ssrc == rtpbasepayload->current_ssrc) {
523           GstCaps *caps;
524           guint suggested_ssrc = 0;
525
526           if (gst_structure_get_uint (s, "suggested-ssrc", &suggested_ssrc))
527             rtpbasepayload->current_ssrc = suggested_ssrc;
528
529           while (ssrc == rtpbasepayload->current_ssrc)
530             rtpbasepayload->current_ssrc = g_random_int ();
531
532           caps = gst_pad_get_current_caps (rtpbasepayload->srcpad);
533           caps = gst_caps_make_writable (caps);
534           gst_caps_set_simple (caps,
535               "ssrc", G_TYPE_UINT, rtpbasepayload->current_ssrc, NULL);
536           res = gst_pad_set_caps (rtpbasepayload->srcpad, caps);
537           gst_caps_unref (caps);
538
539           /* the event was for us */
540           forward = FALSE;
541         }
542       }
543       break;
544     }
545     default:
546       break;
547   }
548
549   if (forward)
550     res = gst_pad_event_default (rtpbasepayload->srcpad, parent, event);
551   else
552     gst_event_unref (event);
553
554   return res;
555 }
556
557 static gboolean
558 gst_rtp_base_payload_src_event (GstPad * pad, GstObject * parent,
559     GstEvent * event)
560 {
561   GstRTPBasePayload *rtpbasepayload;
562   GstRTPBasePayloadClass *rtpbasepayload_class;
563   gboolean res = FALSE;
564
565   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
566   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
567
568   if (rtpbasepayload_class->src_event)
569     res = rtpbasepayload_class->src_event (rtpbasepayload, event);
570   else
571     gst_event_unref (event);
572
573   return res;
574 }
575
576
577 static gboolean
578 gst_rtp_base_payload_query_default (GstRTPBasePayload * rtpbasepayload,
579     GstPad * pad, GstQuery * query)
580 {
581   gboolean res = FALSE;
582
583   switch (GST_QUERY_TYPE (query)) {
584     case GST_QUERY_CAPS:
585     {
586       GstRTPBasePayloadClass *rtpbasepayload_class;
587       GstCaps *filter, *caps;
588
589       gst_query_parse_caps (query, &filter);
590       GST_DEBUG_OBJECT (rtpbasepayload, "getting caps with filter %"
591           GST_PTR_FORMAT, filter);
592
593       rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
594       if (rtpbasepayload_class->get_caps) {
595         caps = rtpbasepayload_class->get_caps (rtpbasepayload, pad, filter);
596         gst_query_set_caps_result (query, caps);
597         gst_caps_unref (caps);
598         res = TRUE;
599       }
600       break;
601     }
602     default:
603       res =
604           gst_pad_query_default (pad, GST_OBJECT_CAST (rtpbasepayload), query);
605       break;
606   }
607   return res;
608 }
609
610 static gboolean
611 gst_rtp_base_payload_query (GstPad * pad, GstObject * parent, GstQuery * query)
612 {
613   GstRTPBasePayload *rtpbasepayload;
614   GstRTPBasePayloadClass *rtpbasepayload_class;
615   gboolean res = FALSE;
616
617   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
618   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
619
620   if (rtpbasepayload_class->query)
621     res = rtpbasepayload_class->query (rtpbasepayload, pad, query);
622
623   return res;
624 }
625
626 static GstFlowReturn
627 gst_rtp_base_payload_chain (GstPad * pad, GstObject * parent,
628     GstBuffer * buffer)
629 {
630   GstRTPBasePayload *rtpbasepayload;
631   GstRTPBasePayloadClass *rtpbasepayload_class;
632   GstFlowReturn ret;
633
634   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
635   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
636
637   if (!rtpbasepayload_class->handle_buffer)
638     goto no_function;
639
640   if (!rtpbasepayload->priv->negotiated)
641     goto not_negotiated;
642
643   ret = rtpbasepayload_class->handle_buffer (rtpbasepayload, buffer);
644
645   return ret;
646
647   /* ERRORS */
648 no_function:
649   {
650     GST_ELEMENT_ERROR (rtpbasepayload, STREAM, NOT_IMPLEMENTED, (NULL),
651         ("subclass did not implement handle_buffer function"));
652     gst_buffer_unref (buffer);
653     return GST_FLOW_ERROR;
654   }
655 not_negotiated:
656   {
657     GST_ELEMENT_ERROR (rtpbasepayload, CORE, NEGOTIATION, (NULL),
658         ("No input format was negotiated, i.e. no caps event was received. "
659             "Perhaps you need a parser or typefind element before the payloader"));
660     gst_buffer_unref (buffer);
661     return GST_FLOW_NOT_NEGOTIATED;
662   }
663 }
664
665 /**
666  * gst_rtp_base_payload_set_options:
667  * @payload: a #GstRTPBasePayload
668  * @media: the media type (typically "audio" or "video")
669  * @dynamic: if the payload type is dynamic
670  * @encoding_name: the encoding name
671  * @clock_rate: the clock rate of the media
672  *
673  * Set the rtp options of the payloader. These options will be set in the caps
674  * of the payloader. Subclasses must call this method before calling
675  * gst_rtp_base_payload_push() or gst_rtp_base_payload_set_outcaps().
676  */
677 void
678 gst_rtp_base_payload_set_options (GstRTPBasePayload * payload,
679     const gchar * media, gboolean dynamic, const gchar * encoding_name,
680     guint32 clock_rate)
681 {
682   g_return_if_fail (payload != NULL);
683   g_return_if_fail (clock_rate != 0);
684
685   g_free (payload->media);
686   payload->media = g_strdup (media);
687   payload->dynamic = dynamic;
688   g_free (payload->encoding_name);
689   payload->encoding_name = g_strdup (encoding_name);
690   payload->clock_rate = clock_rate;
691 }
692
693 static gboolean
694 copy_fixed (GQuark field_id, const GValue * value, GstStructure * dest)
695 {
696   if (gst_value_is_fixed (value)) {
697     gst_structure_id_set_value (dest, field_id, value);
698   }
699   return TRUE;
700 }
701
702 static void
703 update_max_ptime (GstRTPBasePayload * rtpbasepayload)
704 {
705   if (rtpbasepayload->priv->caps_max_ptime != -1 &&
706       rtpbasepayload->priv->prop_max_ptime != -1)
707     rtpbasepayload->max_ptime = MIN (rtpbasepayload->priv->caps_max_ptime,
708         rtpbasepayload->priv->prop_max_ptime);
709   else if (rtpbasepayload->priv->caps_max_ptime != -1)
710     rtpbasepayload->max_ptime = rtpbasepayload->priv->caps_max_ptime;
711   else if (rtpbasepayload->priv->prop_max_ptime != -1)
712     rtpbasepayload->max_ptime = rtpbasepayload->priv->prop_max_ptime;
713   else
714     rtpbasepayload->max_ptime = DEFAULT_MAX_PTIME;
715 }
716
717 /**
718  * gst_rtp_base_payload_set_outcaps:
719  * @payload: a #GstRTPBasePayload
720  * @fieldname: the first field name or %NULL
721  * @...: field values
722  *
723  * Configure the output caps with the optional parameters.
724  *
725  * Variable arguments should be in the form field name, field type
726  * (as a GType), value(s).  The last variable argument should be NULL.
727  *
728  * Returns: %TRUE if the caps could be set.
729  */
730 gboolean
731 gst_rtp_base_payload_set_outcaps (GstRTPBasePayload * payload,
732     const gchar * fieldname, ...)
733 {
734   GstCaps *srccaps, *peercaps;
735   gboolean res;
736
737   /* fill in the defaults, their properties cannot be negotiated. */
738   srccaps = gst_caps_new_simple ("application/x-rtp",
739       "media", G_TYPE_STRING, payload->media,
740       "clock-rate", G_TYPE_INT, payload->clock_rate,
741       "encoding-name", G_TYPE_STRING, payload->encoding_name, NULL);
742
743   GST_DEBUG_OBJECT (payload, "defaults: %" GST_PTR_FORMAT, srccaps);
744
745   if (fieldname) {
746     va_list varargs;
747
748     /* override with custom properties */
749     va_start (varargs, fieldname);
750     gst_caps_set_simple_valist (srccaps, fieldname, varargs);
751     va_end (varargs);
752
753     GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps);
754   }
755
756   payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
757   payload->ptime = 0;
758
759   /* the peer caps can override some of the defaults */
760   peercaps = gst_pad_peer_query_caps (payload->srcpad, srccaps);
761   if (peercaps == NULL) {
762     /* no peer caps, just add the other properties */
763     gst_caps_set_simple (srccaps,
764         "payload", G_TYPE_INT, GST_RTP_BASE_PAYLOAD_PT (payload),
765         "ssrc", G_TYPE_UINT, payload->current_ssrc,
766         "timestamp-offset", G_TYPE_UINT, payload->ts_base,
767         "seqnum-offset", G_TYPE_UINT, payload->seqnum_base, NULL);
768
769     GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps);
770   } else {
771     GstCaps *temp;
772     GstStructure *s, *d;
773     const GValue *value;
774     gint pt;
775     guint max_ptime, ptime;
776
777     /* peer provides caps we can use to fixate. They are already intersected
778      * with our srccaps, just make them writable */
779     temp = gst_caps_make_writable (peercaps);
780     gst_caps_unref (srccaps);
781
782     if (gst_caps_is_empty (temp)) {
783       gst_caps_unref (temp);
784       return FALSE;
785     }
786
787     /* now fixate, start by taking the first caps */
788     temp = gst_caps_truncate (temp);
789
790     /* get first structure */
791     s = gst_caps_get_structure (temp, 0);
792
793     if (gst_structure_get_uint (s, "maxptime", &max_ptime))
794       payload->priv->caps_max_ptime = max_ptime * GST_MSECOND;
795
796     if (gst_structure_get_uint (s, "ptime", &ptime))
797       payload->ptime = ptime * GST_MSECOND;
798
799     if (gst_structure_get_int (s, "payload", &pt)) {
800       /* use peer pt */
801       GST_RTP_BASE_PAYLOAD_PT (payload) = pt;
802       GST_LOG_OBJECT (payload, "using peer pt %d", pt);
803     } else {
804       if (gst_structure_has_field (s, "payload")) {
805         /* can only fixate if there is a field */
806         gst_structure_fixate_field_nearest_int (s, "payload",
807             GST_RTP_BASE_PAYLOAD_PT (payload));
808         gst_structure_get_int (s, "payload", &pt);
809         GST_LOG_OBJECT (payload, "using peer pt %d", pt);
810       } else {
811         /* no pt field, use the internal pt */
812         pt = GST_RTP_BASE_PAYLOAD_PT (payload);
813         gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
814         GST_LOG_OBJECT (payload, "using internal pt %d", pt);
815       }
816     }
817
818     if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) {
819       value = gst_structure_get_value (s, "ssrc");
820       payload->current_ssrc = g_value_get_uint (value);
821       GST_LOG_OBJECT (payload, "using peer ssrc %08x", payload->current_ssrc);
822     } else {
823       /* FIXME, fixate_nearest_uint would be even better */
824       gst_structure_set (s, "ssrc", G_TYPE_UINT, payload->current_ssrc, NULL);
825       GST_LOG_OBJECT (payload, "using internal ssrc %08x",
826           payload->current_ssrc);
827     }
828
829     if (gst_structure_has_field_typed (s, "timestamp-offset", G_TYPE_UINT)) {
830       value = gst_structure_get_value (s, "timestamp-offset");
831       payload->ts_base = g_value_get_uint (value);
832       GST_LOG_OBJECT (payload, "using peer timestamp-offset %u",
833           payload->ts_base);
834     } else {
835       /* FIXME, fixate_nearest_uint would be even better */
836       gst_structure_set (s, "timestamp-offset", G_TYPE_UINT, payload->ts_base,
837           NULL);
838       GST_LOG_OBJECT (payload, "using internal timestamp-offset %u",
839           payload->ts_base);
840     }
841     if (gst_structure_has_field_typed (s, "seqnum-offset", G_TYPE_UINT)) {
842       value = gst_structure_get_value (s, "seqnum-offset");
843       payload->seqnum_base = g_value_get_uint (value);
844       GST_LOG_OBJECT (payload, "using peer seqnum-offset %u",
845           payload->seqnum_base);
846       payload->priv->next_seqnum = payload->seqnum_base;
847       payload->seqnum = payload->seqnum_base;
848       payload->priv->seqnum_offset_random = FALSE;
849     } else {
850       /* FIXME, fixate_nearest_uint would be even better */
851       gst_structure_set (s, "seqnum-offset", G_TYPE_UINT, payload->seqnum_base,
852           NULL);
853       GST_LOG_OBJECT (payload, "using internal seqnum-offset %u",
854           payload->seqnum_base);
855     }
856
857     /* make the target caps by copying over all the fixed caps, removing the
858      * unfixed caps. */
859     srccaps = gst_caps_new_empty_simple (gst_structure_get_name (s));
860     d = gst_caps_get_structure (srccaps, 0);
861
862     gst_structure_foreach (s, (GstStructureForeachFunc) copy_fixed, d);
863
864     gst_caps_unref (temp);
865
866     GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
867   }
868
869   update_max_ptime (payload);
870
871   res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
872   gst_caps_unref (srccaps);
873
874   return res;
875 }
876
877 /**
878  * gst_rtp_base_payload_is_filled:
879  * @payload: a #GstRTPBasePayload
880  * @size: the size of the packet
881  * @duration: the duration of the packet
882  *
883  * Check if the packet with @size and @duration would exceed the configured
884  * maximum size.
885  *
886  * Returns: %TRUE if the packet of @size and @duration would exceed the
887  * configured MTU or max_ptime.
888  */
889 gboolean
890 gst_rtp_base_payload_is_filled (GstRTPBasePayload * payload,
891     guint size, GstClockTime duration)
892 {
893   if (size > payload->mtu)
894     return TRUE;
895
896   if (payload->max_ptime != -1 && duration >= payload->max_ptime)
897     return TRUE;
898
899   return FALSE;
900 }
901
902 typedef struct
903 {
904   GstRTPBasePayload *payload;
905   guint32 ssrc;
906   guint16 seqnum;
907   guint8 pt;
908   GstClockTime dts;
909   GstClockTime pts;
910   guint64 offset;
911   guint32 rtptime;
912 } HeaderData;
913
914 static gboolean
915 find_timestamp (GstBuffer ** buffer, guint idx, gpointer user_data)
916 {
917   HeaderData *data = user_data;
918   data->dts = GST_BUFFER_DTS (*buffer);
919   data->pts = GST_BUFFER_PTS (*buffer);
920   data->offset = GST_BUFFER_OFFSET (*buffer);
921
922   /* stop when we find a timestamp. We take whatever offset is associated with
923    * the timestamp (if any) to do perfect timestamps when we need to. */
924   if (data->pts != -1)
925     return FALSE;
926   else
927     return TRUE;
928 }
929
930 static gboolean
931 set_headers (GstBuffer ** buffer, guint idx, gpointer user_data)
932 {
933   HeaderData *data = user_data;
934   GstRTPBuffer rtp = { NULL, };
935
936   if (!gst_rtp_buffer_map (*buffer, GST_MAP_WRITE, &rtp))
937     goto map_failed;
938
939   gst_rtp_buffer_set_ssrc (&rtp, data->ssrc);
940   gst_rtp_buffer_set_payload_type (&rtp, data->pt);
941   gst_rtp_buffer_set_seq (&rtp, data->seqnum);
942   gst_rtp_buffer_set_timestamp (&rtp, data->rtptime);
943   gst_rtp_buffer_unmap (&rtp);
944
945   /* increment the seqnum for each buffer */
946   data->seqnum++;
947
948   return TRUE;
949   /* ERRORS */
950 map_failed:
951   {
952     GST_ERROR ("failed to map buffer %p", *buffer);
953     return FALSE;
954   }
955 }
956
957 /* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer
958  * before the buffer is pushed. */
959 static GstFlowReturn
960 gst_rtp_base_payload_prepare_push (GstRTPBasePayload * payload,
961     gpointer obj, gboolean is_list)
962 {
963   GstRTPBasePayloadPrivate *priv;
964   HeaderData data;
965
966   if (payload->clock_rate == 0)
967     goto no_rate;
968
969   priv = payload->priv;
970
971   /* update first, so that the property is set to the last
972    * seqnum pushed */
973   payload->seqnum = priv->next_seqnum;
974
975   /* fill in the fields we want to set on all headers */
976   data.payload = payload;
977   data.seqnum = payload->seqnum;
978   data.ssrc = payload->current_ssrc;
979   data.pt = payload->pt;
980
981   /* find the first buffer with a timestamp */
982   if (is_list) {
983     data.dts = -1;
984     data.pts = -1;
985     data.offset = GST_BUFFER_OFFSET_NONE;
986     gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), find_timestamp, &data);
987   } else {
988     data.dts = GST_BUFFER_DTS (GST_BUFFER_CAST (obj));
989     data.pts = GST_BUFFER_PTS (GST_BUFFER_CAST (obj));
990     data.offset = GST_BUFFER_OFFSET (GST_BUFFER_CAST (obj));
991   }
992
993   /* convert to RTP time */
994   if (priv->perfect_rtptime && data.offset != GST_BUFFER_OFFSET_NONE &&
995       priv->base_offset != GST_BUFFER_OFFSET_NONE) {
996     /* generate perfect RTP time by adding together the base timestamp, the
997      * running time of the first buffer and difference between the offset of the
998      * first buffer and the offset of the current buffer. */
999     guint64 offset = data.offset - priv->base_offset;
1000     data.rtptime = payload->ts_base + priv->base_rtime_hz + offset;
1001
1002     GST_LOG_OBJECT (payload,
1003         "Using offset %" G_GUINT64_FORMAT " for RTP timestamp", data.offset);
1004
1005     /* store buffer's running time */
1006     GST_LOG_OBJECT (payload,
1007         "setting running-time to %" G_GUINT64_FORMAT,
1008         data.offset - priv->base_offset);
1009     priv->running_time = priv->base_rtime + data.offset - priv->base_offset;
1010   } else if (GST_CLOCK_TIME_IS_VALID (data.pts)) {
1011     guint64 rtime_ns;
1012     guint64 rtime_hz;
1013
1014     /* no offset, use the gstreamer pts */
1015     rtime_ns = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
1016         data.pts);
1017
1018     if (!GST_CLOCK_TIME_IS_VALID (rtime_ns)) {
1019       GST_LOG_OBJECT (payload, "Clipped pts, using base RTP timestamp");
1020       rtime_hz = 0;
1021     } else {
1022       GST_LOG_OBJECT (payload,
1023           "Using running_time %" GST_TIME_FORMAT " for RTP timestamp",
1024           GST_TIME_ARGS (rtime_ns));
1025       rtime_hz =
1026           gst_util_uint64_scale_int (rtime_ns, payload->clock_rate, GST_SECOND);
1027       priv->base_offset = data.offset;
1028       priv->base_rtime_hz = rtime_hz;
1029     }
1030
1031     /* add running_time in clock-rate units to the base timestamp */
1032     data.rtptime = payload->ts_base + rtime_hz;
1033
1034     /* store buffer's running time */
1035     if (priv->perfect_rtptime) {
1036       GST_LOG_OBJECT (payload,
1037           "setting running-time to %" G_GUINT64_FORMAT, rtime_hz);
1038       priv->running_time = rtime_hz;
1039     } else {
1040       GST_LOG_OBJECT (payload,
1041           "setting running-time to %" GST_TIME_FORMAT,
1042           GST_TIME_ARGS (rtime_ns));
1043       priv->running_time = rtime_ns;
1044     }
1045   } else {
1046     GST_LOG_OBJECT (payload,
1047         "Using previous RTP timestamp %" G_GUINT32_FORMAT, payload->timestamp);
1048     /* no timestamp to convert, take previous timestamp */
1049     data.rtptime = payload->timestamp;
1050   }
1051
1052   /* set ssrc, payload type, seq number, caps and rtptime */
1053   if (is_list) {
1054     gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), set_headers, &data);
1055   } else {
1056     GstBuffer *buf = GST_BUFFER_CAST (obj);
1057     set_headers (&buf, 0, &data);
1058   }
1059
1060   priv->next_seqnum = data.seqnum;
1061   payload->timestamp = data.rtptime;
1062
1063   GST_LOG_OBJECT (payload, "Preparing to push packet with size %"
1064       G_GSIZE_FORMAT ", seq=%d, rtptime=%u, pts %" GST_TIME_FORMAT,
1065       (is_list) ? -1 : gst_buffer_get_size (GST_BUFFER (obj)),
1066       payload->seqnum, data.rtptime, GST_TIME_ARGS (data.pts));
1067
1068   if (g_atomic_int_compare_and_exchange (&payload->
1069           priv->notified_first_timestamp, 1, 0)) {
1070     g_object_notify (G_OBJECT (payload), "timestamp");
1071     g_object_notify (G_OBJECT (payload), "seqnum");
1072   }
1073
1074   return GST_FLOW_OK;
1075
1076   /* ERRORS */
1077 no_rate:
1078   {
1079     GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
1080         ("subclass did not specify clock-rate"));
1081     return GST_FLOW_ERROR;
1082   }
1083 }
1084
1085 /**
1086  * gst_rtp_base_payload_push_list:
1087  * @payload: a #GstRTPBasePayload
1088  * @list: a #GstBufferList
1089  *
1090  * Push @list to the peer element of the payloader. The SSRC, payload type,
1091  * seqnum and timestamp of the RTP buffer will be updated first.
1092  *
1093  * This function takes ownership of @list.
1094  *
1095  * Returns: a #GstFlowReturn.
1096  */
1097 GstFlowReturn
1098 gst_rtp_base_payload_push_list (GstRTPBasePayload * payload,
1099     GstBufferList * list)
1100 {
1101   GstFlowReturn res;
1102
1103   res = gst_rtp_base_payload_prepare_push (payload, list, TRUE);
1104
1105   if (G_LIKELY (res == GST_FLOW_OK)) {
1106     if (G_UNLIKELY (payload->priv->pending_segment)) {
1107       gst_pad_push_event (payload->srcpad, payload->priv->pending_segment);
1108       payload->priv->pending_segment = FALSE;
1109       payload->priv->delay_segment = FALSE;
1110     }
1111     res = gst_pad_push_list (payload->srcpad, list);
1112   } else {
1113     gst_buffer_list_unref (list);
1114   }
1115
1116   return res;
1117 }
1118
1119 /**
1120  * gst_rtp_base_payload_push:
1121  * @payload: a #GstRTPBasePayload
1122  * @buffer: a #GstBuffer
1123  *
1124  * Push @buffer to the peer element of the payloader. The SSRC, payload type,
1125  * seqnum and timestamp of the RTP buffer will be updated first.
1126  *
1127  * This function takes ownership of @buffer.
1128  *
1129  * Returns: a #GstFlowReturn.
1130  */
1131 GstFlowReturn
1132 gst_rtp_base_payload_push (GstRTPBasePayload * payload, GstBuffer * buffer)
1133 {
1134   GstFlowReturn res;
1135
1136   res = gst_rtp_base_payload_prepare_push (payload, buffer, FALSE);
1137
1138   if (G_LIKELY (res == GST_FLOW_OK)) {
1139     if (G_UNLIKELY (payload->priv->pending_segment)) {
1140       gst_pad_push_event (payload->srcpad, payload->priv->pending_segment);
1141       payload->priv->pending_segment = FALSE;
1142       payload->priv->delay_segment = FALSE;
1143     }
1144     res = gst_pad_push (payload->srcpad, buffer);
1145   } else {
1146     gst_buffer_unref (buffer);
1147   }
1148
1149   return res;
1150 }
1151
1152 static GstStructure *
1153 gst_rtp_base_payload_create_stats (GstRTPBasePayload * rtpbasepayload)
1154 {
1155   GstRTPBasePayloadPrivate *priv;
1156   GstStructure *s;
1157
1158   priv = rtpbasepayload->priv;
1159
1160   s = gst_structure_new ("application/x-rtp-payload-stats",
1161       "clock-rate", G_TYPE_UINT, (guint) rtpbasepayload->clock_rate,
1162       "running-time", G_TYPE_UINT64, priv->running_time,
1163       "seqnum", G_TYPE_UINT, (guint) rtpbasepayload->seqnum,
1164       "timestamp", G_TYPE_UINT, (guint) rtpbasepayload->timestamp,
1165       "ssrc", G_TYPE_UINT, rtpbasepayload->current_ssrc,
1166       "pt", G_TYPE_UINT, rtpbasepayload->pt,
1167       "seqnum-offset", G_TYPE_UINT, (guint) rtpbasepayload->seqnum_base,
1168       "timestamp-offset", G_TYPE_UINT, (guint) rtpbasepayload->ts_base, NULL);
1169
1170   return s;
1171 }
1172
1173 static void
1174 gst_rtp_base_payload_set_property (GObject * object, guint prop_id,
1175     const GValue * value, GParamSpec * pspec)
1176 {
1177   GstRTPBasePayload *rtpbasepayload;
1178   GstRTPBasePayloadPrivate *priv;
1179   gint64 val;
1180
1181   rtpbasepayload = GST_RTP_BASE_PAYLOAD (object);
1182   priv = rtpbasepayload->priv;
1183
1184   switch (prop_id) {
1185     case PROP_MTU:
1186       rtpbasepayload->mtu = g_value_get_uint (value);
1187       break;
1188     case PROP_PT:
1189       rtpbasepayload->pt = g_value_get_uint (value);
1190       break;
1191     case PROP_SSRC:
1192       val = g_value_get_uint (value);
1193       rtpbasepayload->ssrc = val;
1194       priv->ssrc_random = FALSE;
1195       break;
1196     case PROP_TIMESTAMP_OFFSET:
1197       val = g_value_get_uint (value);
1198       rtpbasepayload->ts_offset = val;
1199       priv->ts_offset_random = FALSE;
1200       break;
1201     case PROP_SEQNUM_OFFSET:
1202       val = g_value_get_int (value);
1203       rtpbasepayload->seqnum_offset = val;
1204       priv->seqnum_offset_random = (val == -1);
1205       GST_DEBUG_OBJECT (rtpbasepayload, "seqnum offset 0x%04x, random %d",
1206           rtpbasepayload->seqnum_offset, priv->seqnum_offset_random);
1207       break;
1208     case PROP_MAX_PTIME:
1209       rtpbasepayload->priv->prop_max_ptime = g_value_get_int64 (value);
1210       update_max_ptime (rtpbasepayload);
1211       break;
1212     case PROP_MIN_PTIME:
1213       rtpbasepayload->min_ptime = g_value_get_int64 (value);
1214       break;
1215     case PROP_PERFECT_RTPTIME:
1216       priv->perfect_rtptime = g_value_get_boolean (value);
1217       break;
1218     case PROP_PTIME_MULTIPLE:
1219       rtpbasepayload->ptime_multiple = g_value_get_int64 (value);
1220       break;
1221     default:
1222       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1223       break;
1224   }
1225 }
1226
1227 static void
1228 gst_rtp_base_payload_get_property (GObject * object, guint prop_id,
1229     GValue * value, GParamSpec * pspec)
1230 {
1231   GstRTPBasePayload *rtpbasepayload;
1232   GstRTPBasePayloadPrivate *priv;
1233
1234   rtpbasepayload = GST_RTP_BASE_PAYLOAD (object);
1235   priv = rtpbasepayload->priv;
1236
1237   switch (prop_id) {
1238     case PROP_MTU:
1239       g_value_set_uint (value, rtpbasepayload->mtu);
1240       break;
1241     case PROP_PT:
1242       g_value_set_uint (value, rtpbasepayload->pt);
1243       break;
1244     case PROP_SSRC:
1245       if (priv->ssrc_random)
1246         g_value_set_uint (value, -1);
1247       else
1248         g_value_set_uint (value, rtpbasepayload->ssrc);
1249       break;
1250     case PROP_TIMESTAMP_OFFSET:
1251       if (priv->ts_offset_random)
1252         g_value_set_uint (value, -1);
1253       else
1254         g_value_set_uint (value, (guint32) rtpbasepayload->ts_offset);
1255       break;
1256     case PROP_SEQNUM_OFFSET:
1257       if (priv->seqnum_offset_random)
1258         g_value_set_int (value, -1);
1259       else
1260         g_value_set_int (value, (guint16) rtpbasepayload->seqnum_offset);
1261       break;
1262     case PROP_MAX_PTIME:
1263       g_value_set_int64 (value, rtpbasepayload->max_ptime);
1264       break;
1265     case PROP_MIN_PTIME:
1266       g_value_set_int64 (value, rtpbasepayload->min_ptime);
1267       break;
1268     case PROP_TIMESTAMP:
1269       g_value_set_uint (value, rtpbasepayload->timestamp);
1270       break;
1271     case PROP_SEQNUM:
1272       g_value_set_uint (value, rtpbasepayload->seqnum);
1273       break;
1274     case PROP_PERFECT_RTPTIME:
1275       g_value_set_boolean (value, priv->perfect_rtptime);
1276       break;
1277     case PROP_PTIME_MULTIPLE:
1278       g_value_set_int64 (value, rtpbasepayload->ptime_multiple);
1279       break;
1280     case PROP_STATS:
1281       g_value_take_boxed (value,
1282           gst_rtp_base_payload_create_stats (rtpbasepayload));
1283       break;
1284     default:
1285       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1286       break;
1287   }
1288 }
1289
1290 static GstStateChangeReturn
1291 gst_rtp_base_payload_change_state (GstElement * element,
1292     GstStateChange transition)
1293 {
1294   GstRTPBasePayload *rtpbasepayload;
1295   GstRTPBasePayloadPrivate *priv;
1296   GstStateChangeReturn ret;
1297
1298   rtpbasepayload = GST_RTP_BASE_PAYLOAD (element);
1299   priv = rtpbasepayload->priv;
1300
1301   switch (transition) {
1302     case GST_STATE_CHANGE_NULL_TO_READY:
1303       break;
1304     case GST_STATE_CHANGE_READY_TO_PAUSED:
1305       gst_segment_init (&rtpbasepayload->segment, GST_FORMAT_UNDEFINED);
1306       rtpbasepayload->priv->delay_segment = TRUE;
1307       gst_event_replace (&rtpbasepayload->priv->pending_segment, NULL);
1308
1309       if (priv->seqnum_offset_random)
1310         rtpbasepayload->seqnum_base = g_random_int_range (0, G_MAXINT16);
1311       else
1312         rtpbasepayload->seqnum_base = rtpbasepayload->seqnum_offset;
1313       priv->next_seqnum = rtpbasepayload->seqnum_base;
1314       rtpbasepayload->seqnum = rtpbasepayload->seqnum_base;
1315
1316       if (priv->ssrc_random)
1317         rtpbasepayload->current_ssrc = g_random_int ();
1318       else
1319         rtpbasepayload->current_ssrc = rtpbasepayload->ssrc;
1320
1321       if (priv->ts_offset_random)
1322         rtpbasepayload->ts_base = g_random_int ();
1323       else
1324         rtpbasepayload->ts_base = rtpbasepayload->ts_offset;
1325       rtpbasepayload->timestamp = rtpbasepayload->ts_base;
1326       priv->running_time = DEFAULT_RUNNING_TIME;
1327       g_atomic_int_set (&rtpbasepayload->priv->notified_first_timestamp, 1);
1328       priv->base_offset = GST_BUFFER_OFFSET_NONE;
1329       priv->negotiated = FALSE;
1330       break;
1331     default:
1332       break;
1333   }
1334
1335   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1336
1337   switch (transition) {
1338     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1339       g_atomic_int_set (&rtpbasepayload->priv->notified_first_timestamp, 1);
1340       break;
1341     case GST_STATE_CHANGE_PAUSED_TO_READY:
1342       gst_event_replace (&rtpbasepayload->priv->pending_segment, NULL);
1343       break;
1344     default:
1345       break;
1346   }
1347   return ret;
1348 }