Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / gst-libs / gst / rtp / gstbasertppayload.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:gstbasertppayload
17  * @short_description: Base class for RTP payloader
18  *
19  * <refsect2>
20  * <para>
21  * Provides a base class for RTP payloaders
22  * </para>
23  * </refsect2>
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #  include "config.h"
28 #endif
29
30 #include <string.h>
31
32 #include <gst/rtp/gstrtpbuffer.h>
33
34 #include "gstbasertppayload.h"
35
36 GST_DEBUG_CATEGORY_STATIC (basertppayload_debug);
37 #define GST_CAT_DEFAULT (basertppayload_debug)
38
39 #define GST_BASE_RTP_PAYLOAD_GET_PRIVATE(obj)  \
40    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_RTP_PAYLOAD, GstBaseRTPPayloadPrivate))
41
42 struct _GstBaseRTPPayloadPrivate
43 {
44   gboolean ts_offset_random;
45   gboolean seqnum_offset_random;
46   gboolean ssrc_random;
47   guint16 next_seqnum;
48   gboolean perfect_rtptime;
49   gint notified_first_timestamp;
50
51   gint64 prop_max_ptime;
52   gint64 caps_max_ptime;
53 };
54
55 /* BaseRTPPayload signals and args */
56 enum
57 {
58   /* FILL ME */
59   LAST_SIGNAL
60 };
61
62 /* FIXME 0.11, a better default is the Ethernet MTU of
63  * 1500 - sizeof(headers) as pointed out by marcelm in IRC:
64  * So an Ethernet MTU of 1500, minus 60 for the max IP, minus 8 for UDP, gives
65  * 1432 bytes or so.  And that should be adjusted downward further for other
66  * encapsulations like PPPoE, so 1400 at most.
67  */
68 #define DEFAULT_MTU                     1400
69 #define DEFAULT_PT                      96
70 #define DEFAULT_SSRC                    -1
71 #define DEFAULT_TIMESTAMP_OFFSET        -1
72 #define DEFAULT_SEQNUM_OFFSET           -1
73 #define DEFAULT_MAX_PTIME               -1
74 #define DEFAULT_MIN_PTIME               0
75 #define DEFAULT_PERFECT_RTPTIME         TRUE
76 #define DEFAULT_PTIME_MULTIPLE          0
77
78 enum
79 {
80   PROP_0,
81   PROP_MTU,
82   PROP_PT,
83   PROP_SSRC,
84   PROP_TIMESTAMP_OFFSET,
85   PROP_SEQNUM_OFFSET,
86   PROP_MAX_PTIME,
87   PROP_MIN_PTIME,
88   PROP_TIMESTAMP,
89   PROP_SEQNUM,
90   PROP_PERFECT_RTPTIME,
91   PROP_PTIME_MULTIPLE,
92   PROP_LAST
93 };
94
95 static void gst_basertppayload_class_init (GstBaseRTPPayloadClass * klass);
96 static void gst_basertppayload_base_init (GstBaseRTPPayloadClass * klass);
97 static void gst_basertppayload_init (GstBaseRTPPayload * basertppayload,
98     gpointer g_class);
99 static void gst_basertppayload_finalize (GObject * object);
100
101 static gboolean gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps);
102 static GstCaps *gst_basertppayload_sink_getcaps (GstPad * pad);
103 static gboolean gst_basertppayload_event (GstPad * pad, GstEvent * event);
104 static GstFlowReturn gst_basertppayload_chain (GstPad * pad,
105     GstBuffer * buffer);
106
107 static void gst_basertppayload_set_property (GObject * object, guint prop_id,
108     const GValue * value, GParamSpec * pspec);
109 static void gst_basertppayload_get_property (GObject * object, guint prop_id,
110     GValue * value, GParamSpec * pspec);
111
112 static GstStateChangeReturn gst_basertppayload_change_state (GstElement *
113     element, GstStateChange transition);
114
115 static GstElementClass *parent_class = NULL;
116
117 /* FIXME 0.11: API should be changed to gst_base_typ_payload_xyz */
118
119 GType
120 gst_basertppayload_get_type (void)
121 {
122   static GType basertppayload_type = 0;
123
124   if (!basertppayload_type) {
125     static const GTypeInfo basertppayload_info = {
126       sizeof (GstBaseRTPPayloadClass),
127       (GBaseInitFunc) gst_basertppayload_base_init,
128       NULL,
129       (GClassInitFunc) gst_basertppayload_class_init,
130       NULL,
131       NULL,
132       sizeof (GstBaseRTPPayload),
133       0,
134       (GInstanceInitFunc) gst_basertppayload_init,
135     };
136
137     basertppayload_type =
138         g_type_register_static (GST_TYPE_ELEMENT, "GstBaseRTPPayload",
139         &basertppayload_info, G_TYPE_FLAG_ABSTRACT);
140   }
141   return basertppayload_type;
142 }
143
144 static void
145 gst_basertppayload_base_init (GstBaseRTPPayloadClass * klass)
146 {
147 }
148
149 static void
150 gst_basertppayload_class_init (GstBaseRTPPayloadClass * klass)
151 {
152   GObjectClass *gobject_class;
153   GstElementClass *gstelement_class;
154
155   gobject_class = (GObjectClass *) klass;
156   gstelement_class = (GstElementClass *) klass;
157
158   g_type_class_add_private (klass, sizeof (GstBaseRTPPayloadPrivate));
159
160   parent_class = g_type_class_peek_parent (klass);
161
162   gobject_class->finalize = gst_basertppayload_finalize;
163
164   gobject_class->set_property = gst_basertppayload_set_property;
165   gobject_class->get_property = gst_basertppayload_get_property;
166
167   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU,
168       g_param_spec_uint ("mtu", "MTU",
169           "Maximum size of one packet",
170           28, G_MAXUINT, DEFAULT_MTU,
171           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
172   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
173       g_param_spec_uint ("pt", "payload type",
174           "The payload type of the packets", 0, 0x80, DEFAULT_PT,
175           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
176   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
177       g_param_spec_uint ("ssrc", "SSRC",
178           "The SSRC of the packets (default == random)", 0, G_MAXUINT32,
179           DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
180   g_object_class_install_property (G_OBJECT_CLASS (klass),
181       PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset",
182           "Timestamp Offset",
183           "Offset to add to all outgoing timestamps (default = random)", 0,
184           G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET,
185           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
186   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
187       g_param_spec_int ("seqnum-offset", "Sequence number Offset",
188           "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16,
189           DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
190   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME,
191       g_param_spec_int64 ("max-ptime", "Max packet time",
192           "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)",
193           -1, G_MAXINT64, DEFAULT_MAX_PTIME,
194           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
195   /**
196    * GstBaseRTPAudioPayload:min-ptime:
197    *
198    * Minimum duration of the packet data in ns (can't go above MTU)
199    *
200    * Since: 0.10.13
201    **/
202   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME,
203       g_param_spec_int64 ("min-ptime", "Min packet time",
204           "Minimum duration of the packet data in ns (can't go above MTU)",
205           0, G_MAXINT64, DEFAULT_MIN_PTIME,
206           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
207
208   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
209       g_param_spec_uint ("timestamp", "Timestamp",
210           "The RTP timestamp of the last processed packet",
211           0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
212   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
213       g_param_spec_uint ("seqnum", "Sequence number",
214           "The RTP sequence number of the last processed packet",
215           0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
216
217   /**
218    * GstBaseRTPAudioPayload:perfect-rtptime:
219    *
220    * Try to use the offset fields to generate perfect RTP timestamps. when this
221    * option is disabled, RTP timestamps are generated from the GStreamer
222    * timestamps, which could result in RTP timestamps that don't increment with
223    * the amount of data in the packet.
224    *
225    * Since: 0.10.25
226    */
227   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PERFECT_RTPTIME,
228       g_param_spec_boolean ("perfect-rtptime", "Perfect RTP Time",
229           "Generate perfect RTP timestamps when possible",
230           DEFAULT_PERFECT_RTPTIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
231   /**
232    * GstBaseRTPAudioPayload:ptime-multiple:
233    *
234    * Force buffers to be multiples of this duration in ns (0 disables)
235    *
236    * Since: 0.10.29
237    **/
238   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PTIME_MULTIPLE,
239       g_param_spec_int64 ("ptime-multiple", "Packet time multiple",
240           "Force buffers to be multiples of this duration in ns (0 disables)",
241           0, G_MAXINT64, DEFAULT_PTIME_MULTIPLE,
242           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
243
244   gstelement_class->change_state = gst_basertppayload_change_state;
245
246   GST_DEBUG_CATEGORY_INIT (basertppayload_debug, "basertppayload", 0,
247       "Base class for RTP Payloaders");
248 }
249
250 static void
251 gst_basertppayload_init (GstBaseRTPPayload * basertppayload, gpointer g_class)
252 {
253   GstPadTemplate *templ;
254   GstBaseRTPPayloadPrivate *priv;
255
256   basertppayload->priv = priv =
257       GST_BASE_RTP_PAYLOAD_GET_PRIVATE (basertppayload);
258
259   templ =
260       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
261   g_return_if_fail (templ != NULL);
262
263   basertppayload->srcpad = gst_pad_new_from_template (templ, "src");
264   gst_element_add_pad (GST_ELEMENT (basertppayload), basertppayload->srcpad);
265
266   templ =
267       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink");
268   g_return_if_fail (templ != NULL);
269
270   basertppayload->sinkpad = gst_pad_new_from_template (templ, "sink");
271   gst_pad_set_setcaps_function (basertppayload->sinkpad,
272       gst_basertppayload_sink_setcaps);
273   gst_pad_set_getcaps_function (basertppayload->sinkpad,
274       gst_basertppayload_sink_getcaps);
275   gst_pad_set_event_function (basertppayload->sinkpad,
276       gst_basertppayload_event);
277   gst_pad_set_chain_function (basertppayload->sinkpad,
278       gst_basertppayload_chain);
279   gst_element_add_pad (GST_ELEMENT (basertppayload), basertppayload->sinkpad);
280
281   basertppayload->seq_rand = g_rand_new_with_seed (g_random_int ());
282   basertppayload->ssrc_rand = g_rand_new_with_seed (g_random_int ());
283   basertppayload->ts_rand = g_rand_new_with_seed (g_random_int ());
284
285   basertppayload->mtu = DEFAULT_MTU;
286   basertppayload->pt = DEFAULT_PT;
287   basertppayload->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
288   basertppayload->ssrc = DEFAULT_SSRC;
289   basertppayload->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
290   priv->seqnum_offset_random = (basertppayload->seqnum_offset == -1);
291   priv->ts_offset_random = (basertppayload->ts_offset == -1);
292   priv->ssrc_random = (basertppayload->ssrc == -1);
293
294   basertppayload->max_ptime = DEFAULT_MAX_PTIME;
295   basertppayload->min_ptime = DEFAULT_MIN_PTIME;
296   basertppayload->priv->perfect_rtptime = DEFAULT_PERFECT_RTPTIME;
297   basertppayload->abidata.ABI.ptime_multiple = DEFAULT_PTIME_MULTIPLE;
298
299   basertppayload->media = NULL;
300   basertppayload->encoding_name = NULL;
301
302   basertppayload->clock_rate = 0;
303
304   basertppayload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
305   basertppayload->priv->prop_max_ptime = DEFAULT_MAX_PTIME;
306 }
307
308 static void
309 gst_basertppayload_finalize (GObject * object)
310 {
311   GstBaseRTPPayload *basertppayload;
312
313   basertppayload = GST_BASE_RTP_PAYLOAD (object);
314
315   g_rand_free (basertppayload->seq_rand);
316   basertppayload->seq_rand = NULL;
317   g_rand_free (basertppayload->ssrc_rand);
318   basertppayload->ssrc_rand = NULL;
319   g_rand_free (basertppayload->ts_rand);
320   basertppayload->ts_rand = NULL;
321
322   g_free (basertppayload->media);
323   basertppayload->media = NULL;
324   g_free (basertppayload->encoding_name);
325   basertppayload->encoding_name = NULL;
326
327   G_OBJECT_CLASS (parent_class)->finalize (object);
328 }
329
330 static gboolean
331 gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps)
332 {
333   GstBaseRTPPayload *basertppayload;
334   GstBaseRTPPayloadClass *basertppayload_class;
335   gboolean ret = TRUE;
336
337   GST_DEBUG_OBJECT (pad, "setting caps %" GST_PTR_FORMAT, caps);
338   basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad));
339   basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload);
340
341   if (basertppayload_class->set_caps)
342     ret = basertppayload_class->set_caps (basertppayload, caps);
343
344   gst_object_unref (basertppayload);
345
346   return ret;
347 }
348
349 static GstCaps *
350 gst_basertppayload_sink_getcaps (GstPad * pad)
351 {
352   GstBaseRTPPayload *basertppayload;
353   GstBaseRTPPayloadClass *basertppayload_class;
354   GstCaps *caps = NULL;
355
356   GST_DEBUG_OBJECT (pad, "getting caps");
357
358   basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad));
359   basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload);
360
361   if (basertppayload_class->get_caps)
362     caps = basertppayload_class->get_caps (basertppayload, pad);
363
364   if (!caps) {
365     caps = GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
366     GST_DEBUG_OBJECT (pad,
367         "using pad template %p with caps %p %" GST_PTR_FORMAT,
368         GST_PAD_PAD_TEMPLATE (pad), caps, caps);
369
370     caps = gst_caps_ref (caps);
371   }
372
373   gst_object_unref (basertppayload);
374
375   return caps;
376 }
377
378 static gboolean
379 gst_basertppayload_event (GstPad * pad, GstEvent * event)
380 {
381   GstBaseRTPPayload *basertppayload;
382   GstBaseRTPPayloadClass *basertppayload_class;
383   gboolean res;
384
385   basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad));
386   if (G_UNLIKELY (basertppayload == NULL)) {
387     gst_event_unref (event);
388     return FALSE;
389   }
390   basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload);
391
392   if (basertppayload_class->handle_event) {
393     res = basertppayload_class->handle_event (pad, event);
394     if (res)
395       goto done;
396   }
397
398   switch (GST_EVENT_TYPE (event)) {
399     case GST_EVENT_FLUSH_START:
400       res = gst_pad_event_default (pad, event);
401       break;
402     case GST_EVENT_FLUSH_STOP:
403       res = gst_pad_event_default (pad, event);
404       gst_segment_init (&basertppayload->segment, GST_FORMAT_UNDEFINED);
405       break;
406     case GST_EVENT_NEWSEGMENT:
407     {
408       gboolean update;
409       gdouble rate, arate;
410       GstFormat fmt;
411       gint64 start, stop, position;
412       GstSegment *segment;
413
414       segment = &basertppayload->segment;
415
416       gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt,
417           &start, &stop, &position);
418       gst_segment_set_newsegment_full (segment, update, rate, arate, fmt, start,
419           stop, position);
420
421       GST_DEBUG_OBJECT (basertppayload,
422           "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
423           "format %d, "
424           "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
425           G_GINT64_FORMAT ", accum %" G_GINT64_FORMAT, update, rate, arate,
426           segment->format, segment->start, segment->stop, segment->time,
427           segment->accum);
428       /* fallthrough */
429     }
430     default:
431       res = gst_pad_event_default (pad, event);
432       break;
433   }
434
435 done:
436   gst_object_unref (basertppayload);
437
438   return res;
439 }
440
441
442 static GstFlowReturn
443 gst_basertppayload_chain (GstPad * pad, GstBuffer * buffer)
444 {
445   GstBaseRTPPayload *basertppayload;
446   GstBaseRTPPayloadClass *basertppayload_class;
447   GstFlowReturn ret;
448
449   basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad));
450   basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload);
451
452   if (!basertppayload_class->handle_buffer)
453     goto no_function;
454
455   ret = basertppayload_class->handle_buffer (basertppayload, buffer);
456
457   gst_object_unref (basertppayload);
458
459   return ret;
460
461   /* ERRORS */
462 no_function:
463   {
464     GST_ELEMENT_ERROR (basertppayload, STREAM, NOT_IMPLEMENTED, (NULL),
465         ("subclass did not implement handle_buffer function"));
466     gst_object_unref (basertppayload);
467     gst_buffer_unref (buffer);
468     return GST_FLOW_ERROR;
469   }
470 }
471
472 /**
473  * gst_basertppayload_set_options:
474  * @payload: a #GstBaseRTPPayload
475  * @media: the media type (typically "audio" or "video")
476  * @dynamic: if the payload type is dynamic
477  * @encoding_name: the encoding name
478  * @clock_rate: the clock rate of the media
479  *
480  * Set the rtp options of the payloader. These options will be set in the caps
481  * of the payloader. Subclasses must call this method before calling
482  * gst_basertppayload_push() or gst_basertppayload_set_outcaps().
483  */
484 void
485 gst_basertppayload_set_options (GstBaseRTPPayload * payload,
486     const gchar * media, gboolean dynamic, const gchar * encoding_name,
487     guint32 clock_rate)
488 {
489   g_return_if_fail (payload != NULL);
490   g_return_if_fail (clock_rate != 0);
491
492   g_free (payload->media);
493   payload->media = g_strdup (media);
494   payload->dynamic = dynamic;
495   g_free (payload->encoding_name);
496   payload->encoding_name = g_strdup (encoding_name);
497   payload->clock_rate = clock_rate;
498 }
499
500 static gboolean
501 copy_fixed (GQuark field_id, const GValue * value, GstStructure * dest)
502 {
503   if (gst_value_is_fixed (value)) {
504     gst_structure_id_set_value (dest, field_id, value);
505   }
506   return TRUE;
507 }
508
509 static void
510 update_max_ptime (GstBaseRTPPayload * basertppayload)
511 {
512   if (basertppayload->priv->caps_max_ptime != -1 &&
513       basertppayload->priv->prop_max_ptime != -1)
514     basertppayload->max_ptime = MIN (basertppayload->priv->caps_max_ptime,
515         basertppayload->priv->prop_max_ptime);
516   else if (basertppayload->priv->caps_max_ptime != -1)
517     basertppayload->max_ptime = basertppayload->priv->caps_max_ptime;
518   else if (basertppayload->priv->prop_max_ptime != -1)
519     basertppayload->max_ptime = basertppayload->priv->prop_max_ptime;
520   else
521     basertppayload->max_ptime = DEFAULT_MAX_PTIME;
522 }
523
524 /**
525  * gst_basertppayload_set_outcaps:
526  * @payload: a #GstBaseRTPPayload
527  * @fieldname: the first field name or %NULL
528  * @...: field values
529  *
530  * Configure the output caps with the optional parameters.
531  *
532  * Variable arguments should be in the form field name, field type
533  * (as a GType), value(s).  The last variable argument should be NULL.
534  *
535  * Returns: %TRUE if the caps could be set.
536  */
537 gboolean
538 gst_basertppayload_set_outcaps (GstBaseRTPPayload * payload,
539     const gchar * fieldname, ...)
540 {
541   GstCaps *srccaps, *peercaps;
542   gboolean res;
543
544   /* fill in the defaults, their properties cannot be negotiated. */
545   srccaps = gst_caps_new_simple ("application/x-rtp",
546       "media", G_TYPE_STRING, payload->media,
547       "clock-rate", G_TYPE_INT, payload->clock_rate,
548       "encoding-name", G_TYPE_STRING, payload->encoding_name, NULL);
549
550   GST_DEBUG_OBJECT (payload, "defaults: %" GST_PTR_FORMAT, srccaps);
551
552   if (fieldname) {
553     va_list varargs;
554
555     /* override with custom properties */
556     va_start (varargs, fieldname);
557     gst_caps_set_simple_valist (srccaps, fieldname, varargs);
558     va_end (varargs);
559
560     GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps);
561   }
562
563   payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
564   payload->abidata.ABI.ptime = 0;
565
566   /* the peer caps can override some of the defaults */
567   peercaps = gst_pad_peer_get_caps (payload->srcpad);
568   if (peercaps == NULL) {
569     /* no peer caps, just add the other properties */
570     gst_caps_set_simple (srccaps,
571         "payload", G_TYPE_INT, GST_BASE_RTP_PAYLOAD_PT (payload),
572         "ssrc", G_TYPE_UINT, payload->current_ssrc,
573         "clock-base", G_TYPE_UINT, payload->ts_base,
574         "seqnum-base", G_TYPE_UINT, payload->seqnum_base, NULL);
575
576     GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps);
577   } else {
578     GstCaps *temp;
579     GstStructure *s, *d;
580     const GValue *value;
581     gint pt;
582     guint max_ptime, ptime;
583
584     /* peer provides caps we can use to fixate, intersect. This always returns a
585      * writable caps. */
586     temp = gst_caps_intersect (srccaps, peercaps);
587     gst_caps_unref (srccaps);
588     gst_caps_unref (peercaps);
589
590     if (gst_caps_is_empty (temp)) {
591       gst_caps_unref (temp);
592       return FALSE;
593     }
594
595     /* now fixate, start by taking the first caps */
596     gst_caps_truncate (temp);
597
598     /* get first structure */
599     s = gst_caps_get_structure (temp, 0);
600
601     if (gst_structure_get_uint (s, "maxptime", &max_ptime))
602       payload->priv->caps_max_ptime = max_ptime * GST_MSECOND;
603
604     if (gst_structure_get_uint (s, "ptime", &ptime))
605       payload->abidata.ABI.ptime = ptime * GST_MSECOND;
606
607     if (gst_structure_get_int (s, "payload", &pt)) {
608       /* use peer pt */
609       GST_BASE_RTP_PAYLOAD_PT (payload) = pt;
610       GST_LOG_OBJECT (payload, "using peer pt %d", pt);
611     } else {
612       if (gst_structure_has_field (s, "payload")) {
613         /* can only fixate if there is a field */
614         gst_structure_fixate_field_nearest_int (s, "payload",
615             GST_BASE_RTP_PAYLOAD_PT (payload));
616         gst_structure_get_int (s, "payload", &pt);
617         GST_LOG_OBJECT (payload, "using peer pt %d", pt);
618       } else {
619         /* no pt field, use the internal pt */
620         pt = GST_BASE_RTP_PAYLOAD_PT (payload);
621         gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
622         GST_LOG_OBJECT (payload, "using internal pt %d", pt);
623       }
624     }
625
626     if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) {
627       value = gst_structure_get_value (s, "ssrc");
628       payload->current_ssrc = g_value_get_uint (value);
629       GST_LOG_OBJECT (payload, "using peer ssrc %08x", payload->current_ssrc);
630     } else {
631       /* FIXME, fixate_nearest_uint would be even better */
632       gst_structure_set (s, "ssrc", G_TYPE_UINT, payload->current_ssrc, NULL);
633       GST_LOG_OBJECT (payload, "using internal ssrc %08x",
634           payload->current_ssrc);
635     }
636
637     if (gst_structure_has_field_typed (s, "clock-base", G_TYPE_UINT)) {
638       value = gst_structure_get_value (s, "clock-base");
639       payload->ts_base = g_value_get_uint (value);
640       GST_LOG_OBJECT (payload, "using peer clock-base %u", payload->ts_base);
641     } else {
642       /* FIXME, fixate_nearest_uint would be even better */
643       gst_structure_set (s, "clock-base", G_TYPE_UINT, payload->ts_base, NULL);
644       GST_LOG_OBJECT (payload, "using internal clock-base %u",
645           payload->ts_base);
646     }
647     if (gst_structure_has_field_typed (s, "seqnum-base", G_TYPE_UINT)) {
648       value = gst_structure_get_value (s, "seqnum-base");
649       payload->seqnum_base = g_value_get_uint (value);
650       GST_LOG_OBJECT (payload, "using peer seqnum-base %u",
651           payload->seqnum_base);
652     } else {
653       /* FIXME, fixate_nearest_uint would be even better */
654       gst_structure_set (s, "seqnum-base", G_TYPE_UINT, payload->seqnum_base,
655           NULL);
656       GST_LOG_OBJECT (payload, "using internal seqnum-base %u",
657           payload->seqnum_base);
658     }
659
660     /* make the target caps by copying over all the fixed caps, removing the
661      * unfixed caps. */
662     srccaps = gst_caps_new_simple (gst_structure_get_name (s), NULL);
663     d = gst_caps_get_structure (srccaps, 0);
664
665     gst_structure_foreach (s, (GstStructureForeachFunc) copy_fixed, d);
666
667     gst_caps_unref (temp);
668
669     GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
670   }
671
672   update_max_ptime (payload);
673
674   res = gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps);
675   gst_caps_unref (srccaps);
676
677   return res;
678 }
679
680 /**
681  * gst_basertppayload_is_filled:
682  * @payload: a #GstBaseRTPPayload
683  * @size: the size of the packet
684  * @duration: the duration of the packet
685  *
686  * Check if the packet with @size and @duration would exceed the configured
687  * maximum size.
688  *
689  * Returns: %TRUE if the packet of @size and @duration would exceed the
690  * configured MTU or max_ptime.
691  */
692 gboolean
693 gst_basertppayload_is_filled (GstBaseRTPPayload * payload,
694     guint size, GstClockTime duration)
695 {
696   if (size > payload->mtu)
697     return TRUE;
698
699   if (payload->max_ptime != -1 && duration >= payload->max_ptime)
700     return TRUE;
701
702   return FALSE;
703 }
704
705 typedef struct
706 {
707   GstBaseRTPPayload *payload;
708   guint32 ssrc;
709   guint16 seqnum;
710   guint8 pt;
711   GstCaps *caps;
712   GstClockTime timestamp;
713   guint64 offset;
714   guint32 rtptime;
715 } HeaderData;
716
717 static GstBufferListItem
718 find_timestamp (GstBuffer ** buffer, guint group, guint idx, HeaderData * data)
719 {
720   data->timestamp = GST_BUFFER_TIMESTAMP (*buffer);
721   data->offset = GST_BUFFER_OFFSET (*buffer);
722
723   /* stop when we find a timestamp. We take whatever offset is associated with
724    * the timestamp (if any) to do perfect timestamps when we need to. */
725   if (data->timestamp != -1)
726     return GST_BUFFER_LIST_END;
727   else
728     return GST_BUFFER_LIST_CONTINUE;
729 }
730
731 static GstBufferListItem
732 set_headers (GstBuffer ** buffer, guint group, guint idx, HeaderData * data)
733 {
734   gst_rtp_buffer_set_ssrc (*buffer, data->ssrc);
735   gst_rtp_buffer_set_payload_type (*buffer, data->pt);
736   gst_rtp_buffer_set_seq (*buffer, data->seqnum);
737   gst_rtp_buffer_set_timestamp (*buffer, data->rtptime);
738   gst_buffer_set_caps (*buffer, data->caps);
739   /* increment the seqnum for each buffer */
740   data->seqnum++;
741
742   return GST_BUFFER_LIST_SKIP_GROUP;
743 }
744
745 /* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer
746  * before the buffer is pushed. */
747 static GstFlowReturn
748 gst_basertppayload_prepare_push (GstBaseRTPPayload * payload,
749     gpointer obj, gboolean is_list)
750 {
751   GstBaseRTPPayloadPrivate *priv;
752   HeaderData data;
753
754   if (payload->clock_rate == 0)
755     goto no_rate;
756
757   priv = payload->priv;
758
759   /* update first, so that the property is set to the last
760    * seqnum pushed */
761   payload->seqnum = priv->next_seqnum;
762
763   /* fill in the fields we want to set on all headers */
764   data.payload = payload;
765   data.seqnum = payload->seqnum;
766   data.ssrc = payload->current_ssrc;
767   data.pt = payload->pt;
768   data.caps = GST_PAD_CAPS (payload->srcpad);
769
770   /* find the first buffer with a timestamp */
771   if (is_list) {
772     data.timestamp = -1;
773     data.offset = GST_BUFFER_OFFSET_NONE;
774     gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj),
775         (GstBufferListFunc) find_timestamp, &data);
776   } else {
777     data.timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (obj));
778     data.offset = GST_BUFFER_OFFSET (GST_BUFFER_CAST (obj));
779   }
780
781   /* convert to RTP time */
782   if (priv->perfect_rtptime && data.offset != GST_BUFFER_OFFSET_NONE) {
783     /* if we have an offset, use that for making an RTP timestamp */
784     data.rtptime = payload->ts_base + data.offset;
785     GST_LOG_OBJECT (payload,
786         "Using offset %" G_GUINT64_FORMAT " for RTP timestamp", data.offset);
787   } else if (GST_CLOCK_TIME_IS_VALID (data.timestamp)) {
788     gint64 rtime;
789
790     /* no offset, use the gstreamer timestamp */
791     rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
792         data.timestamp);
793
794     if (rtime == -1) {
795       GST_LOG_OBJECT (payload, "Clipped timestamp, using base RTP timestamp");
796       rtime = 0;
797     } else {
798       GST_LOG_OBJECT (payload,
799           "Using running_time %" GST_TIME_FORMAT " for RTP timestamp",
800           GST_TIME_ARGS (rtime));
801       rtime =
802           gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND);
803     }
804     /* add running_time in clock-rate units to the base timestamp */
805     data.rtptime = payload->ts_base + rtime;
806   } else {
807     GST_LOG_OBJECT (payload,
808         "Using previous RTP timestamp %" G_GUINT32_FORMAT, payload->timestamp);
809     /* no timestamp to convert, take previous timestamp */
810     data.rtptime = payload->timestamp;
811   }
812
813   /* set ssrc, payload type, seq number, caps and rtptime */
814   if (is_list) {
815     gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj),
816         (GstBufferListFunc) set_headers, &data);
817   } else {
818     GstBuffer *buf = GST_BUFFER_CAST (obj);
819     set_headers (&buf, 0, 0, &data);
820   }
821
822   priv->next_seqnum = data.seqnum;
823   payload->timestamp = data.rtptime;
824
825   GST_LOG_OBJECT (payload,
826       "Preparing to push packet with size %d, seq=%d, rtptime=%u, timestamp %"
827       GST_TIME_FORMAT, (is_list) ? -1 :
828       GST_BUFFER_SIZE (GST_BUFFER (obj)), payload->seqnum, data.rtptime,
829       GST_TIME_ARGS (data.timestamp));
830
831   if (g_atomic_int_compare_and_exchange (&payload->
832           priv->notified_first_timestamp, 1, 0)) {
833     g_object_notify (G_OBJECT (payload), "timestamp");
834     g_object_notify (G_OBJECT (payload), "seqnum");
835   }
836
837   return GST_FLOW_OK;
838
839   /* ERRORS */
840 no_rate:
841   {
842     GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
843         ("subclass did not specify clock-rate"));
844     return GST_FLOW_ERROR;
845   }
846 }
847
848 /**
849  * gst_basertppayload_push_list:
850  * @payload: a #GstBaseRTPPayload
851  * @list: a #GstBufferList
852  *
853  * Push @list to the peer element of the payloader. The SSRC, payload type,
854  * seqnum and timestamp of the RTP buffer will be updated first.
855  *
856  * This function takes ownership of @list.
857  *
858  * Returns: a #GstFlowReturn.
859  *
860  * Since: 0.10.24
861  */
862 GstFlowReturn
863 gst_basertppayload_push_list (GstBaseRTPPayload * payload, GstBufferList * list)
864 {
865   GstFlowReturn res;
866
867   res = gst_basertppayload_prepare_push (payload, list, TRUE);
868
869   if (G_LIKELY (res == GST_FLOW_OK))
870     res = gst_pad_push_list (payload->srcpad, list);
871   else
872     gst_buffer_list_unref (list);
873
874   return res;
875 }
876
877 /**
878  * gst_basertppayload_push:
879  * @payload: a #GstBaseRTPPayload
880  * @buffer: a #GstBuffer
881  *
882  * Push @buffer to the peer element of the payloader. The SSRC, payload type,
883  * seqnum and timestamp of the RTP buffer will be updated first.
884  *
885  * This function takes ownership of @buffer.
886  *
887  * Returns: a #GstFlowReturn.
888  */
889 GstFlowReturn
890 gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer)
891 {
892   GstFlowReturn res;
893
894   res = gst_basertppayload_prepare_push (payload, buffer, FALSE);
895
896   if (G_LIKELY (res == GST_FLOW_OK))
897     res = gst_pad_push (payload->srcpad, buffer);
898   else
899     gst_buffer_unref (buffer);
900
901   return res;
902 }
903
904 static void
905 gst_basertppayload_set_property (GObject * object, guint prop_id,
906     const GValue * value, GParamSpec * pspec)
907 {
908   GstBaseRTPPayload *basertppayload;
909   GstBaseRTPPayloadPrivate *priv;
910   gint64 val;
911
912   basertppayload = GST_BASE_RTP_PAYLOAD (object);
913   priv = basertppayload->priv;
914
915   switch (prop_id) {
916     case PROP_MTU:
917       basertppayload->mtu = g_value_get_uint (value);
918       break;
919     case PROP_PT:
920       basertppayload->pt = g_value_get_uint (value);
921       break;
922     case PROP_SSRC:
923       val = g_value_get_uint (value);
924       basertppayload->ssrc = val;
925       priv->ssrc_random = FALSE;
926       break;
927     case PROP_TIMESTAMP_OFFSET:
928       val = g_value_get_uint (value);
929       basertppayload->ts_offset = val;
930       priv->ts_offset_random = FALSE;
931       break;
932     case PROP_SEQNUM_OFFSET:
933       val = g_value_get_int (value);
934       basertppayload->seqnum_offset = val;
935       priv->seqnum_offset_random = (val == -1);
936       GST_DEBUG_OBJECT (basertppayload, "seqnum offset 0x%04x, random %d",
937           basertppayload->seqnum_offset, priv->seqnum_offset_random);
938       break;
939     case PROP_MAX_PTIME:
940       basertppayload->priv->prop_max_ptime = g_value_get_int64 (value);
941       update_max_ptime (basertppayload);
942       break;
943     case PROP_MIN_PTIME:
944       basertppayload->min_ptime = g_value_get_int64 (value);
945       break;
946     case PROP_PERFECT_RTPTIME:
947       priv->perfect_rtptime = g_value_get_boolean (value);
948       break;
949     case PROP_PTIME_MULTIPLE:
950       basertppayload->abidata.ABI.ptime_multiple = g_value_get_int64 (value);
951       break;
952     default:
953       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
954       break;
955   }
956 }
957
958 static void
959 gst_basertppayload_get_property (GObject * object, guint prop_id,
960     GValue * value, GParamSpec * pspec)
961 {
962   GstBaseRTPPayload *basertppayload;
963   GstBaseRTPPayloadPrivate *priv;
964
965   basertppayload = GST_BASE_RTP_PAYLOAD (object);
966   priv = basertppayload->priv;
967
968   switch (prop_id) {
969     case PROP_MTU:
970       g_value_set_uint (value, basertppayload->mtu);
971       break;
972     case PROP_PT:
973       g_value_set_uint (value, basertppayload->pt);
974       break;
975     case PROP_SSRC:
976       if (priv->ssrc_random)
977         g_value_set_uint (value, -1);
978       else
979         g_value_set_uint (value, basertppayload->ssrc);
980       break;
981     case PROP_TIMESTAMP_OFFSET:
982       if (priv->ts_offset_random)
983         g_value_set_uint (value, -1);
984       else
985         g_value_set_uint (value, (guint32) basertppayload->ts_offset);
986       break;
987     case PROP_SEQNUM_OFFSET:
988       if (priv->seqnum_offset_random)
989         g_value_set_int (value, -1);
990       else
991         g_value_set_int (value, (guint16) basertppayload->seqnum_offset);
992       break;
993     case PROP_MAX_PTIME:
994       g_value_set_int64 (value, basertppayload->max_ptime);
995       break;
996     case PROP_MIN_PTIME:
997       g_value_set_int64 (value, basertppayload->min_ptime);
998       break;
999     case PROP_TIMESTAMP:
1000       g_value_set_uint (value, basertppayload->timestamp);
1001       break;
1002     case PROP_SEQNUM:
1003       g_value_set_uint (value, basertppayload->seqnum);
1004       break;
1005     case PROP_PERFECT_RTPTIME:
1006       g_value_set_boolean (value, priv->perfect_rtptime);
1007       break;
1008     case PROP_PTIME_MULTIPLE:
1009       g_value_set_int64 (value, basertppayload->abidata.ABI.ptime_multiple);
1010       break;
1011     default:
1012       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1013       break;
1014   }
1015 }
1016
1017 static GstStateChangeReturn
1018 gst_basertppayload_change_state (GstElement * element,
1019     GstStateChange transition)
1020 {
1021   GstBaseRTPPayload *basertppayload;
1022   GstBaseRTPPayloadPrivate *priv;
1023   GstStateChangeReturn ret;
1024
1025   basertppayload = GST_BASE_RTP_PAYLOAD (element);
1026   priv = basertppayload->priv;
1027
1028   switch (transition) {
1029     case GST_STATE_CHANGE_NULL_TO_READY:
1030       break;
1031     case GST_STATE_CHANGE_READY_TO_PAUSED:
1032       gst_segment_init (&basertppayload->segment, GST_FORMAT_UNDEFINED);
1033
1034       if (priv->seqnum_offset_random)
1035         basertppayload->seqnum_base = g_random_int_range (0, G_MAXUINT16);
1036       else
1037         basertppayload->seqnum_base = basertppayload->seqnum_offset;
1038       priv->next_seqnum = basertppayload->seqnum_base;
1039       basertppayload->seqnum = basertppayload->seqnum_base;
1040
1041       if (priv->ssrc_random)
1042         basertppayload->current_ssrc = g_random_int ();
1043       else
1044         basertppayload->current_ssrc = basertppayload->ssrc;
1045
1046       if (priv->ts_offset_random)
1047         basertppayload->ts_base = g_random_int ();
1048       else
1049         basertppayload->ts_base = basertppayload->ts_offset;
1050       basertppayload->timestamp = basertppayload->ts_base;
1051       g_atomic_int_set (&basertppayload->priv->notified_first_timestamp, 1);
1052       break;
1053     default:
1054       break;
1055   }
1056
1057   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1058
1059   switch (transition) {
1060     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1061       g_atomic_int_set (&basertppayload->priv->notified_first_timestamp, 1);
1062       break;
1063     case GST_STATE_CHANGE_READY_TO_NULL:
1064       break;
1065     default:
1066       break;
1067   }
1068   return ret;
1069 }