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  * @title: GstRTPBasePayload
18  * @short_description: Base class for RTP payloader
19  *
20  * Provides a base class for RTP payloaders
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <string.h>
28 
29 #include <gst/rtp/gstrtpbuffer.h>
30 
31 #include "gstrtpbasepayload.h"
32 #include "gstrtpmeta.h"
33 
34 GST_DEBUG_CATEGORY_STATIC (rtpbasepayload_debug);
35 #define GST_CAT_DEFAULT (rtpbasepayload_debug)
36 
37 struct _GstRTPBasePayloadPrivate
38 {
39   gboolean ts_offset_random;
40   gboolean seqnum_offset_random;
41   gboolean ssrc_random;
42   guint16 next_seqnum;
43   gboolean perfect_rtptime;
44   gint notified_first_timestamp;
45 
46   gboolean pt_set;
47 
48   gboolean source_info;
49   GstBuffer *input_meta_buffer;
50 
51   guint64 base_offset;
52   gint64 base_rtime;
53   guint64 base_rtime_hz;
54   guint64 running_time;
55 
56   gint64 prop_max_ptime;
57   gint64 caps_max_ptime;
58 
59   gboolean onvif_no_rate_control;
60 
61   gboolean negotiated;
62 
63   gboolean delay_segment;
64   GstEvent *pending_segment;
65 
66   GstCaps *subclass_srccaps;
67   GstCaps *sinkcaps;
68 };
69 
70 /* RTPBasePayload signals and args */
71 enum
72 {
73   /* FILL ME */
74   LAST_SIGNAL
75 };
76 
77 /* FIXME 0.11, a better default is the Ethernet MTU of
78  * 1500 - sizeof(headers) as pointed out by marcelm in IRC:
79  * So an Ethernet MTU of 1500, minus 60 for the max IP, minus 8 for UDP, gives
80  * 1432 bytes or so.  And that should be adjusted downward further for other
81  * encapsulations like PPPoE, so 1400 at most.
82  */
83 #define DEFAULT_MTU                     1400
84 #define DEFAULT_PT                      96
85 #define DEFAULT_SSRC                    -1
86 #define DEFAULT_TIMESTAMP_OFFSET        -1
87 #define DEFAULT_SEQNUM_OFFSET           -1
88 #define DEFAULT_MAX_PTIME               -1
89 #define DEFAULT_MIN_PTIME               0
90 #define DEFAULT_PERFECT_RTPTIME         TRUE
91 #define DEFAULT_PTIME_MULTIPLE          0
92 #define DEFAULT_RUNNING_TIME            GST_CLOCK_TIME_NONE
93 #define DEFAULT_SOURCE_INFO             FALSE
94 #define DEFAULT_ONVIF_NO_RATE_CONTROL   FALSE
95 
96 enum
97 {
98   PROP_0,
99   PROP_MTU,
100   PROP_PT,
101   PROP_SSRC,
102   PROP_TIMESTAMP_OFFSET,
103   PROP_SEQNUM_OFFSET,
104   PROP_MAX_PTIME,
105   PROP_MIN_PTIME,
106   PROP_TIMESTAMP,
107   PROP_SEQNUM,
108   PROP_PERFECT_RTPTIME,
109   PROP_PTIME_MULTIPLE,
110   PROP_STATS,
111   PROP_SOURCE_INFO,
112   PROP_ONVIF_NO_RATE_CONTROL,
113   PROP_LAST
114 };
115 
116 static void gst_rtp_base_payload_class_init (GstRTPBasePayloadClass * klass);
117 static void gst_rtp_base_payload_init (GstRTPBasePayload * rtpbasepayload,
118     gpointer g_class);
119 static void gst_rtp_base_payload_finalize (GObject * object);
120 
121 static GstCaps *gst_rtp_base_payload_getcaps_default (GstRTPBasePayload *
122     rtpbasepayload, GstPad * pad, GstCaps * filter);
123 
124 static gboolean gst_rtp_base_payload_sink_event_default (GstRTPBasePayload *
125     rtpbasepayload, GstEvent * event);
126 static gboolean gst_rtp_base_payload_sink_event (GstPad * pad,
127     GstObject * parent, GstEvent * event);
128 static gboolean gst_rtp_base_payload_src_event_default (GstRTPBasePayload *
129     rtpbasepayload, GstEvent * event);
130 static gboolean gst_rtp_base_payload_src_event (GstPad * pad,
131     GstObject * parent, GstEvent * event);
132 static gboolean gst_rtp_base_payload_query_default (GstRTPBasePayload *
133     rtpbasepayload, GstPad * pad, GstQuery * query);
134 static gboolean gst_rtp_base_payload_query (GstPad * pad, GstObject * parent,
135     GstQuery * query);
136 static GstFlowReturn gst_rtp_base_payload_chain (GstPad * pad,
137     GstObject * parent, GstBuffer * buffer);
138 
139 static void gst_rtp_base_payload_set_property (GObject * object, guint prop_id,
140     const GValue * value, GParamSpec * pspec);
141 static void gst_rtp_base_payload_get_property (GObject * object, guint prop_id,
142     GValue * value, GParamSpec * pspec);
143 
144 static GstStateChangeReturn gst_rtp_base_payload_change_state (GstElement *
145     element, GstStateChange transition);
146 
147 static gboolean gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload);
148 
149 
150 static GstElementClass *parent_class = NULL;
151 static gint private_offset = 0;
152 
153 GType
gst_rtp_base_payload_get_type(void)154 gst_rtp_base_payload_get_type (void)
155 {
156   static GType rtpbasepayload_type = 0;
157 
158   if (g_once_init_enter ((gsize *) & rtpbasepayload_type)) {
159     static const GTypeInfo rtpbasepayload_info = {
160       sizeof (GstRTPBasePayloadClass),
161       NULL,
162       NULL,
163       (GClassInitFunc) gst_rtp_base_payload_class_init,
164       NULL,
165       NULL,
166       sizeof (GstRTPBasePayload),
167       0,
168       (GInstanceInitFunc) gst_rtp_base_payload_init,
169     };
170     GType _type;
171 
172     _type = g_type_register_static (GST_TYPE_ELEMENT, "GstRTPBasePayload",
173         &rtpbasepayload_info, G_TYPE_FLAG_ABSTRACT);
174 
175     private_offset =
176         g_type_add_instance_private (_type, sizeof (GstRTPBasePayloadPrivate));
177 
178     g_once_init_leave ((gsize *) & rtpbasepayload_type, _type);
179   }
180   return rtpbasepayload_type;
181 }
182 
183 static inline GstRTPBasePayloadPrivate *
gst_rtp_base_payload_get_instance_private(GstRTPBasePayload * self)184 gst_rtp_base_payload_get_instance_private (GstRTPBasePayload * self)
185 {
186   return (G_STRUCT_MEMBER_P (self, private_offset));
187 }
188 
189 static void
gst_rtp_base_payload_class_init(GstRTPBasePayloadClass * klass)190 gst_rtp_base_payload_class_init (GstRTPBasePayloadClass * klass)
191 {
192   GObjectClass *gobject_class;
193   GstElementClass *gstelement_class;
194 
195   gobject_class = (GObjectClass *) klass;
196   gstelement_class = (GstElementClass *) klass;
197 
198   if (private_offset != 0)
199     g_type_class_adjust_private_offset (klass, &private_offset);
200 
201   parent_class = g_type_class_peek_parent (klass);
202 
203   gobject_class->finalize = gst_rtp_base_payload_finalize;
204 
205   gobject_class->set_property = gst_rtp_base_payload_set_property;
206   gobject_class->get_property = gst_rtp_base_payload_get_property;
207 
208   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU,
209       g_param_spec_uint ("mtu", "MTU",
210           "Maximum size of one packet",
211           28, G_MAXUINT, DEFAULT_MTU,
212           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
213   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
214       g_param_spec_uint ("pt", "payload type",
215           "The payload type of the packets", 0, 0x7f, DEFAULT_PT,
216           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
217   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
218       g_param_spec_uint ("ssrc", "SSRC",
219           "The SSRC of the packets (default == random)", 0, G_MAXUINT32,
220           DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
221   g_object_class_install_property (G_OBJECT_CLASS (klass),
222       PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset",
223           "Timestamp Offset",
224           "Offset to add to all outgoing timestamps (default = random)", 0,
225           G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET,
226           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
227   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
228       g_param_spec_int ("seqnum-offset", "Sequence number Offset",
229           "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16,
230           DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
231   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME,
232       g_param_spec_int64 ("max-ptime", "Max packet time",
233           "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)",
234           -1, G_MAXINT64, DEFAULT_MAX_PTIME,
235           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
236   /**
237    * GstRTPBasePayload:min-ptime:
238    *
239    * Minimum duration of the packet data in ns (can't go above MTU)
240    **/
241   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME,
242       g_param_spec_int64 ("min-ptime", "Min packet time",
243           "Minimum duration of the packet data in ns (can't go above MTU)",
244           0, G_MAXINT64, DEFAULT_MIN_PTIME,
245           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
246 
247   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
248       g_param_spec_uint ("timestamp", "Timestamp",
249           "The RTP timestamp of the last processed packet",
250           0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
251   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
252       g_param_spec_uint ("seqnum", "Sequence number",
253           "The RTP sequence number of the last processed packet",
254           0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
255 
256   /**
257    * GstRTPBasePayload:perfect-rtptime:
258    *
259    * Try to use the offset fields to generate perfect RTP timestamps. When this
260    * option is disabled, RTP timestamps are generated from GST_BUFFER_PTS of
261    * each payloaded buffer. The PTSes of buffers may not necessarily increment
262    * with the amount of data in each input buffer, consider e.g. the case where
263    * the buffer arrives from a network which means that the PTS is unrelated to
264    * the amount of data. Because the RTP timestamps are generated from
265    * GST_BUFFER_PTS this can result in RTP timestamps that also don't increment
266    * with the amount of data in the payloaded packet. To circumvent this it is
267    * possible to set the perfect rtptime option enabled. When this option is
268    * enabled the payloader will increment the RTP timestamps based on
269    * GST_BUFFER_OFFSET which relates to the amount of data in each packet
270    * rather than the GST_BUFFER_PTS of each buffer and therefore the RTP
271    * timestamps will more closely correlate with the amount of data in each
272    * buffer. Currently GstRTPBasePayload is limited to handling perfect RTP
273    * timestamps for audio streams.
274    */
275   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PERFECT_RTPTIME,
276       g_param_spec_boolean ("perfect-rtptime", "Perfect RTP Time",
277           "Generate perfect RTP timestamps when possible",
278           DEFAULT_PERFECT_RTPTIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
279   /**
280    * GstRTPBasePayload:ptime-multiple:
281    *
282    * Force buffers to be multiples of this duration in ns (0 disables)
283    **/
284   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PTIME_MULTIPLE,
285       g_param_spec_int64 ("ptime-multiple", "Packet time multiple",
286           "Force buffers to be multiples of this duration in ns (0 disables)",
287           0, G_MAXINT64, DEFAULT_PTIME_MULTIPLE,
288           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
289 
290   /**
291    * GstRTPBasePayload:stats:
292    *
293    * Various payloader statistics retrieved atomically (and are therefore
294    * synchroized with each other), these can be used e.g. to generate an
295    * RTP-Info header. This property return a GstStructure named
296    * application/x-rtp-payload-stats containing the following fields relating to
297    * the last processed buffer and current state of the stream being payloaded:
298    *
299    *   * `clock-rate` :#G_TYPE_UINT, clock-rate of the stream
300    *   * `running-time` :#G_TYPE_UINT64, running time
301    *   * `seqnum` :#G_TYPE_UINT, sequence number, same as #GstRTPBasePayload:seqnum
302    *   * `timestamp` :#G_TYPE_UINT, RTP timestamp, same as #GstRTPBasePayload:timestamp
303    *   * `ssrc` :#G_TYPE_UINT, The SSRC in use
304    *   * `pt` :#G_TYPE_UINT, The Payload type in use, same as #GstRTPBasePayload:pt
305    *   * `seqnum-offset` :#G_TYPE_UINT, The current offset added to the seqnum
306    *   * `timestamp-offset` :#G_TYPE_UINT, The current offset added to the timestamp
307    **/
308   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATS,
309       g_param_spec_boxed ("stats", "Statistics", "Various statistics",
310           GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
311 
312   /**
313    * GstRTPBasePayload:source-info:
314    *
315    * Enable writing the CSRC field in allocated RTP header based on RTP source
316    * information found in the input buffer's #GstRTPSourceMeta.
317    *
318    * Since: 1.16
319    **/
320   g_object_class_install_property (gobject_class, PROP_SOURCE_INFO,
321       g_param_spec_boolean ("source-info", "RTP source information",
322           "Write CSRC based on buffer meta RTP source information",
323           DEFAULT_SOURCE_INFO, G_PARAM_READWRITE));
324 
325   /**
326    * GstRTPBasePayload:onvif-no-rate-control:
327    *
328    * Make the payloader timestamp packets according to the Rate-Control=no
329    * behaviour specified in the ONVIF replay spec.
330    *
331    * Since: 1.16
332    */
333   g_object_class_install_property (G_OBJECT_CLASS (klass),
334       PROP_ONVIF_NO_RATE_CONTROL, g_param_spec_boolean ("onvif-no-rate-control",
335           "ONVIF no rate control",
336           "Enable ONVIF Rate-Control=no timestamping mode",
337           DEFAULT_ONVIF_NO_RATE_CONTROL,
338           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
339 
340   gstelement_class->change_state = gst_rtp_base_payload_change_state;
341 
342   klass->get_caps = gst_rtp_base_payload_getcaps_default;
343   klass->sink_event = gst_rtp_base_payload_sink_event_default;
344   klass->src_event = gst_rtp_base_payload_src_event_default;
345   klass->query = gst_rtp_base_payload_query_default;
346 
347   GST_DEBUG_CATEGORY_INIT (rtpbasepayload_debug, "rtpbasepayload", 0,
348       "Base class for RTP Payloaders");
349 }
350 
351 static void
gst_rtp_base_payload_init(GstRTPBasePayload * rtpbasepayload,gpointer g_class)352 gst_rtp_base_payload_init (GstRTPBasePayload * rtpbasepayload, gpointer g_class)
353 {
354   GstPadTemplate *templ;
355   GstRTPBasePayloadPrivate *priv;
356 
357   rtpbasepayload->priv = priv =
358       gst_rtp_base_payload_get_instance_private (rtpbasepayload);
359 
360   templ =
361       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
362   g_return_if_fail (templ != NULL);
363 
364   rtpbasepayload->srcpad = gst_pad_new_from_template (templ, "src");
365   gst_pad_set_event_function (rtpbasepayload->srcpad,
366       gst_rtp_base_payload_src_event);
367   gst_element_add_pad (GST_ELEMENT (rtpbasepayload), rtpbasepayload->srcpad);
368 
369   templ =
370       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink");
371   g_return_if_fail (templ != NULL);
372 
373   rtpbasepayload->sinkpad = gst_pad_new_from_template (templ, "sink");
374   gst_pad_set_chain_function (rtpbasepayload->sinkpad,
375       gst_rtp_base_payload_chain);
376   gst_pad_set_event_function (rtpbasepayload->sinkpad,
377       gst_rtp_base_payload_sink_event);
378   gst_pad_set_query_function (rtpbasepayload->sinkpad,
379       gst_rtp_base_payload_query);
380   gst_element_add_pad (GST_ELEMENT (rtpbasepayload), rtpbasepayload->sinkpad);
381 
382   rtpbasepayload->mtu = DEFAULT_MTU;
383   rtpbasepayload->pt = DEFAULT_PT;
384   rtpbasepayload->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
385   rtpbasepayload->ssrc = DEFAULT_SSRC;
386   rtpbasepayload->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
387   priv->running_time = DEFAULT_RUNNING_TIME;
388   priv->seqnum_offset_random = (rtpbasepayload->seqnum_offset == -1);
389   priv->ts_offset_random = (rtpbasepayload->ts_offset == -1);
390   priv->ssrc_random = (rtpbasepayload->ssrc == -1);
391   priv->pt_set = FALSE;
392   priv->source_info = DEFAULT_SOURCE_INFO;
393 
394   rtpbasepayload->max_ptime = DEFAULT_MAX_PTIME;
395   rtpbasepayload->min_ptime = DEFAULT_MIN_PTIME;
396   rtpbasepayload->priv->perfect_rtptime = DEFAULT_PERFECT_RTPTIME;
397   rtpbasepayload->ptime_multiple = DEFAULT_PTIME_MULTIPLE;
398   rtpbasepayload->priv->base_offset = GST_BUFFER_OFFSET_NONE;
399   rtpbasepayload->priv->base_rtime_hz = GST_BUFFER_OFFSET_NONE;
400   rtpbasepayload->priv->onvif_no_rate_control = DEFAULT_ONVIF_NO_RATE_CONTROL;
401 
402   rtpbasepayload->media = NULL;
403   rtpbasepayload->encoding_name = NULL;
404 
405   rtpbasepayload->clock_rate = 0;
406 
407   rtpbasepayload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
408   rtpbasepayload->priv->prop_max_ptime = DEFAULT_MAX_PTIME;
409 }
410 
411 static void
gst_rtp_base_payload_finalize(GObject * object)412 gst_rtp_base_payload_finalize (GObject * object)
413 {
414   GstRTPBasePayload *rtpbasepayload;
415 
416   rtpbasepayload = GST_RTP_BASE_PAYLOAD (object);
417 
418   g_free (rtpbasepayload->media);
419   rtpbasepayload->media = NULL;
420   g_free (rtpbasepayload->encoding_name);
421   rtpbasepayload->encoding_name = NULL;
422 
423   gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
424   gst_caps_replace (&rtpbasepayload->priv->sinkcaps, NULL);
425 
426   G_OBJECT_CLASS (parent_class)->finalize (object);
427 }
428 
429 static GstCaps *
gst_rtp_base_payload_getcaps_default(GstRTPBasePayload * rtpbasepayload,GstPad * pad,GstCaps * filter)430 gst_rtp_base_payload_getcaps_default (GstRTPBasePayload * rtpbasepayload,
431     GstPad * pad, GstCaps * filter)
432 {
433   GstCaps *caps;
434 
435   caps = GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
436   GST_DEBUG_OBJECT (pad,
437       "using pad template %p with caps %p %" GST_PTR_FORMAT,
438       GST_PAD_PAD_TEMPLATE (pad), caps, caps);
439 
440   if (filter)
441     caps = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
442   else
443     caps = gst_caps_ref (caps);
444 
445   return caps;
446 }
447 
448 static gboolean
gst_rtp_base_payload_sink_event_default(GstRTPBasePayload * rtpbasepayload,GstEvent * event)449 gst_rtp_base_payload_sink_event_default (GstRTPBasePayload * rtpbasepayload,
450     GstEvent * event)
451 {
452   GstObject *parent = GST_OBJECT_CAST (rtpbasepayload);
453   gboolean res = FALSE;
454 
455   switch (GST_EVENT_TYPE (event)) {
456     case GST_EVENT_FLUSH_START:
457       res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
458       break;
459     case GST_EVENT_FLUSH_STOP:
460       res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
461       gst_segment_init (&rtpbasepayload->segment, GST_FORMAT_UNDEFINED);
462       gst_event_replace (&rtpbasepayload->priv->pending_segment, NULL);
463       break;
464     case GST_EVENT_CAPS:
465     {
466       GstRTPBasePayloadClass *rtpbasepayload_class;
467       GstCaps *caps;
468 
469       gst_event_parse_caps (event, &caps);
470       GST_DEBUG_OBJECT (rtpbasepayload, "setting caps %" GST_PTR_FORMAT, caps);
471 
472       gst_caps_replace (&rtpbasepayload->priv->sinkcaps, caps);
473 
474       rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
475       if (rtpbasepayload_class->set_caps)
476         res = rtpbasepayload_class->set_caps (rtpbasepayload, caps);
477       else
478         res = gst_rtp_base_payload_negotiate (rtpbasepayload);
479 
480       rtpbasepayload->priv->negotiated = res;
481 
482       gst_event_unref (event);
483       break;
484     }
485     case GST_EVENT_SEGMENT:
486     {
487       GstSegment *segment;
488 
489       segment = &rtpbasepayload->segment;
490       gst_event_copy_segment (event, segment);
491 
492       rtpbasepayload->priv->base_offset = GST_BUFFER_OFFSET_NONE;
493 
494       GST_DEBUG_OBJECT (rtpbasepayload,
495           "configured SEGMENT %" GST_SEGMENT_FORMAT, segment);
496       if (rtpbasepayload->priv->delay_segment) {
497         gst_event_replace (&rtpbasepayload->priv->pending_segment, event);
498         gst_event_unref (event);
499         res = TRUE;
500       } else {
501         res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
502       }
503       break;
504     }
505     default:
506       res = gst_pad_event_default (rtpbasepayload->sinkpad, parent, event);
507       break;
508   }
509   return res;
510 }
511 
512 static gboolean
gst_rtp_base_payload_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)513 gst_rtp_base_payload_sink_event (GstPad * pad, GstObject * parent,
514     GstEvent * event)
515 {
516   GstRTPBasePayload *rtpbasepayload;
517   GstRTPBasePayloadClass *rtpbasepayload_class;
518   gboolean res = FALSE;
519 
520   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
521   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
522 
523   if (rtpbasepayload_class->sink_event)
524     res = rtpbasepayload_class->sink_event (rtpbasepayload, event);
525   else
526     gst_event_unref (event);
527 
528   return res;
529 }
530 
531 static gboolean
gst_rtp_base_payload_src_event_default(GstRTPBasePayload * rtpbasepayload,GstEvent * event)532 gst_rtp_base_payload_src_event_default (GstRTPBasePayload * rtpbasepayload,
533     GstEvent * event)
534 {
535   GstObject *parent = GST_OBJECT_CAST (rtpbasepayload);
536   gboolean res = TRUE, forward = TRUE;
537 
538   switch (GST_EVENT_TYPE (event)) {
539     case GST_EVENT_CUSTOM_UPSTREAM:
540     {
541       const GstStructure *s = gst_event_get_structure (event);
542 
543       if (gst_structure_has_name (s, "GstRTPCollision")) {
544         guint ssrc = 0;
545 
546         if (!gst_structure_get_uint (s, "ssrc", &ssrc))
547           ssrc = -1;
548 
549         GST_DEBUG_OBJECT (rtpbasepayload, "collided ssrc: %" G_GUINT32_FORMAT,
550             ssrc);
551 
552         /* choose another ssrc for our stream */
553         if (ssrc == rtpbasepayload->current_ssrc) {
554           GstCaps *caps;
555           guint suggested_ssrc = 0;
556 
557           if (gst_structure_get_uint (s, "suggested-ssrc", &suggested_ssrc))
558             rtpbasepayload->current_ssrc = suggested_ssrc;
559 
560           while (ssrc == rtpbasepayload->current_ssrc)
561             rtpbasepayload->current_ssrc = g_random_int ();
562 
563           caps = gst_pad_get_current_caps (rtpbasepayload->srcpad);
564           if (caps) {
565             caps = gst_caps_make_writable (caps);
566             gst_caps_set_simple (caps,
567                 "ssrc", G_TYPE_UINT, rtpbasepayload->current_ssrc, NULL);
568             res = gst_pad_set_caps (rtpbasepayload->srcpad, caps);
569             gst_caps_unref (caps);
570           }
571 
572           /* the event was for us */
573           forward = FALSE;
574         }
575       }
576       break;
577     }
578     default:
579       break;
580   }
581 
582   if (forward)
583     res = gst_pad_event_default (rtpbasepayload->srcpad, parent, event);
584   else
585     gst_event_unref (event);
586 
587   return res;
588 }
589 
590 static gboolean
gst_rtp_base_payload_src_event(GstPad * pad,GstObject * parent,GstEvent * event)591 gst_rtp_base_payload_src_event (GstPad * pad, GstObject * parent,
592     GstEvent * event)
593 {
594   GstRTPBasePayload *rtpbasepayload;
595   GstRTPBasePayloadClass *rtpbasepayload_class;
596   gboolean res = FALSE;
597 
598   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
599   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
600 
601   if (rtpbasepayload_class->src_event)
602     res = rtpbasepayload_class->src_event (rtpbasepayload, event);
603   else
604     gst_event_unref (event);
605 
606   return res;
607 }
608 
609 
610 static gboolean
gst_rtp_base_payload_query_default(GstRTPBasePayload * rtpbasepayload,GstPad * pad,GstQuery * query)611 gst_rtp_base_payload_query_default (GstRTPBasePayload * rtpbasepayload,
612     GstPad * pad, GstQuery * query)
613 {
614   gboolean res = FALSE;
615 
616   switch (GST_QUERY_TYPE (query)) {
617     case GST_QUERY_CAPS:
618     {
619       GstRTPBasePayloadClass *rtpbasepayload_class;
620       GstCaps *filter, *caps;
621 
622       gst_query_parse_caps (query, &filter);
623       GST_DEBUG_OBJECT (rtpbasepayload, "getting caps with filter %"
624           GST_PTR_FORMAT, filter);
625 
626       rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
627       if (rtpbasepayload_class->get_caps) {
628         caps = rtpbasepayload_class->get_caps (rtpbasepayload, pad, filter);
629         gst_query_set_caps_result (query, caps);
630         gst_caps_unref (caps);
631         res = TRUE;
632       }
633       break;
634     }
635     default:
636       res =
637           gst_pad_query_default (pad, GST_OBJECT_CAST (rtpbasepayload), query);
638       break;
639   }
640   return res;
641 }
642 
643 static gboolean
gst_rtp_base_payload_query(GstPad * pad,GstObject * parent,GstQuery * query)644 gst_rtp_base_payload_query (GstPad * pad, GstObject * parent, GstQuery * query)
645 {
646   GstRTPBasePayload *rtpbasepayload;
647   GstRTPBasePayloadClass *rtpbasepayload_class;
648   gboolean res = FALSE;
649 
650   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
651   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
652 
653   if (rtpbasepayload_class->query)
654     res = rtpbasepayload_class->query (rtpbasepayload, pad, query);
655 
656   return res;
657 }
658 
659 static GstFlowReturn
gst_rtp_base_payload_chain(GstPad * pad,GstObject * parent,GstBuffer * buffer)660 gst_rtp_base_payload_chain (GstPad * pad, GstObject * parent,
661     GstBuffer * buffer)
662 {
663   GstRTPBasePayload *rtpbasepayload;
664   GstRTPBasePayloadClass *rtpbasepayload_class;
665   GstFlowReturn ret;
666 
667   rtpbasepayload = GST_RTP_BASE_PAYLOAD (parent);
668   rtpbasepayload_class = GST_RTP_BASE_PAYLOAD_GET_CLASS (rtpbasepayload);
669 
670   if (!rtpbasepayload_class->handle_buffer)
671     goto no_function;
672 
673   if (!rtpbasepayload->priv->negotiated)
674     goto not_negotiated;
675 
676   if (rtpbasepayload->priv->source_info) {
677     /* Save a copy of meta (instead of taking an extra reference before
678      * handle_buffer) to make the meta available when allocating a output
679      * buffer. */
680     rtpbasepayload->priv->input_meta_buffer = gst_buffer_new ();
681     gst_buffer_copy_into (rtpbasepayload->priv->input_meta_buffer, buffer,
682         GST_BUFFER_COPY_META, 0, -1);
683   }
684 
685   if (gst_pad_check_reconfigure (GST_RTP_BASE_PAYLOAD_SRCPAD (rtpbasepayload))) {
686     if (!gst_rtp_base_payload_negotiate (rtpbasepayload)) {
687       gst_pad_mark_reconfigure (GST_RTP_BASE_PAYLOAD_SRCPAD (rtpbasepayload));
688       if (GST_PAD_IS_FLUSHING (GST_RTP_BASE_PAYLOAD_SRCPAD (rtpbasepayload))) {
689         goto flushing;
690       } else {
691         goto negotiate_failed;
692       }
693     }
694   }
695 
696   ret = rtpbasepayload_class->handle_buffer (rtpbasepayload, buffer);
697 
698   gst_buffer_replace (&rtpbasepayload->priv->input_meta_buffer, NULL);
699 
700   return ret;
701 
702   /* ERRORS */
703 no_function:
704   {
705     GST_ELEMENT_ERROR (rtpbasepayload, STREAM, NOT_IMPLEMENTED, (NULL),
706         ("subclass did not implement handle_buffer function"));
707     gst_buffer_unref (buffer);
708     return GST_FLOW_ERROR;
709   }
710 not_negotiated:
711   {
712     GST_ELEMENT_ERROR (rtpbasepayload, CORE, NEGOTIATION, (NULL),
713         ("No input format was negotiated, i.e. no caps event was received. "
714             "Perhaps you need a parser or typefind element before the payloader"));
715     gst_buffer_unref (buffer);
716     return GST_FLOW_NOT_NEGOTIATED;
717   }
718 negotiate_failed:
719   {
720     GST_DEBUG_OBJECT (rtpbasepayload, "Not negotiated");
721     gst_buffer_unref (buffer);
722     return GST_FLOW_NOT_NEGOTIATED;
723   }
724 flushing:
725   {
726     GST_DEBUG_OBJECT (rtpbasepayload, "we are flushing");
727     gst_buffer_unref (buffer);
728     return GST_FLOW_FLUSHING;
729   }
730 }
731 
732 /**
733  * gst_rtp_base_payload_set_options:
734  * @payload: a #GstRTPBasePayload
735  * @media: the media type (typically "audio" or "video")
736  * @dynamic: if the payload type is dynamic
737  * @encoding_name: the encoding name
738  * @clock_rate: the clock rate of the media
739  *
740  * Set the rtp options of the payloader. These options will be set in the caps
741  * of the payloader. Subclasses must call this method before calling
742  * gst_rtp_base_payload_push() or gst_rtp_base_payload_set_outcaps().
743  */
744 void
gst_rtp_base_payload_set_options(GstRTPBasePayload * payload,const gchar * media,gboolean dynamic,const gchar * encoding_name,guint32 clock_rate)745 gst_rtp_base_payload_set_options (GstRTPBasePayload * payload,
746     const gchar * media, gboolean dynamic, const gchar * encoding_name,
747     guint32 clock_rate)
748 {
749   g_return_if_fail (payload != NULL);
750   g_return_if_fail (clock_rate != 0);
751 
752   g_free (payload->media);
753   payload->media = g_strdup (media);
754   payload->dynamic = dynamic;
755   g_free (payload->encoding_name);
756   payload->encoding_name = g_strdup (encoding_name);
757   payload->clock_rate = clock_rate;
758 }
759 
760 static gboolean
copy_fixed(GQuark field_id,const GValue * value,GstStructure * dest)761 copy_fixed (GQuark field_id, const GValue * value, GstStructure * dest)
762 {
763   if (gst_value_is_fixed (value)) {
764     gst_structure_id_set_value (dest, field_id, value);
765   }
766   return TRUE;
767 }
768 
769 static void
update_max_ptime(GstRTPBasePayload * rtpbasepayload)770 update_max_ptime (GstRTPBasePayload * rtpbasepayload)
771 {
772   if (rtpbasepayload->priv->caps_max_ptime != -1 &&
773       rtpbasepayload->priv->prop_max_ptime != -1)
774     rtpbasepayload->max_ptime = MIN (rtpbasepayload->priv->caps_max_ptime,
775         rtpbasepayload->priv->prop_max_ptime);
776   else if (rtpbasepayload->priv->caps_max_ptime != -1)
777     rtpbasepayload->max_ptime = rtpbasepayload->priv->caps_max_ptime;
778   else if (rtpbasepayload->priv->prop_max_ptime != -1)
779     rtpbasepayload->max_ptime = rtpbasepayload->priv->prop_max_ptime;
780   else
781     rtpbasepayload->max_ptime = DEFAULT_MAX_PTIME;
782 }
783 
784 /**
785  * gst_rtp_base_payload_set_outcaps:
786  * @payload: a #GstRTPBasePayload
787  * @fieldname: the first field name or %NULL
788  * @...: field values
789  *
790  * Configure the output caps with the optional parameters.
791  *
792  * Variable arguments should be in the form field name, field type
793  * (as a GType), value(s).  The last variable argument should be NULL.
794  *
795  * Returns: %TRUE if the caps could be set.
796  */
797 gboolean
gst_rtp_base_payload_set_outcaps(GstRTPBasePayload * payload,const gchar * fieldname,...)798 gst_rtp_base_payload_set_outcaps (GstRTPBasePayload * payload,
799     const gchar * fieldname, ...)
800 {
801   GstCaps *srccaps;
802 
803   /* fill in the defaults, their properties cannot be negotiated. */
804   srccaps = gst_caps_new_simple ("application/x-rtp",
805       "media", G_TYPE_STRING, payload->media,
806       "clock-rate", G_TYPE_INT, payload->clock_rate,
807       "encoding-name", G_TYPE_STRING, payload->encoding_name, NULL);
808 
809   GST_DEBUG_OBJECT (payload, "defaults: %" GST_PTR_FORMAT, srccaps);
810 
811   if (fieldname) {
812     va_list varargs;
813 
814     /* override with custom properties */
815     va_start (varargs, fieldname);
816     gst_caps_set_simple_valist (srccaps, fieldname, varargs);
817     va_end (varargs);
818 
819     GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps);
820   }
821 
822   gst_caps_replace (&payload->priv->subclass_srccaps, srccaps);
823   gst_caps_unref (srccaps);
824 
825   return gst_rtp_base_payload_negotiate (payload);
826 }
827 
828 static gboolean
gst_rtp_base_payload_negotiate(GstRTPBasePayload * payload)829 gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload)
830 {
831   GstCaps *templ, *peercaps, *srccaps;
832   GstStructure *s, *d;
833   gboolean res;
834 
835   payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
836   payload->ptime = 0;
837 
838   gst_pad_check_reconfigure (payload->srcpad);
839 
840   templ = gst_pad_get_pad_template_caps (payload->srcpad);
841 
842   if (payload->priv->subclass_srccaps) {
843     GstCaps *tmp = gst_caps_intersect (payload->priv->subclass_srccaps,
844         templ);
845     gst_caps_unref (templ);
846     templ = tmp;
847   }
848 
849   peercaps = gst_pad_peer_query_caps (payload->srcpad, templ);
850 
851   if (peercaps == NULL) {
852     /* no peer caps, just add the other properties */
853 
854     srccaps = gst_caps_copy (templ);
855     gst_caps_set_simple (srccaps,
856         "payload", G_TYPE_INT, GST_RTP_BASE_PAYLOAD_PT (payload),
857         "ssrc", G_TYPE_UINT, payload->current_ssrc,
858         "timestamp-offset", G_TYPE_UINT, payload->ts_base,
859         "seqnum-offset", G_TYPE_UINT, payload->seqnum_base, NULL);
860 
861     GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps);
862   } else {
863     GstCaps *temp;
864     const GValue *value;
865     gboolean have_pt = FALSE;
866     gboolean have_ts_offset = FALSE;
867     gboolean have_seqnum_offset = FALSE;
868     guint max_ptime, ptime;
869 
870     /* peer provides caps we can use to fixate. They are already intersected
871      * with our srccaps, just make them writable */
872     temp = gst_caps_make_writable (peercaps);
873     peercaps = NULL;
874 
875     if (gst_caps_is_empty (temp)) {
876       gst_caps_unref (temp);
877       gst_caps_unref (templ);
878       res = FALSE;
879       goto out;
880     }
881 
882     /* We prefer the pt, timestamp-offset, seqnum-offset from the
883      * property (if set), or any previously configured value over what
884      * downstream prefers. Only if downstream can't accept that, or the
885      * properties were not set, we fall back to choosing downstream's
886      * preferred value
887      *
888      * For ssrc we prefer any value downstream suggests, otherwise
889      * the property value or as a last resort a random value.
890      * This difference for ssrc is implemented for retaining backwards
891      * compatibility with changing rtpsession's internal-ssrc property.
892      *
893      * FIXME 2.0: All these properties should go away and be negotiated
894      * via caps only!
895      */
896 
897     /* try to use the previously set pt, or the one from the property */
898     if (payload->priv->pt_set || gst_pad_has_current_caps (payload->srcpad)) {
899       GstCaps *probe_caps = gst_caps_copy (templ);
900       GstCaps *intersection;
901 
902       gst_caps_set_simple (probe_caps, "payload", G_TYPE_INT,
903           GST_RTP_BASE_PAYLOAD_PT (payload), NULL);
904       intersection = gst_caps_intersect (probe_caps, temp);
905 
906       if (!gst_caps_is_empty (intersection)) {
907         GST_LOG_OBJECT (payload, "Using selected pt %d",
908             GST_RTP_BASE_PAYLOAD_PT (payload));
909         have_pt = TRUE;
910         gst_caps_unref (temp);
911         temp = intersection;
912       } else {
913         GST_WARNING_OBJECT (payload, "Can't use selected pt %d",
914             GST_RTP_BASE_PAYLOAD_PT (payload));
915         gst_caps_unref (intersection);
916       }
917       gst_caps_unref (probe_caps);
918     }
919 
920     /* If we got no pt above, select one now */
921     if (!have_pt) {
922       gint pt;
923 
924       /* get first structure */
925       s = gst_caps_get_structure (temp, 0);
926 
927       if (gst_structure_get_int (s, "payload", &pt)) {
928         /* use peer pt */
929         GST_RTP_BASE_PAYLOAD_PT (payload) = pt;
930         GST_LOG_OBJECT (payload, "using peer pt %d", pt);
931       } else {
932         if (gst_structure_has_field (s, "payload")) {
933           /* can only fixate if there is a field */
934           gst_structure_fixate_field_nearest_int (s, "payload",
935               GST_RTP_BASE_PAYLOAD_PT (payload));
936           gst_structure_get_int (s, "payload", &pt);
937           GST_RTP_BASE_PAYLOAD_PT (payload) = pt;
938           GST_LOG_OBJECT (payload, "using peer pt %d", pt);
939         } else {
940           /* no pt field, use the internal pt */
941           pt = GST_RTP_BASE_PAYLOAD_PT (payload);
942           gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
943           GST_LOG_OBJECT (payload, "using internal pt %d", pt);
944         }
945       }
946       s = NULL;
947     }
948 
949     /* If we got no ssrc above, select one now */
950     /* get first structure */
951     s = gst_caps_get_structure (temp, 0);
952 
953     if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) {
954       value = gst_structure_get_value (s, "ssrc");
955       payload->current_ssrc = g_value_get_uint (value);
956       GST_LOG_OBJECT (payload, "using peer ssrc %08x", payload->current_ssrc);
957     } else {
958       /* FIXME, fixate_nearest_uint would be even better but we
959        * don't support uint ranges so how likely is it that anybody
960        * uses a list of possible ssrcs */
961       gst_structure_set (s, "ssrc", G_TYPE_UINT, payload->current_ssrc, NULL);
962       GST_LOG_OBJECT (payload, "using internal ssrc %08x",
963           payload->current_ssrc);
964     }
965     s = NULL;
966 
967     /* try to select the previously used timestamp-offset, or the one from the property */
968     if (!payload->priv->ts_offset_random
969         || gst_pad_has_current_caps (payload->srcpad)) {
970       GstCaps *probe_caps = gst_caps_copy (templ);
971       GstCaps *intersection;
972 
973       gst_caps_set_simple (probe_caps, "timestamp-offset", G_TYPE_UINT,
974           payload->ts_base, NULL);
975       intersection = gst_caps_intersect (probe_caps, temp);
976 
977       if (!gst_caps_is_empty (intersection)) {
978         GST_LOG_OBJECT (payload, "Using selected timestamp-offset %u",
979             payload->ts_base);
980         gst_caps_unref (temp);
981         temp = intersection;
982         have_ts_offset = TRUE;
983       } else {
984         GST_WARNING_OBJECT (payload, "Can't use selected timestamp-offset %u",
985             payload->ts_base);
986         gst_caps_unref (intersection);
987       }
988       gst_caps_unref (probe_caps);
989     }
990 
991     /* If we got no timestamp-offset above, select one now */
992     if (!have_ts_offset) {
993       /* get first structure */
994       s = gst_caps_get_structure (temp, 0);
995 
996       if (gst_structure_has_field_typed (s, "timestamp-offset", G_TYPE_UINT)) {
997         value = gst_structure_get_value (s, "timestamp-offset");
998         payload->ts_base = g_value_get_uint (value);
999         GST_LOG_OBJECT (payload, "using peer timestamp-offset %u",
1000             payload->ts_base);
1001       } else {
1002         /* FIXME, fixate_nearest_uint would be even better but we
1003          * don't support uint ranges so how likely is it that anybody
1004          * uses a list of possible timestamp-offsets */
1005         gst_structure_set (s, "timestamp-offset", G_TYPE_UINT, payload->ts_base,
1006             NULL);
1007         GST_LOG_OBJECT (payload, "using internal timestamp-offset %u",
1008             payload->ts_base);
1009       }
1010       s = NULL;
1011     }
1012 
1013     /* try to select the previously used seqnum-offset, or the one from the property */
1014     if (!payload->priv->seqnum_offset_random
1015         || gst_pad_has_current_caps (payload->srcpad)) {
1016       GstCaps *probe_caps = gst_caps_copy (templ);
1017       GstCaps *intersection;
1018 
1019       gst_caps_set_simple (probe_caps, "seqnum-offset", G_TYPE_UINT,
1020           payload->seqnum_base, NULL);
1021       intersection = gst_caps_intersect (probe_caps, temp);
1022 
1023       if (!gst_caps_is_empty (intersection)) {
1024         GST_LOG_OBJECT (payload, "Using selected seqnum-offset %u",
1025             payload->seqnum_base);
1026         gst_caps_unref (temp);
1027         temp = intersection;
1028         have_seqnum_offset = TRUE;
1029       } else {
1030         GST_WARNING_OBJECT (payload, "Can't use selected seqnum-offset %u",
1031             payload->seqnum_base);
1032         gst_caps_unref (intersection);
1033       }
1034       gst_caps_unref (probe_caps);
1035     }
1036 
1037     /* If we got no seqnum-offset above, select one now */
1038     if (!have_seqnum_offset) {
1039       /* get first structure */
1040       s = gst_caps_get_structure (temp, 0);
1041 
1042       if (gst_structure_has_field_typed (s, "seqnum-offset", G_TYPE_UINT)) {
1043         value = gst_structure_get_value (s, "seqnum-offset");
1044         payload->seqnum_base = g_value_get_uint (value);
1045         GST_LOG_OBJECT (payload, "using peer seqnum-offset %u",
1046             payload->seqnum_base);
1047         payload->priv->next_seqnum = payload->seqnum_base;
1048         payload->seqnum = payload->seqnum_base;
1049         payload->priv->seqnum_offset_random = FALSE;
1050       } else {
1051         /* FIXME, fixate_nearest_uint would be even better but we
1052          * don't support uint ranges so how likely is it that anybody
1053          * uses a list of possible seqnum-offsets */
1054         gst_structure_set (s, "seqnum-offset", G_TYPE_UINT,
1055             payload->seqnum_base, NULL);
1056         GST_LOG_OBJECT (payload, "using internal seqnum-offset %u",
1057             payload->seqnum_base);
1058       }
1059 
1060       s = NULL;
1061     }
1062 
1063     /* now fixate, start by taking the first caps */
1064     temp = gst_caps_truncate (temp);
1065 
1066     /* get first structure */
1067     s = gst_caps_get_structure (temp, 0);
1068 
1069     if (gst_structure_get_uint (s, "maxptime", &max_ptime))
1070       payload->priv->caps_max_ptime = max_ptime * GST_MSECOND;
1071 
1072     if (gst_structure_get_uint (s, "ptime", &ptime))
1073       payload->ptime = ptime * GST_MSECOND;
1074 
1075     /* make the target caps by copying over all the fixed fields, removing the
1076      * unfixed fields. */
1077     srccaps = gst_caps_new_empty_simple (gst_structure_get_name (s));
1078     d = gst_caps_get_structure (srccaps, 0);
1079 
1080     gst_structure_foreach (s, (GstStructureForeachFunc) copy_fixed, d);
1081 
1082     gst_caps_unref (temp);
1083 
1084     GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
1085   }
1086 
1087   if (payload->priv->sinkcaps != NULL) {
1088     s = gst_caps_get_structure (payload->priv->sinkcaps, 0);
1089     if (g_str_has_prefix (gst_structure_get_name (s), "video")) {
1090       gboolean has_framerate;
1091       gint num, denom;
1092 
1093       GST_DEBUG_OBJECT (payload, "video caps: %" GST_PTR_FORMAT,
1094           payload->priv->sinkcaps);
1095 
1096       has_framerate = gst_structure_get_fraction (s, "framerate", &num, &denom);
1097       if (has_framerate && num == 0 && denom == 1) {
1098         has_framerate =
1099             gst_structure_get_fraction (s, "max-framerate", &num, &denom);
1100       }
1101 
1102       if (has_framerate) {
1103         gchar str[G_ASCII_DTOSTR_BUF_SIZE];
1104         gdouble framerate;
1105 
1106         gst_util_fraction_to_double (num, denom, &framerate);
1107         g_ascii_dtostr (str, G_ASCII_DTOSTR_BUF_SIZE, framerate);
1108         d = gst_caps_get_structure (srccaps, 0);
1109         gst_structure_set (d, "a-framerate", G_TYPE_STRING, str, NULL);
1110       }
1111 
1112       GST_DEBUG_OBJECT (payload, "with video caps: %" GST_PTR_FORMAT, srccaps);
1113     }
1114   }
1115 
1116   update_max_ptime (payload);
1117 
1118   res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
1119   gst_caps_unref (srccaps);
1120   gst_caps_unref (templ);
1121 
1122 out:
1123 
1124   if (!res)
1125     gst_pad_mark_reconfigure (GST_RTP_BASE_PAYLOAD_SRCPAD (payload));
1126 
1127   return res;
1128 }
1129 
1130 /**
1131  * gst_rtp_base_payload_is_filled:
1132  * @payload: a #GstRTPBasePayload
1133  * @size: the size of the packet
1134  * @duration: the duration of the packet
1135  *
1136  * Check if the packet with @size and @duration would exceed the configured
1137  * maximum size.
1138  *
1139  * Returns: %TRUE if the packet of @size and @duration would exceed the
1140  * configured MTU or max_ptime.
1141  */
1142 gboolean
gst_rtp_base_payload_is_filled(GstRTPBasePayload * payload,guint size,GstClockTime duration)1143 gst_rtp_base_payload_is_filled (GstRTPBasePayload * payload,
1144     guint size, GstClockTime duration)
1145 {
1146   if (size > payload->mtu)
1147     return TRUE;
1148 
1149   if (payload->max_ptime != -1 && duration >= payload->max_ptime)
1150     return TRUE;
1151 
1152   return FALSE;
1153 }
1154 
1155 typedef struct
1156 {
1157   GstRTPBasePayload *payload;
1158   guint32 ssrc;
1159   guint16 seqnum;
1160   guint8 pt;
1161   GstClockTime dts;
1162   GstClockTime pts;
1163   guint64 offset;
1164   guint32 rtptime;
1165 } HeaderData;
1166 
1167 static gboolean
find_timestamp(GstBuffer ** buffer,guint idx,gpointer user_data)1168 find_timestamp (GstBuffer ** buffer, guint idx, gpointer user_data)
1169 {
1170   HeaderData *data = user_data;
1171   data->dts = GST_BUFFER_DTS (*buffer);
1172   data->pts = GST_BUFFER_PTS (*buffer);
1173   data->offset = GST_BUFFER_OFFSET (*buffer);
1174 
1175   /* stop when we find a timestamp. We take whatever offset is associated with
1176    * the timestamp (if any) to do perfect timestamps when we need to. */
1177   if (data->pts != -1)
1178     return FALSE;
1179   else
1180     return TRUE;
1181 }
1182 
1183 static gboolean
set_headers(GstBuffer ** buffer,guint idx,gpointer user_data)1184 set_headers (GstBuffer ** buffer, guint idx, gpointer user_data)
1185 {
1186   HeaderData *data = user_data;
1187   GstRTPBuffer rtp = { NULL, };
1188 
1189   if (!gst_rtp_buffer_map (*buffer, GST_MAP_WRITE, &rtp))
1190     goto map_failed;
1191 
1192   gst_rtp_buffer_set_ssrc (&rtp, data->ssrc);
1193   gst_rtp_buffer_set_payload_type (&rtp, data->pt);
1194   gst_rtp_buffer_set_seq (&rtp, data->seqnum);
1195   gst_rtp_buffer_set_timestamp (&rtp, data->rtptime);
1196   gst_rtp_buffer_unmap (&rtp);
1197 
1198   /* increment the seqnum for each buffer */
1199   data->seqnum++;
1200 
1201   return TRUE;
1202   /* ERRORS */
1203 map_failed:
1204   {
1205     GST_ERROR ("failed to map buffer %p", *buffer);
1206     return FALSE;
1207   }
1208 }
1209 
1210 static gboolean
foreach_metadata_drop(GstBuffer * buffer,GstMeta ** meta,gpointer user_data)1211 foreach_metadata_drop (GstBuffer * buffer, GstMeta ** meta, gpointer user_data)
1212 {
1213   GType drop_api_type = (GType) GPOINTER_TO_INT (user_data);
1214   const GstMetaInfo *info = (*meta)->info;
1215 
1216   if (info->api == drop_api_type)
1217     *meta = NULL;
1218 
1219   return TRUE;
1220 }
1221 
1222 static gboolean
filter_meta(GstBuffer ** buffer,guint idx,gpointer user_data)1223 filter_meta (GstBuffer ** buffer, guint idx, gpointer user_data)
1224 {
1225   return gst_buffer_foreach_meta (*buffer, foreach_metadata_drop,
1226       GINT_TO_POINTER (GST_RTP_SOURCE_META_API_TYPE));
1227 }
1228 
1229 /* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer
1230  * before the buffer is pushed. */
1231 static GstFlowReturn
gst_rtp_base_payload_prepare_push(GstRTPBasePayload * payload,gpointer obj,gboolean is_list)1232 gst_rtp_base_payload_prepare_push (GstRTPBasePayload * payload,
1233     gpointer obj, gboolean is_list)
1234 {
1235   GstRTPBasePayloadPrivate *priv;
1236   HeaderData data;
1237 
1238   if (payload->clock_rate == 0)
1239     goto no_rate;
1240 
1241   priv = payload->priv;
1242 
1243   /* update first, so that the property is set to the last
1244    * seqnum pushed */
1245   payload->seqnum = priv->next_seqnum;
1246 
1247   /* fill in the fields we want to set on all headers */
1248   data.payload = payload;
1249   data.seqnum = payload->seqnum;
1250   data.ssrc = payload->current_ssrc;
1251   data.pt = payload->pt;
1252 
1253   /* find the first buffer with a timestamp */
1254   if (is_list) {
1255     data.dts = -1;
1256     data.pts = -1;
1257     data.offset = GST_BUFFER_OFFSET_NONE;
1258     gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), find_timestamp, &data);
1259   } else {
1260     data.dts = GST_BUFFER_DTS (GST_BUFFER_CAST (obj));
1261     data.pts = GST_BUFFER_PTS (GST_BUFFER_CAST (obj));
1262     data.offset = GST_BUFFER_OFFSET (GST_BUFFER_CAST (obj));
1263   }
1264 
1265   /* convert to RTP time */
1266   if (priv->perfect_rtptime && data.offset != GST_BUFFER_OFFSET_NONE &&
1267       priv->base_offset != GST_BUFFER_OFFSET_NONE) {
1268     /* generate perfect RTP time by adding together the base timestamp, the
1269      * running time of the first buffer and difference between the offset of the
1270      * first buffer and the offset of the current buffer. */
1271     guint64 offset = data.offset - priv->base_offset;
1272     data.rtptime = payload->ts_base + priv->base_rtime_hz + offset;
1273 
1274     GST_LOG_OBJECT (payload,
1275         "Using offset %" G_GUINT64_FORMAT " for RTP timestamp", data.offset);
1276 
1277     /* store buffer's running time */
1278     GST_LOG_OBJECT (payload,
1279         "setting running-time to %" G_GUINT64_FORMAT,
1280         data.offset - priv->base_offset);
1281     priv->running_time = priv->base_rtime + data.offset - priv->base_offset;
1282   } else if (GST_CLOCK_TIME_IS_VALID (data.pts)) {
1283     guint64 rtime_ns;
1284     guint64 rtime_hz;
1285 
1286     /* no offset, use the gstreamer pts */
1287     if (priv->onvif_no_rate_control)
1288       rtime_ns = data.pts;
1289     else
1290       rtime_ns =
1291           gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
1292           data.pts);
1293 
1294     if (!GST_CLOCK_TIME_IS_VALID (rtime_ns)) {
1295       GST_LOG_OBJECT (payload, "Clipped pts, using base RTP timestamp");
1296       rtime_hz = 0;
1297     } else {
1298       GST_LOG_OBJECT (payload,
1299           "Using running_time %" GST_TIME_FORMAT " for RTP timestamp",
1300           GST_TIME_ARGS (rtime_ns));
1301       rtime_hz =
1302           gst_util_uint64_scale_int (rtime_ns, payload->clock_rate, GST_SECOND);
1303       priv->base_offset = data.offset;
1304       priv->base_rtime_hz = rtime_hz;
1305     }
1306 
1307     /* add running_time in clock-rate units to the base timestamp */
1308     data.rtptime = payload->ts_base + rtime_hz;
1309 
1310     /* store buffer's running time */
1311     if (priv->perfect_rtptime) {
1312       GST_LOG_OBJECT (payload,
1313           "setting running-time to %" G_GUINT64_FORMAT, rtime_hz);
1314       priv->running_time = rtime_hz;
1315     } else {
1316       GST_LOG_OBJECT (payload,
1317           "setting running-time to %" GST_TIME_FORMAT,
1318           GST_TIME_ARGS (rtime_ns));
1319       priv->running_time = rtime_ns;
1320     }
1321   } else {
1322     GST_LOG_OBJECT (payload,
1323         "Using previous RTP timestamp %" G_GUINT32_FORMAT, payload->timestamp);
1324     /* no timestamp to convert, take previous timestamp */
1325     data.rtptime = payload->timestamp;
1326   }
1327 
1328   /* set ssrc, payload type, seq number, caps and rtptime */
1329   /* remove unwanted meta */
1330   if (is_list) {
1331     gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), set_headers, &data);
1332     gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), filter_meta, NULL);
1333     /* sequence number has increased more if this was a buffer list */
1334     payload->seqnum = data.seqnum - 1;
1335   } else {
1336     GstBuffer *buf = GST_BUFFER_CAST (obj);
1337     set_headers (&buf, 0, &data);
1338     filter_meta (&buf, 0, NULL);
1339   }
1340 
1341   priv->next_seqnum = data.seqnum;
1342   payload->timestamp = data.rtptime;
1343 
1344   GST_LOG_OBJECT (payload, "Preparing to push %s with size %"
1345       G_GSIZE_FORMAT ", seq=%d, rtptime=%u, pts %" GST_TIME_FORMAT,
1346       (is_list) ? "list" : "packet",
1347       (is_list) ? gst_buffer_list_length (GST_BUFFER_LIST_CAST (obj)) :
1348       gst_buffer_get_size (GST_BUFFER (obj)),
1349       payload->seqnum, data.rtptime, GST_TIME_ARGS (data.pts));
1350 
1351   if (g_atomic_int_compare_and_exchange (&payload->priv->
1352           notified_first_timestamp, 1, 0)) {
1353     g_object_notify (G_OBJECT (payload), "timestamp");
1354     g_object_notify (G_OBJECT (payload), "seqnum");
1355   }
1356 
1357   return GST_FLOW_OK;
1358 
1359   /* ERRORS */
1360 no_rate:
1361   {
1362     GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
1363         ("subclass did not specify clock-rate"));
1364     return GST_FLOW_ERROR;
1365   }
1366 }
1367 
1368 /**
1369  * gst_rtp_base_payload_push_list:
1370  * @payload: a #GstRTPBasePayload
1371  * @list: a #GstBufferList
1372  *
1373  * Push @list to the peer element of the payloader. The SSRC, payload type,
1374  * seqnum and timestamp of the RTP buffer will be updated first.
1375  *
1376  * This function takes ownership of @list.
1377  *
1378  * Returns: a #GstFlowReturn.
1379  */
1380 GstFlowReturn
gst_rtp_base_payload_push_list(GstRTPBasePayload * payload,GstBufferList * list)1381 gst_rtp_base_payload_push_list (GstRTPBasePayload * payload,
1382     GstBufferList * list)
1383 {
1384   GstFlowReturn res;
1385 
1386   res = gst_rtp_base_payload_prepare_push (payload, list, TRUE);
1387 
1388   if (G_LIKELY (res == GST_FLOW_OK)) {
1389     if (G_UNLIKELY (payload->priv->pending_segment)) {
1390       gst_pad_push_event (payload->srcpad, payload->priv->pending_segment);
1391       payload->priv->pending_segment = FALSE;
1392       payload->priv->delay_segment = FALSE;
1393     }
1394     res = gst_pad_push_list (payload->srcpad, list);
1395   } else {
1396     gst_buffer_list_unref (list);
1397   }
1398 
1399   return res;
1400 }
1401 
1402 /**
1403  * gst_rtp_base_payload_push:
1404  * @payload: a #GstRTPBasePayload
1405  * @buffer: a #GstBuffer
1406  *
1407  * Push @buffer to the peer element of the payloader. The SSRC, payload type,
1408  * seqnum and timestamp of the RTP buffer will be updated first.
1409  *
1410  * This function takes ownership of @buffer.
1411  *
1412  * Returns: a #GstFlowReturn.
1413  */
1414 GstFlowReturn
gst_rtp_base_payload_push(GstRTPBasePayload * payload,GstBuffer * buffer)1415 gst_rtp_base_payload_push (GstRTPBasePayload * payload, GstBuffer * buffer)
1416 {
1417   GstFlowReturn res;
1418 
1419   res = gst_rtp_base_payload_prepare_push (payload, buffer, FALSE);
1420 
1421   if (G_LIKELY (res == GST_FLOW_OK)) {
1422     if (G_UNLIKELY (payload->priv->pending_segment)) {
1423       gst_pad_push_event (payload->srcpad, payload->priv->pending_segment);
1424       payload->priv->pending_segment = FALSE;
1425       payload->priv->delay_segment = FALSE;
1426     }
1427     res = gst_pad_push (payload->srcpad, buffer);
1428   } else {
1429     gst_buffer_unref (buffer);
1430   }
1431 
1432   return res;
1433 }
1434 
1435 /**
1436  * gst_rtp_base_payload_allocate_output_buffer:
1437  * @payload: a #GstRTPBasePayload
1438  * @payload_len: the length of the payload
1439  * @pad_len: the amount of padding
1440  * @csrc_count: the minimum number of CSRC entries
1441  *
1442  * Allocate a new #GstBuffer with enough data to hold an RTP packet with
1443  * minimum @csrc_count CSRCs, a payload length of @payload_len and padding of
1444  * @pad_len. If @payload has #GstRTPBasePayload:source-info %TRUE additional
1445  * CSRCs may be allocated and filled with RTP source information.
1446  *
1447  * Returns: A newly allocated buffer that can hold an RTP packet with given
1448  * parameters.
1449  *
1450  * Since: 1.16
1451  */
1452 GstBuffer *
gst_rtp_base_payload_allocate_output_buffer(GstRTPBasePayload * payload,guint payload_len,guint8 pad_len,guint8 csrc_count)1453 gst_rtp_base_payload_allocate_output_buffer (GstRTPBasePayload * payload,
1454     guint payload_len, guint8 pad_len, guint8 csrc_count)
1455 {
1456   GstBuffer *buffer = NULL;
1457 
1458   if (payload->priv->input_meta_buffer != NULL) {
1459     GstRTPSourceMeta *meta =
1460         gst_buffer_get_rtp_source_meta (payload->priv->input_meta_buffer);
1461     if (meta != NULL) {
1462       guint total_csrc_count, idx, i;
1463       GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
1464 
1465       total_csrc_count = csrc_count + meta->csrc_count +
1466           (meta->ssrc_valid ? 1 : 0);
1467       total_csrc_count = MIN (total_csrc_count, 15);
1468       buffer = gst_rtp_buffer_new_allocate (payload_len, pad_len,
1469           total_csrc_count);
1470 
1471       gst_rtp_buffer_map (buffer, GST_MAP_READWRITE, &rtp);
1472 
1473       /* Skip CSRC fields requested by derived class and fill CSRCs from meta.
1474        * Finally append the SSRC as a new CSRC. */
1475       idx = csrc_count;
1476       for (i = 0; i < meta->csrc_count && idx < 15; i++, idx++)
1477         gst_rtp_buffer_set_csrc (&rtp, idx, meta->csrc[i]);
1478       if (meta->ssrc_valid && idx < 15)
1479         gst_rtp_buffer_set_csrc (&rtp, idx, meta->ssrc);
1480 
1481       gst_rtp_buffer_unmap (&rtp);
1482     }
1483   }
1484 
1485   if (buffer == NULL)
1486     buffer = gst_rtp_buffer_new_allocate (payload_len, pad_len, csrc_count);
1487 
1488   return buffer;
1489 }
1490 
1491 static GstStructure *
gst_rtp_base_payload_create_stats(GstRTPBasePayload * rtpbasepayload)1492 gst_rtp_base_payload_create_stats (GstRTPBasePayload * rtpbasepayload)
1493 {
1494   GstRTPBasePayloadPrivate *priv;
1495   GstStructure *s;
1496 
1497   priv = rtpbasepayload->priv;
1498 
1499   s = gst_structure_new ("application/x-rtp-payload-stats",
1500       "clock-rate", G_TYPE_UINT, (guint) rtpbasepayload->clock_rate,
1501       "running-time", G_TYPE_UINT64, priv->running_time,
1502       "seqnum", G_TYPE_UINT, (guint) rtpbasepayload->seqnum,
1503       "timestamp", G_TYPE_UINT, (guint) rtpbasepayload->timestamp,
1504       "ssrc", G_TYPE_UINT, rtpbasepayload->current_ssrc,
1505       "pt", G_TYPE_UINT, rtpbasepayload->pt,
1506       "seqnum-offset", G_TYPE_UINT, (guint) rtpbasepayload->seqnum_base,
1507       "timestamp-offset", G_TYPE_UINT, (guint) rtpbasepayload->ts_base, NULL);
1508 
1509   return s;
1510 }
1511 
1512 static void
gst_rtp_base_payload_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1513 gst_rtp_base_payload_set_property (GObject * object, guint prop_id,
1514     const GValue * value, GParamSpec * pspec)
1515 {
1516   GstRTPBasePayload *rtpbasepayload;
1517   GstRTPBasePayloadPrivate *priv;
1518   gint64 val;
1519 
1520   rtpbasepayload = GST_RTP_BASE_PAYLOAD (object);
1521   priv = rtpbasepayload->priv;
1522 
1523   switch (prop_id) {
1524     case PROP_MTU:
1525       rtpbasepayload->mtu = g_value_get_uint (value);
1526       break;
1527     case PROP_PT:
1528       rtpbasepayload->pt = g_value_get_uint (value);
1529       priv->pt_set = TRUE;
1530       break;
1531     case PROP_SSRC:
1532       val = g_value_get_uint (value);
1533       rtpbasepayload->ssrc = val;
1534       priv->ssrc_random = FALSE;
1535       break;
1536     case PROP_TIMESTAMP_OFFSET:
1537       val = g_value_get_uint (value);
1538       rtpbasepayload->ts_offset = val;
1539       priv->ts_offset_random = FALSE;
1540       break;
1541     case PROP_SEQNUM_OFFSET:
1542       val = g_value_get_int (value);
1543       rtpbasepayload->seqnum_offset = val;
1544       priv->seqnum_offset_random = (val == -1);
1545       GST_DEBUG_OBJECT (rtpbasepayload, "seqnum offset 0x%04x, random %d",
1546           rtpbasepayload->seqnum_offset, priv->seqnum_offset_random);
1547       break;
1548     case PROP_MAX_PTIME:
1549       rtpbasepayload->priv->prop_max_ptime = g_value_get_int64 (value);
1550       update_max_ptime (rtpbasepayload);
1551       break;
1552     case PROP_MIN_PTIME:
1553       rtpbasepayload->min_ptime = g_value_get_int64 (value);
1554       break;
1555     case PROP_PERFECT_RTPTIME:
1556       priv->perfect_rtptime = g_value_get_boolean (value);
1557       break;
1558     case PROP_PTIME_MULTIPLE:
1559       rtpbasepayload->ptime_multiple = g_value_get_int64 (value);
1560       break;
1561     case PROP_SOURCE_INFO:
1562       gst_rtp_base_payload_set_source_info_enabled (rtpbasepayload,
1563           g_value_get_boolean (value));
1564       break;
1565     case PROP_ONVIF_NO_RATE_CONTROL:
1566       priv->onvif_no_rate_control = g_value_get_boolean (value);
1567       break;
1568     default:
1569       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1570       break;
1571   }
1572 }
1573 
1574 static void
gst_rtp_base_payload_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1575 gst_rtp_base_payload_get_property (GObject * object, guint prop_id,
1576     GValue * value, GParamSpec * pspec)
1577 {
1578   GstRTPBasePayload *rtpbasepayload;
1579   GstRTPBasePayloadPrivate *priv;
1580 
1581   rtpbasepayload = GST_RTP_BASE_PAYLOAD (object);
1582   priv = rtpbasepayload->priv;
1583 
1584   switch (prop_id) {
1585     case PROP_MTU:
1586       g_value_set_uint (value, rtpbasepayload->mtu);
1587       break;
1588     case PROP_PT:
1589       g_value_set_uint (value, rtpbasepayload->pt);
1590       break;
1591     case PROP_SSRC:
1592       if (priv->ssrc_random)
1593         g_value_set_uint (value, -1);
1594       else
1595         g_value_set_uint (value, rtpbasepayload->ssrc);
1596       break;
1597     case PROP_TIMESTAMP_OFFSET:
1598       if (priv->ts_offset_random)
1599         g_value_set_uint (value, -1);
1600       else
1601         g_value_set_uint (value, (guint32) rtpbasepayload->ts_offset);
1602       break;
1603     case PROP_SEQNUM_OFFSET:
1604       if (priv->seqnum_offset_random)
1605         g_value_set_int (value, -1);
1606       else
1607         g_value_set_int (value, (guint16) rtpbasepayload->seqnum_offset);
1608       break;
1609     case PROP_MAX_PTIME:
1610       g_value_set_int64 (value, rtpbasepayload->max_ptime);
1611       break;
1612     case PROP_MIN_PTIME:
1613       g_value_set_int64 (value, rtpbasepayload->min_ptime);
1614       break;
1615     case PROP_TIMESTAMP:
1616       g_value_set_uint (value, rtpbasepayload->timestamp);
1617       break;
1618     case PROP_SEQNUM:
1619       g_value_set_uint (value, rtpbasepayload->seqnum);
1620       break;
1621     case PROP_PERFECT_RTPTIME:
1622       g_value_set_boolean (value, priv->perfect_rtptime);
1623       break;
1624     case PROP_PTIME_MULTIPLE:
1625       g_value_set_int64 (value, rtpbasepayload->ptime_multiple);
1626       break;
1627     case PROP_STATS:
1628       g_value_take_boxed (value,
1629           gst_rtp_base_payload_create_stats (rtpbasepayload));
1630       break;
1631     case PROP_SOURCE_INFO:
1632       g_value_set_boolean (value,
1633           gst_rtp_base_payload_is_source_info_enabled (rtpbasepayload));
1634       break;
1635     case PROP_ONVIF_NO_RATE_CONTROL:
1636       g_value_set_boolean (value, priv->onvif_no_rate_control);
1637       break;
1638     default:
1639       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1640       break;
1641   }
1642 }
1643 
1644 static GstStateChangeReturn
gst_rtp_base_payload_change_state(GstElement * element,GstStateChange transition)1645 gst_rtp_base_payload_change_state (GstElement * element,
1646     GstStateChange transition)
1647 {
1648   GstRTPBasePayload *rtpbasepayload;
1649   GstRTPBasePayloadPrivate *priv;
1650   GstStateChangeReturn ret;
1651 
1652   rtpbasepayload = GST_RTP_BASE_PAYLOAD (element);
1653   priv = rtpbasepayload->priv;
1654 
1655   switch (transition) {
1656     case GST_STATE_CHANGE_NULL_TO_READY:
1657       break;
1658     case GST_STATE_CHANGE_READY_TO_PAUSED:
1659       gst_segment_init (&rtpbasepayload->segment, GST_FORMAT_UNDEFINED);
1660       rtpbasepayload->priv->delay_segment = TRUE;
1661       gst_event_replace (&rtpbasepayload->priv->pending_segment, NULL);
1662 
1663       if (priv->seqnum_offset_random)
1664         rtpbasepayload->seqnum_base = g_random_int_range (0, G_MAXINT16);
1665       else
1666         rtpbasepayload->seqnum_base = rtpbasepayload->seqnum_offset;
1667       priv->next_seqnum = rtpbasepayload->seqnum_base;
1668       rtpbasepayload->seqnum = rtpbasepayload->seqnum_base;
1669 
1670       if (priv->ssrc_random)
1671         rtpbasepayload->current_ssrc = g_random_int ();
1672       else
1673         rtpbasepayload->current_ssrc = rtpbasepayload->ssrc;
1674 
1675       if (priv->ts_offset_random)
1676         rtpbasepayload->ts_base = g_random_int ();
1677       else
1678         rtpbasepayload->ts_base = rtpbasepayload->ts_offset;
1679       rtpbasepayload->timestamp = rtpbasepayload->ts_base;
1680       priv->running_time = DEFAULT_RUNNING_TIME;
1681       g_atomic_int_set (&rtpbasepayload->priv->notified_first_timestamp, 1);
1682       priv->base_offset = GST_BUFFER_OFFSET_NONE;
1683       priv->negotiated = FALSE;
1684       gst_caps_replace (&rtpbasepayload->priv->subclass_srccaps, NULL);
1685       gst_caps_replace (&rtpbasepayload->priv->sinkcaps, NULL);
1686       break;
1687     default:
1688       break;
1689   }
1690 
1691   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1692 
1693   switch (transition) {
1694     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1695       g_atomic_int_set (&rtpbasepayload->priv->notified_first_timestamp, 1);
1696       break;
1697     case GST_STATE_CHANGE_PAUSED_TO_READY:
1698       gst_event_replace (&rtpbasepayload->priv->pending_segment, NULL);
1699       break;
1700     default:
1701       break;
1702   }
1703   return ret;
1704 }
1705 
1706 /**
1707  * gst_rtp_base_payload_set_source_info_enabled:
1708  * @payload: a #GstRTPBasePayload
1709  * @enable: whether to add contributing sources to RTP packets
1710  *
1711  * Enable or disable adding contributing sources to RTP packets from
1712  * #GstRTPSourceMeta.
1713  *
1714  * Since: 1.16
1715  **/
1716 void
gst_rtp_base_payload_set_source_info_enabled(GstRTPBasePayload * payload,gboolean enable)1717 gst_rtp_base_payload_set_source_info_enabled (GstRTPBasePayload * payload,
1718     gboolean enable)
1719 {
1720   payload->priv->source_info = enable;
1721 }
1722 
1723 /**
1724  * gst_rtp_base_payload_is_source_info_enabled:
1725  * @payload: a #GstRTPBasePayload
1726  *
1727  * Queries whether the payloader will add contributing sources (CSRCs) to the
1728  * RTP header from #GstRTPSourceMeta.
1729  *
1730  * Returns: %TRUE if source-info is enabled.
1731  *
1732  * Since: 1.16
1733  **/
1734 gboolean
gst_rtp_base_payload_is_source_info_enabled(GstRTPBasePayload * payload)1735 gst_rtp_base_payload_is_source_info_enabled (GstRTPBasePayload * payload)
1736 {
1737   return payload->priv->source_info;
1738 }
1739 
1740 
1741 /**
1742  * gst_rtp_base_payload_get_source_count:
1743  * @payload: a #GstRTPBasePayload
1744  * @buffer: (transfer none): a #GstBuffer, typically the buffer to payload
1745  *
1746  * Count the total number of RTP sources found in the meta of @buffer, which
1747  * will be automically added by gst_rtp_base_payload_allocate_output_buffer().
1748  * If #GstRTPBasePayload:source-info is %FALSE the count will be 0.
1749  *
1750  * Returns: The number of sources.
1751  *
1752  * Since: 1.16
1753  **/
1754 guint
gst_rtp_base_payload_get_source_count(GstRTPBasePayload * payload,GstBuffer * buffer)1755 gst_rtp_base_payload_get_source_count (GstRTPBasePayload * payload,
1756     GstBuffer * buffer)
1757 {
1758   guint count = 0;
1759 
1760   g_return_val_if_fail (buffer != NULL, 0);
1761 
1762   if (gst_rtp_base_payload_is_source_info_enabled (payload)) {
1763     GstRTPSourceMeta *meta = gst_buffer_get_rtp_source_meta (buffer);
1764     if (meta != NULL)
1765       count = gst_rtp_source_meta_get_source_count (meta);
1766   }
1767 
1768   return count;
1769 }
1770