good:v4l2bufferpool: Add missed header file
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-base / gst-libs / gst / rtp / gstrtpbasedepayload.c
1 /* GStreamer
2  * Copyright (C) <2005> Philippe Khalaf <burger@speedy.org>
3  * Copyright (C) <2005> Nokia Corporation <kai.vehmanen@nokia.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * SECTION:gstrtpbasedepayload
23  * @title: GstRTPBaseDepayload
24  * @short_description: Base class for RTP depayloader
25  *
26  * Provides a base class for RTP depayloaders
27  */
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "gstrtpbasedepayload.h"
33 #include "gstrtpmeta.h"
34 #include "gstrtphdrext.h"
35
36 GST_DEBUG_CATEGORY_STATIC (rtpbasedepayload_debug);
37 #define GST_CAT_DEFAULT (rtpbasedepayload_debug)
38
39 static GstStaticCaps ntp_reference_timestamp_caps =
40 GST_STATIC_CAPS ("timestamp/x-ntp");
41
42 struct _GstRTPBaseDepayloadPrivate
43 {
44   GstClockTime npt_start;
45   GstClockTime npt_stop;
46   gdouble play_speed;
47   gdouble play_scale;
48   guint clock_base;
49   gboolean onvif_mode;
50
51   gboolean discont;
52   GstClockTime pts;
53   GstClockTime dts;
54   GstClockTime duration;
55
56   GstClockTime ref_ts;
57
58   guint32 last_ssrc;
59   guint32 last_seqnum;
60   guint32 last_rtptime;
61   guint32 next_seqnum;
62   gint max_reorder;
63   gboolean auto_hdr_ext;
64
65   gboolean negotiated;
66
67   GstCaps *last_caps;
68   GstEvent *segment_event;
69   guint32 segment_seqnum;       /* Note: this is a GstEvent seqnum */
70
71   gboolean source_info;
72   GstBuffer *input_buffer;
73
74   GstFlowReturn process_flow_ret;
75
76   /* array of GstRTPHeaderExtension's * */
77   GPtrArray *header_exts;
78 };
79
80 /* Filter signals and args */
81 enum
82 {
83   SIGNAL_0,
84   SIGNAL_REQUEST_EXTENSION,
85   SIGNAL_ADD_EXTENSION,
86   SIGNAL_CLEAR_EXTENSIONS,
87   LAST_SIGNAL
88 };
89
90 static guint gst_rtp_base_depayload_signals[LAST_SIGNAL] = { 0 };
91
92 #define DEFAULT_SOURCE_INFO FALSE
93 #define DEFAULT_MAX_REORDER 100
94 #define DEFAULT_AUTO_HEADER_EXTENSION TRUE
95
96 enum
97 {
98   PROP_0,
99   PROP_STATS,
100   PROP_SOURCE_INFO,
101   PROP_MAX_REORDER,
102   PROP_AUTO_HEADER_EXTENSION,
103   PROP_LAST
104 };
105
106 static void gst_rtp_base_depayload_finalize (GObject * object);
107 static void gst_rtp_base_depayload_set_property (GObject * object,
108     guint prop_id, const GValue * value, GParamSpec * pspec);
109 static void gst_rtp_base_depayload_get_property (GObject * object,
110     guint prop_id, GValue * value, GParamSpec * pspec);
111
112 static GstFlowReturn gst_rtp_base_depayload_chain (GstPad * pad,
113     GstObject * parent, GstBuffer * in);
114 static GstFlowReturn gst_rtp_base_depayload_chain_list (GstPad * pad,
115     GstObject * parent, GstBufferList * list);
116 static gboolean gst_rtp_base_depayload_handle_sink_event (GstPad * pad,
117     GstObject * parent, GstEvent * event);
118
119 static GstStateChangeReturn gst_rtp_base_depayload_change_state (GstElement *
120     element, GstStateChange transition);
121
122 static gboolean gst_rtp_base_depayload_packet_lost (GstRTPBaseDepayload *
123     filter, GstEvent * event);
124 static gboolean gst_rtp_base_depayload_handle_event (GstRTPBaseDepayload *
125     filter, GstEvent * event);
126
127 static GstElementClass *parent_class = NULL;
128 static gint private_offset = 0;
129
130 static void gst_rtp_base_depayload_class_init (GstRTPBaseDepayloadClass *
131     klass);
132 static void gst_rtp_base_depayload_init (GstRTPBaseDepayload * rtpbasepayload,
133     GstRTPBaseDepayloadClass * klass);
134 static GstEvent *create_segment_event (GstRTPBaseDepayload * filter,
135     guint rtptime, GstClockTime position);
136
137 static void gst_rtp_base_depayload_add_extension (GstRTPBaseDepayload *
138     rtpbasepayload, GstRTPHeaderExtension * ext);
139 static void gst_rtp_base_depayload_clear_extensions (GstRTPBaseDepayload *
140     rtpbasepayload);
141
142 GType
143 gst_rtp_base_depayload_get_type (void)
144 {
145   static GType rtp_base_depayload_type = 0;
146
147   if (g_once_init_enter ((gsize *) & rtp_base_depayload_type)) {
148     static const GTypeInfo rtp_base_depayload_info = {
149       sizeof (GstRTPBaseDepayloadClass),
150       NULL,
151       NULL,
152       (GClassInitFunc) gst_rtp_base_depayload_class_init,
153       NULL,
154       NULL,
155       sizeof (GstRTPBaseDepayload),
156       0,
157       (GInstanceInitFunc) gst_rtp_base_depayload_init,
158     };
159     GType _type;
160
161     _type = g_type_register_static (GST_TYPE_ELEMENT, "GstRTPBaseDepayload",
162         &rtp_base_depayload_info, G_TYPE_FLAG_ABSTRACT);
163
164     private_offset =
165         g_type_add_instance_private (_type,
166         sizeof (GstRTPBaseDepayloadPrivate));
167
168     g_once_init_leave ((gsize *) & rtp_base_depayload_type, _type);
169   }
170   return rtp_base_depayload_type;
171 }
172
173 static inline GstRTPBaseDepayloadPrivate *
174 gst_rtp_base_depayload_get_instance_private (GstRTPBaseDepayload * self)
175 {
176   return (G_STRUCT_MEMBER_P (self, private_offset));
177 }
178
179 static GstRTPHeaderExtension *
180 gst_rtp_base_depayload_request_extension_default (GstRTPBaseDepayload *
181     depayload, guint ext_id, const gchar * uri)
182 {
183   GstRTPHeaderExtension *ext = NULL;
184
185   if (!depayload->priv->auto_hdr_ext)
186     return NULL;
187
188   ext = gst_rtp_header_extension_create_from_uri (uri);
189   if (ext) {
190     GST_DEBUG_OBJECT (depayload,
191         "Automatically enabled extension %s for uri \'%s\'",
192         GST_ELEMENT_NAME (ext), uri);
193
194     gst_rtp_header_extension_set_id (ext, ext_id);
195   } else {
196     GST_DEBUG_OBJECT (depayload,
197         "Didn't find any extension implementing uri \'%s\'", uri);
198   }
199
200   return ext;
201 }
202
203 static gboolean
204 extension_accumulator (GSignalInvocationHint * ihint,
205     GValue * return_accu, const GValue * handler_return, gpointer data)
206 {
207   gpointer ext;
208
209   /* Call default handler if user callback didn't create the extension */
210   ext = g_value_get_object (handler_return);
211   if (!ext)
212     return TRUE;
213
214   g_value_set_object (return_accu, ext);
215   return FALSE;
216 }
217
218 static void
219 gst_rtp_base_depayload_class_init (GstRTPBaseDepayloadClass * klass)
220 {
221   GObjectClass *gobject_class;
222   GstElementClass *gstelement_class;
223
224   gobject_class = G_OBJECT_CLASS (klass);
225   gstelement_class = (GstElementClass *) klass;
226   parent_class = g_type_class_peek_parent (klass);
227
228   if (private_offset != 0)
229     g_type_class_adjust_private_offset (klass, &private_offset);
230
231   gobject_class->finalize = gst_rtp_base_depayload_finalize;
232   gobject_class->set_property = gst_rtp_base_depayload_set_property;
233   gobject_class->get_property = gst_rtp_base_depayload_get_property;
234
235
236   /**
237    * GstRTPBaseDepayload:stats:
238    *
239    * Various depayloader statistics retrieved atomically (and are therefore
240    * synchroized with each other). This property return a GstStructure named
241    * application/x-rtp-depayload-stats containing the following fields relating to
242    * the last processed buffer and current state of the stream being depayloaded:
243    *
244    *   * `clock-rate`: #G_TYPE_UINT, clock-rate of the stream
245    *   * `npt-start`: #G_TYPE_UINT64, time of playback start
246    *   * `npt-stop`: #G_TYPE_UINT64, time of playback stop
247    *   * `play-speed`: #G_TYPE_DOUBLE, the playback speed
248    *   * `play-scale`: #G_TYPE_DOUBLE, the playback scale
249    *   * `running-time-dts`: #G_TYPE_UINT64, the last running-time of the
250    *      last DTS
251    *   * `running-time-pts`: #G_TYPE_UINT64, the last running-time of the
252    *      last PTS
253    *   * `seqnum`: #G_TYPE_UINT, the last seen seqnum
254    *   * `timestamp`: #G_TYPE_UINT, the last seen RTP timestamp
255    **/
256   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATS,
257       g_param_spec_boxed ("stats", "Statistics", "Various statistics",
258           GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
259
260   /**
261    * GstRTPBaseDepayload:source-info:
262    *
263    * Add RTP source information found in RTP header as meta to output buffer.
264    *
265    * Since: 1.16
266    **/
267   g_object_class_install_property (gobject_class, PROP_SOURCE_INFO,
268       g_param_spec_boolean ("source-info", "RTP source information",
269           "Add RTP source information as buffer meta",
270           DEFAULT_SOURCE_INFO, G_PARAM_READWRITE));
271
272   /**
273    * GstRTPBaseDepayload:max-reorder:
274    *
275    * Max seqnum reorder before the sender is assumed to have restarted.
276    *
277    * When max-reorder is set to 0 all reordered/duplicate packets are
278    * considered coming from a restarted sender.
279    *
280    * Since: 1.18
281    **/
282   g_object_class_install_property (gobject_class, PROP_MAX_REORDER,
283       g_param_spec_int ("max-reorder", "Max Reorder",
284           "Max seqnum reorder before assuming sender has restarted",
285           0, G_MAXINT, DEFAULT_MAX_REORDER, G_PARAM_READWRITE));
286
287   /**
288    * GstRTPBaseDepayload:auto-header-extension:
289    *
290    * If enabled, the depayloader will automatically try to enable all the
291    * RTP header extensions provided in the sink caps, saving the application
292    * the need to handle these extensions manually using the
293    * GstRTPBaseDepayload::request-extension: signal.
294    *
295    * Since: 1.20
296    */
297   g_object_class_install_property (G_OBJECT_CLASS (klass),
298       PROP_AUTO_HEADER_EXTENSION, g_param_spec_boolean ("auto-header-extension",
299           "Automatic RTP header extension",
300           "Whether RTP header extensions should be automatically enabled, if an implementation is available",
301           DEFAULT_AUTO_HEADER_EXTENSION,
302           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
303
304   /**
305    * GstRTPBaseDepayload::request-extension:
306    * @object: the #GstRTPBaseDepayload
307    * @ext_id: the extension id being requested
308    * @ext_uri: (nullable): the extension URI being requested
309    *
310    * The returned @ext must be configured with the correct @ext_id and with the
311    * necessary attributes as required by the extension implementation.
312    *
313    * Returns: (transfer full) (nullable): the #GstRTPHeaderExtension for @ext_id, or %NULL
314    *
315    * Since: 1.20
316    */
317   gst_rtp_base_depayload_signals[SIGNAL_REQUEST_EXTENSION] =
318       g_signal_new_class_handler ("request-extension",
319       G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
320       G_CALLBACK (gst_rtp_base_depayload_request_extension_default),
321       extension_accumulator, NULL, NULL,
322       GST_TYPE_RTP_HEADER_EXTENSION, 2, G_TYPE_UINT, G_TYPE_STRING);
323
324   /**
325    * GstRTPBaseDepayload::add-extension:
326    * @object: the #GstRTPBaseDepayload
327    * @ext: (transfer full): the #GstRTPHeaderExtension
328    *
329    * Add @ext as an extension for reading part of an RTP header extension from
330    * incoming RTP packets.
331    *
332    * Since: 1.20
333    */
334   gst_rtp_base_depayload_signals[SIGNAL_ADD_EXTENSION] =
335       g_signal_new_class_handler ("add-extension", G_TYPE_FROM_CLASS (klass),
336       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
337       G_CALLBACK (gst_rtp_base_depayload_add_extension), NULL, NULL, NULL,
338       G_TYPE_NONE, 1, GST_TYPE_RTP_HEADER_EXTENSION);
339
340   /**
341    * GstRTPBaseDepayload::clear-extensions:
342    * @object: the #GstRTPBaseDepayload
343    *
344    * Clear all RTP header extensions used by this depayloader.
345    *
346    * Since: 1.20
347    */
348   gst_rtp_base_depayload_signals[SIGNAL_CLEAR_EXTENSIONS] =
349       g_signal_new_class_handler ("clear-extensions", G_TYPE_FROM_CLASS (klass),
350       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
351       G_CALLBACK (gst_rtp_base_depayload_clear_extensions), NULL, NULL, NULL,
352       G_TYPE_NONE, 0);
353
354   gstelement_class->change_state = gst_rtp_base_depayload_change_state;
355
356   klass->packet_lost = gst_rtp_base_depayload_packet_lost;
357   klass->handle_event = gst_rtp_base_depayload_handle_event;
358
359   GST_DEBUG_CATEGORY_INIT (rtpbasedepayload_debug, "rtpbasedepayload", 0,
360       "Base class for RTP Depayloaders");
361 }
362
363 static void
364 gst_rtp_base_depayload_init (GstRTPBaseDepayload * filter,
365     GstRTPBaseDepayloadClass * klass)
366 {
367   GstPadTemplate *pad_template;
368   GstRTPBaseDepayloadPrivate *priv;
369
370   priv = gst_rtp_base_depayload_get_instance_private (filter);
371
372   filter->priv = priv;
373
374   GST_DEBUG_OBJECT (filter, "init");
375
376   pad_template =
377       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
378   g_return_if_fail (pad_template != NULL);
379   filter->sinkpad = gst_pad_new_from_template (pad_template, "sink");
380   gst_pad_set_chain_function (filter->sinkpad, gst_rtp_base_depayload_chain);
381   gst_pad_set_chain_list_function (filter->sinkpad,
382       gst_rtp_base_depayload_chain_list);
383   gst_pad_set_event_function (filter->sinkpad,
384       gst_rtp_base_depayload_handle_sink_event);
385   gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
386
387   pad_template =
388       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src");
389   g_return_if_fail (pad_template != NULL);
390   filter->srcpad = gst_pad_new_from_template (pad_template, "src");
391   gst_pad_use_fixed_caps (filter->srcpad);
392   gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
393
394   priv->npt_start = 0;
395   priv->npt_stop = -1;
396   priv->play_speed = 1.0;
397   priv->play_scale = 1.0;
398   priv->clock_base = -1;
399   priv->onvif_mode = FALSE;
400   priv->dts = -1;
401   priv->pts = -1;
402   priv->duration = -1;
403   priv->ref_ts = -1;
404   priv->source_info = DEFAULT_SOURCE_INFO;
405   priv->max_reorder = DEFAULT_MAX_REORDER;
406   priv->auto_hdr_ext = DEFAULT_AUTO_HEADER_EXTENSION;
407
408   gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED);
409
410   priv->header_exts =
411       g_ptr_array_new_with_free_func ((GDestroyNotify) gst_object_unref);
412 }
413
414 static void
415 gst_rtp_base_depayload_finalize (GObject * object)
416 {
417   GstRTPBaseDepayload *rtpbasedepayload = GST_RTP_BASE_DEPAYLOAD (object);
418
419   g_ptr_array_unref (rtpbasedepayload->priv->header_exts);
420   rtpbasedepayload->priv->header_exts = NULL;
421
422   G_OBJECT_CLASS (parent_class)->finalize (object);
423 }
424
425 static void
426 add_and_ref_item (GstRTPHeaderExtension * ext, GPtrArray * ret)
427 {
428   g_ptr_array_add (ret, gst_object_ref (ext));
429 }
430
431 static void
432 remove_item_from (GstRTPHeaderExtension * ext, GPtrArray * ret)
433 {
434   g_ptr_array_remove_fast (ret, ext);
435 }
436
437 static void
438 add_item_to (GstRTPHeaderExtension * ext, GPtrArray * ret)
439 {
440   g_ptr_array_add (ret, ext);
441 }
442
443 static gboolean
444 gst_rtp_base_depayload_setcaps (GstRTPBaseDepayload * filter, GstCaps * caps)
445 {
446   GstRTPBaseDepayloadClass *bclass;
447   GstRTPBaseDepayloadPrivate *priv;
448   gboolean res = TRUE;
449   GstStructure *caps_struct;
450   const GValue *value;
451
452   priv = filter->priv;
453
454   bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (filter);
455
456   GST_DEBUG_OBJECT (filter, "Set caps %" GST_PTR_FORMAT, caps);
457
458   if (priv->last_caps) {
459     if (gst_caps_is_equal (priv->last_caps, caps)) {
460       res = TRUE;
461       goto caps_not_changed;
462     } else {
463       gst_caps_unref (priv->last_caps);
464       priv->last_caps = NULL;
465     }
466   }
467
468   caps_struct = gst_caps_get_structure (caps, 0);
469
470   value = gst_structure_get_value (caps_struct, "onvif-mode");
471   if (value && G_VALUE_HOLDS_BOOLEAN (value))
472     priv->onvif_mode = g_value_get_boolean (value);
473   else
474     priv->onvif_mode = FALSE;
475   GST_DEBUG_OBJECT (filter, "Onvif mode: %d", priv->onvif_mode);
476
477   if (priv->onvif_mode)
478     filter->need_newsegment = FALSE;
479
480   /* get other values for newsegment */
481   value = gst_structure_get_value (caps_struct, "npt-start");
482   if (value && G_VALUE_HOLDS_UINT64 (value))
483     priv->npt_start = g_value_get_uint64 (value);
484   else
485     priv->npt_start = 0;
486   GST_DEBUG_OBJECT (filter, "NPT start %" G_GUINT64_FORMAT, priv->npt_start);
487
488   value = gst_structure_get_value (caps_struct, "npt-stop");
489   if (value && G_VALUE_HOLDS_UINT64 (value))
490     priv->npt_stop = g_value_get_uint64 (value);
491   else
492     priv->npt_stop = -1;
493
494   GST_DEBUG_OBJECT (filter, "NPT stop %" G_GUINT64_FORMAT, priv->npt_stop);
495
496   value = gst_structure_get_value (caps_struct, "play-speed");
497   if (value && G_VALUE_HOLDS_DOUBLE (value))
498     priv->play_speed = g_value_get_double (value);
499   else
500     priv->play_speed = 1.0;
501
502   value = gst_structure_get_value (caps_struct, "play-scale");
503   if (value && G_VALUE_HOLDS_DOUBLE (value))
504     priv->play_scale = g_value_get_double (value);
505   else
506     priv->play_scale = 1.0;
507
508   value = gst_structure_get_value (caps_struct, "clock-base");
509   if (value && G_VALUE_HOLDS_UINT (value))
510     priv->clock_base = g_value_get_uint (value);
511   else
512     priv->clock_base = -1;
513
514   {
515     /* ensure we have header extension implementations for the list in the
516      * caps */
517     guint i, j, n_fields = gst_structure_n_fields (caps_struct);
518     GPtrArray *header_exts = g_ptr_array_new_with_free_func (gst_object_unref);
519     GPtrArray *to_add = g_ptr_array_new ();
520     GPtrArray *to_remove = g_ptr_array_new ();
521
522     GST_OBJECT_LOCK (filter);
523     g_ptr_array_foreach (filter->priv->header_exts,
524         (GFunc) add_and_ref_item, header_exts);
525     GST_OBJECT_UNLOCK (filter);
526
527     for (i = 0; i < n_fields; i++) {
528       const gchar *field_name = gst_structure_nth_field_name (caps_struct, i);
529       if (g_str_has_prefix (field_name, "extmap-")) {
530         const GValue *val;
531         const gchar *uri = NULL;
532         gchar *nptr;
533         guint ext_id;
534         GstRTPHeaderExtension *ext = NULL;
535
536         errno = 0;
537         ext_id = g_ascii_strtoull (&field_name[strlen ("extmap-")], &nptr, 10);
538         if (errno != 0 || (ext_id == 0 && field_name == nptr)) {
539           GST_WARNING_OBJECT (filter, "could not parse id from %s", field_name);
540           res = FALSE;
541           goto ext_out;
542         }
543
544         val = gst_structure_get_value (caps_struct, field_name);
545         if (G_VALUE_HOLDS_STRING (val)) {
546           uri = g_value_get_string (val);
547         } else if (GST_VALUE_HOLDS_ARRAY (val)) {
548           /* the uri is the second value in the array */
549           const GValue *str = gst_value_array_get_value (val, 1);
550           if (G_VALUE_HOLDS_STRING (str)) {
551             uri = g_value_get_string (str);
552           }
553         }
554
555         if (!uri) {
556           GST_WARNING_OBJECT (filter, "could not get extmap uri for "
557               "field %s", field_name);
558           res = FALSE;
559           goto ext_out;
560         }
561
562         /* try to find if this extension mapping already exists */
563         for (j = 0; j < header_exts->len; j++) {
564           ext = g_ptr_array_index (header_exts, j);
565           if (gst_rtp_header_extension_get_id (ext) == ext_id) {
566             if (g_strcmp0 (uri, gst_rtp_header_extension_get_uri (ext)) == 0) {
567               /* still matching, we're good, set attributes from caps in case
568                * the caps have changed */
569               if (!gst_rtp_header_extension_set_attributes_from_caps (ext,
570                       caps)) {
571                 GST_WARNING_OBJECT (filter,
572                     "Failed to configure rtp header " "extension %"
573                     GST_PTR_FORMAT " attributes from caps %" GST_PTR_FORMAT,
574                     ext, caps);
575                 res = FALSE;
576                 goto ext_out;
577               }
578               break;
579             } else {
580               GST_DEBUG_OBJECT (filter, "extension id %u"
581                   "was replaced with a different extension uri "
582                   "original:\'%s' vs \'%s\'", ext_id,
583                   gst_rtp_header_extension_get_uri (ext), uri);
584               g_ptr_array_add (to_remove, ext);
585               ext = NULL;
586               break;
587             }
588           } else {
589             ext = NULL;
590           }
591         }
592
593         /* if no extension, attempt to request one */
594         if (!ext) {
595           GST_DEBUG_OBJECT (filter, "requesting extension for id %u"
596               " and uri %s", ext_id, uri);
597           g_signal_emit (filter,
598               gst_rtp_base_depayload_signals[SIGNAL_REQUEST_EXTENSION], 0,
599               ext_id, uri, &ext);
600           GST_DEBUG_OBJECT (filter, "request returned extension %p \'%s\' "
601               "for id %u and uri %s", ext,
602               ext ? GST_OBJECT_NAME (ext) : "", ext_id, uri);
603
604           /* We require the caller to set the appropriate extension if it's required */
605           if (ext && gst_rtp_header_extension_get_id (ext) != ext_id) {
606             g_warning ("\'request-extension\' signal provided an rtp header "
607                 "extension for uri \'%s\' that does not match the requested "
608                 "extension id %u", uri, ext_id);
609             gst_clear_object (&ext);
610           }
611
612           if (ext && !gst_rtp_header_extension_set_attributes_from_caps (ext,
613                   caps)) {
614             GST_WARNING_OBJECT (filter,
615                 "Failed to configure rtp header " "extension %"
616                 GST_PTR_FORMAT " attributes from caps %" GST_PTR_FORMAT,
617                 ext, caps);
618             res = FALSE;
619             g_clear_object (&ext);
620             goto ext_out;
621           }
622
623           if (ext)
624             g_ptr_array_add (to_add, ext);
625         }
626       }
627     }
628
629     /* Note: we intentionally don't remove extensions that are not listed
630      * in caps */
631
632     GST_OBJECT_LOCK (filter);
633     g_ptr_array_foreach (to_remove, (GFunc) remove_item_from,
634         filter->priv->header_exts);
635     g_ptr_array_foreach (to_add, (GFunc) add_item_to,
636         filter->priv->header_exts);
637     GST_OBJECT_UNLOCK (filter);
638
639   ext_out:
640     g_ptr_array_unref (to_add);
641     g_ptr_array_unref (to_remove);
642     g_ptr_array_unref (header_exts);
643
644     if (!res)
645       return res;
646   }
647
648   if (bclass->set_caps) {
649     res = bclass->set_caps (filter, caps);
650     if (!res) {
651       GST_WARNING_OBJECT (filter, "Subclass rejected caps %" GST_PTR_FORMAT,
652           caps);
653     }
654   } else {
655     res = TRUE;
656   }
657
658   priv->negotiated = res;
659
660   if (priv->negotiated)
661     priv->last_caps = gst_caps_ref (caps);
662
663   return res;
664
665 caps_not_changed:
666   {
667     GST_DEBUG_OBJECT (filter, "Caps did not change");
668     return res;
669   }
670 }
671
672 /* takes ownership of the input buffer */
673 static GstFlowReturn
674 gst_rtp_base_depayload_handle_buffer (GstRTPBaseDepayload * filter,
675     GstRTPBaseDepayloadClass * bclass, GstBuffer * in)
676 {
677   GstBuffer *(*process_rtp_packet_func) (GstRTPBaseDepayload * base,
678       GstRTPBuffer * rtp_buffer);
679   GstBuffer *(*process_func) (GstRTPBaseDepayload * base, GstBuffer * in);
680   GstRTPBaseDepayloadPrivate *priv;
681   GstBuffer *out_buf;
682   guint32 ssrc;
683   guint16 seqnum;
684   guint32 rtptime;
685   gboolean discont, buf_discont;
686   gint gap;
687   GstRTPBuffer rtp = { NULL };
688   GstReferenceTimestampMeta *meta;
689   GstCaps *ref_caps;
690
691   priv = filter->priv;
692   priv->process_flow_ret = GST_FLOW_OK;
693
694   process_func = bclass->process;
695   process_rtp_packet_func = bclass->process_rtp_packet;
696
697   /* we must have a setcaps first */
698   if (G_UNLIKELY (!priv->negotiated))
699     goto not_negotiated;
700
701   /* Check for duplicate reference timestamp metadata */
702   ref_caps = gst_static_caps_get (&ntp_reference_timestamp_caps);
703   meta = gst_buffer_get_reference_timestamp_meta (in, ref_caps);
704   gst_caps_unref (ref_caps);
705   if (meta) {
706     guint64 ref_ts = meta->timestamp;
707     if (ref_ts == priv->ref_ts) {
708       /* Drop the redundant/duplicate reference timstamp metadata */
709       in = gst_buffer_make_writable (in);
710       gst_buffer_remove_meta (in, GST_META_CAST (meta));
711     } else {
712       priv->ref_ts = ref_ts;
713     }
714   }
715
716   if (G_UNLIKELY (!gst_rtp_buffer_map (in, GST_MAP_READ, &rtp)))
717     goto invalid_buffer;
718
719   buf_discont = GST_BUFFER_IS_DISCONT (in);
720
721   priv->pts = GST_BUFFER_PTS (in);
722   priv->dts = GST_BUFFER_DTS (in);
723   priv->duration = GST_BUFFER_DURATION (in);
724
725   ssrc = gst_rtp_buffer_get_ssrc (&rtp);
726   seqnum = gst_rtp_buffer_get_seq (&rtp);
727   rtptime = gst_rtp_buffer_get_timestamp (&rtp);
728
729   priv->last_seqnum = seqnum;
730   priv->last_rtptime = rtptime;
731
732   discont = buf_discont;
733
734   GST_LOG_OBJECT (filter, "discont %d, seqnum %u, rtptime %u, pts %"
735       GST_TIME_FORMAT ", dts %" GST_TIME_FORMAT, buf_discont, seqnum, rtptime,
736       GST_TIME_ARGS (priv->pts), GST_TIME_ARGS (priv->dts));
737
738   /* Check seqnum. This is a very simple check that makes sure that the seqnums
739    * are strictly increasing, dropping anything that is out of the ordinary. We
740    * can only do this when the next_seqnum is known. */
741   if (G_LIKELY (priv->next_seqnum != -1)) {
742     if (ssrc != priv->last_ssrc) {
743       GST_LOG_OBJECT (filter,
744           "New ssrc %u (current ssrc %u), sender restarted",
745           ssrc, priv->last_ssrc);
746       discont = TRUE;
747     } else {
748       gap = gst_rtp_buffer_compare_seqnum (seqnum, priv->next_seqnum);
749
750       /* if we have no gap, all is fine */
751       if (G_UNLIKELY (gap != 0)) {
752         GST_LOG_OBJECT (filter, "got packet %u, expected %u, gap %d", seqnum,
753             priv->next_seqnum, gap);
754         if (gap < 0) {
755           /* seqnum > next_seqnum, we are missing some packets, this is always a
756            * DISCONT. */
757           GST_LOG_OBJECT (filter, "%d missing packets", gap);
758           discont = TRUE;
759         } else {
760           /* seqnum < next_seqnum, we have seen this packet before, have a
761            * reordered packet or the sender could be restarted. If the packet
762            * is not too old, we throw it away as a duplicate. Otherwise we
763            * mark discont and continue assuming the sender has restarted. See
764            * also RFC 4737. */
765           if (gap <= priv->max_reorder) {
766             GST_WARNING_OBJECT (filter, "got old packet %u, expected %u, "
767                 "gap %d <= max_reorder (%d), dropping!",
768                 seqnum, priv->next_seqnum, gap, priv->max_reorder);
769             goto dropping;
770           }
771           GST_WARNING_OBJECT (filter, "got old packet %u, expected %u, "
772               "marking discont", seqnum, priv->next_seqnum);
773           discont = TRUE;
774         }
775       }
776     }
777   }
778   priv->next_seqnum = (seqnum + 1) & 0xffff;
779   priv->last_ssrc = ssrc;
780
781   if (G_UNLIKELY (discont)) {
782     priv->discont = TRUE;
783     if (!buf_discont) {
784       gpointer old_inbuf = in;
785
786       /* we detected a seqnum discont but the buffer was not flagged with a discont,
787        * set the discont flag so that the subclass can throw away old data. */
788       GST_LOG_OBJECT (filter, "mark DISCONT on input buffer");
789       in = gst_buffer_make_writable (in);
790       GST_BUFFER_FLAG_SET (in, GST_BUFFER_FLAG_DISCONT);
791       /* depayloaders will check flag on rtpbuffer->buffer, so if the input
792        * buffer was not writable already we need to remap to make our
793        * newly-flagged buffer current on the rtpbuffer */
794       if (in != old_inbuf) {
795         gst_rtp_buffer_unmap (&rtp);
796         if (G_UNLIKELY (!gst_rtp_buffer_map (in, GST_MAP_READ, &rtp)))
797           goto invalid_buffer;
798       }
799     }
800   }
801
802   /* prepare segment event if needed */
803   if (filter->need_newsegment) {
804     priv->segment_event = create_segment_event (filter, rtptime,
805         GST_BUFFER_PTS (in));
806     filter->need_newsegment = FALSE;
807   }
808
809   priv->input_buffer = in;
810
811   if (process_rtp_packet_func != NULL) {
812     out_buf = process_rtp_packet_func (filter, &rtp);
813     gst_rtp_buffer_unmap (&rtp);
814   } else if (process_func != NULL) {
815     gst_rtp_buffer_unmap (&rtp);
816     out_buf = process_func (filter, in);
817   } else {
818     goto no_process;
819   }
820
821   /* let's send it out to processing */
822   if (out_buf) {
823     if (priv->process_flow_ret == GST_FLOW_OK)
824       priv->process_flow_ret = gst_rtp_base_depayload_push (filter, out_buf);
825     else
826       gst_buffer_unref (out_buf);
827   }
828
829   gst_buffer_unref (in);
830   priv->input_buffer = NULL;
831
832   return priv->process_flow_ret;
833
834   /* ERRORS */
835 not_negotiated:
836   {
837     /* this is not fatal but should be filtered earlier */
838     GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION,
839         ("No RTP format was negotiated."),
840         ("Input buffers need to have RTP caps set on them. This is usually "
841             "achieved by setting the 'caps' property of the upstream source "
842             "element (often udpsrc or appsrc), or by putting a capsfilter "
843             "element before the depayloader and setting the 'caps' property "
844             "on that. Also see http://cgit.freedesktop.org/gstreamer/"
845             "gst-plugins-good/tree/gst/rtp/README"));
846     gst_buffer_unref (in);
847     return GST_FLOW_NOT_NEGOTIATED;
848   }
849 invalid_buffer:
850   {
851     /* this is not fatal but should be filtered earlier */
852     GST_ELEMENT_WARNING (filter, STREAM, DECODE, (NULL),
853         ("Received invalid RTP payload, dropping"));
854     gst_buffer_unref (in);
855     return GST_FLOW_OK;
856   }
857 dropping:
858   {
859     gst_rtp_buffer_unmap (&rtp);
860     gst_buffer_unref (in);
861     return GST_FLOW_OK;
862   }
863 no_process:
864   {
865     gst_rtp_buffer_unmap (&rtp);
866     /* this is not fatal but should be filtered earlier */
867     GST_ELEMENT_ERROR (filter, STREAM, NOT_IMPLEMENTED, (NULL),
868         ("The subclass does not have a process or process_rtp_packet method"));
869     gst_buffer_unref (in);
870     return GST_FLOW_ERROR;
871   }
872 }
873
874 static GstFlowReturn
875 gst_rtp_base_depayload_chain (GstPad * pad, GstObject * parent, GstBuffer * in)
876 {
877   GstRTPBaseDepayloadClass *bclass;
878   GstRTPBaseDepayload *basedepay;
879   GstFlowReturn flow_ret;
880
881   basedepay = GST_RTP_BASE_DEPAYLOAD_CAST (parent);
882
883   bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (basedepay);
884
885   flow_ret = gst_rtp_base_depayload_handle_buffer (basedepay, bclass, in);
886
887   return flow_ret;
888 }
889
890 static GstFlowReturn
891 gst_rtp_base_depayload_chain_list (GstPad * pad, GstObject * parent,
892     GstBufferList * list)
893 {
894   GstRTPBaseDepayloadClass *bclass;
895   GstRTPBaseDepayload *basedepay;
896   GstFlowReturn flow_ret;
897   GstBuffer *buffer;
898   guint i, len;
899
900   basedepay = GST_RTP_BASE_DEPAYLOAD_CAST (parent);
901
902   bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (basedepay);
903
904   flow_ret = GST_FLOW_OK;
905
906   /* chain each buffer in list individually */
907   len = gst_buffer_list_length (list);
908
909   if (len == 0)
910     goto done;
911
912   for (i = 0; i < len; i++) {
913     buffer = gst_buffer_list_get (list, i);
914
915     /* handle_buffer takes ownership of input buffer */
916     /* FIXME: add a way to steal buffers from list as we will unref it anyway */
917     gst_buffer_ref (buffer);
918
919     /* Should we fix up any missing timestamps for list buffers here
920      * (e.g. set to first or previous timestamp in list) or just assume
921      * the's a jitterbuffer that will have done that for us? */
922     flow_ret = gst_rtp_base_depayload_handle_buffer (basedepay, bclass, buffer);
923     if (flow_ret != GST_FLOW_OK)
924       break;
925   }
926
927 done:
928
929   gst_buffer_list_unref (list);
930
931   return flow_ret;
932 }
933
934 static gboolean
935 gst_rtp_base_depayload_handle_event (GstRTPBaseDepayload * filter,
936     GstEvent * event)
937 {
938   gboolean res = TRUE;
939   gboolean forward = TRUE;
940
941   switch (GST_EVENT_TYPE (event)) {
942     case GST_EVENT_FLUSH_STOP:
943       GST_OBJECT_LOCK (filter);
944       gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED);
945       GST_OBJECT_UNLOCK (filter);
946
947       filter->need_newsegment = !filter->priv->onvif_mode;
948       filter->priv->next_seqnum = -1;
949       filter->priv->ref_ts = -1;
950       gst_event_replace (&filter->priv->segment_event, NULL);
951       break;
952     case GST_EVENT_CAPS:
953     {
954       GstCaps *caps;
955
956       gst_event_parse_caps (event, &caps);
957
958       res = gst_rtp_base_depayload_setcaps (filter, caps);
959       forward = FALSE;
960       break;
961     }
962     case GST_EVENT_SEGMENT:
963     {
964       GstSegment segment;
965
966       GST_OBJECT_LOCK (filter);
967       gst_event_copy_segment (event, &segment);
968
969       if (segment.format != GST_FORMAT_TIME) {
970         GST_ERROR_OBJECT (filter, "Segment with non-TIME format not supported");
971         res = FALSE;
972       }
973       filter->priv->segment_seqnum = gst_event_get_seqnum (event);
974       filter->segment = segment;
975       GST_OBJECT_UNLOCK (filter);
976
977       /* In ONVIF mode, upstream is expected to send us the correct segment */
978       if (!filter->priv->onvif_mode) {
979         /* don't pass the event downstream, we generate our own segment including
980          * the NTP time and other things we receive in caps */
981         forward = FALSE;
982       }
983       break;
984     }
985     case GST_EVENT_CUSTOM_DOWNSTREAM:
986     {
987       GstRTPBaseDepayloadClass *bclass;
988
989       bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (filter);
990
991       if (gst_event_has_name (event, "GstRTPPacketLost")) {
992         /* we get this event from the jitterbuffer when it considers a packet as
993          * being lost. We send it to our packet_lost vmethod. The default
994          * implementation will make time progress by pushing out a GAP event.
995          * Subclasses can override and do one of the following:
996          *  - Adjust timestamp/duration to something more accurate before
997          *    calling the parent (default) packet_lost method.
998          *  - do some more advanced error concealing on the already received
999          *    (fragmented) packets.
1000          *  - ignore the packet lost.
1001          */
1002         if (bclass->packet_lost)
1003           res = bclass->packet_lost (filter, event);
1004         forward = FALSE;
1005       }
1006       break;
1007     }
1008     default:
1009       break;
1010   }
1011
1012   if (forward)
1013     res = gst_pad_push_event (filter->srcpad, event);
1014   else
1015     gst_event_unref (event);
1016
1017   return res;
1018 }
1019
1020 static gboolean
1021 gst_rtp_base_depayload_handle_sink_event (GstPad * pad, GstObject * parent,
1022     GstEvent * event)
1023 {
1024   gboolean res = FALSE;
1025   GstRTPBaseDepayload *filter;
1026   GstRTPBaseDepayloadClass *bclass;
1027
1028   filter = GST_RTP_BASE_DEPAYLOAD (parent);
1029   bclass = GST_RTP_BASE_DEPAYLOAD_GET_CLASS (filter);
1030   if (bclass->handle_event)
1031     res = bclass->handle_event (filter, event);
1032   else
1033     gst_event_unref (event);
1034
1035   return res;
1036 }
1037
1038 static GstEvent *
1039 create_segment_event (GstRTPBaseDepayload * filter, guint rtptime,
1040     GstClockTime position)
1041 {
1042   GstEvent *event;
1043   GstClockTime start, stop, running_time;
1044   GstRTPBaseDepayloadPrivate *priv;
1045   GstSegment segment;
1046
1047   priv = filter->priv;
1048
1049   /* We don't need the object lock around - the segment
1050    * can't change here while we're holding the STREAM_LOCK
1051    */
1052
1053   /* determining the start of the segment */
1054   start = filter->segment.start;
1055   if (priv->clock_base != -1 && position != -1) {
1056     GstClockTime exttime, gap;
1057
1058     exttime = priv->clock_base;
1059     gst_rtp_buffer_ext_timestamp (&exttime, rtptime);
1060     gap = gst_util_uint64_scale_int (exttime - priv->clock_base,
1061         filter->clock_rate, GST_SECOND);
1062
1063     /* account for lost packets */
1064     if (position > gap) {
1065       GST_DEBUG_OBJECT (filter,
1066           "Found gap of %" GST_TIME_FORMAT ", adjusting start: %"
1067           GST_TIME_FORMAT " = %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
1068           GST_TIME_ARGS (gap), GST_TIME_ARGS (position - gap),
1069           GST_TIME_ARGS (position), GST_TIME_ARGS (gap));
1070       start = position - gap;
1071     }
1072   }
1073
1074   /* determining the stop of the segment */
1075   stop = filter->segment.stop;
1076   if (priv->npt_stop != -1)
1077     stop = start + (priv->npt_stop - priv->npt_start);
1078
1079   if (position == -1)
1080     position = start;
1081
1082   running_time = gst_segment_to_running_time (&filter->segment,
1083       GST_FORMAT_TIME, start);
1084
1085   gst_segment_init (&segment, GST_FORMAT_TIME);
1086   segment.rate = priv->play_speed;
1087   segment.applied_rate = priv->play_scale;
1088   segment.start = start;
1089   segment.stop = stop;
1090   segment.time = priv->npt_start;
1091   segment.position = position;
1092   segment.base = running_time;
1093
1094   GST_DEBUG_OBJECT (filter, "Creating segment event %" GST_SEGMENT_FORMAT,
1095       &segment);
1096   event = gst_event_new_segment (&segment);
1097   if (filter->priv->segment_seqnum != GST_SEQNUM_INVALID)
1098     gst_event_set_seqnum (event, filter->priv->segment_seqnum);
1099
1100   return event;
1101 }
1102
1103 static gboolean
1104 foreach_metadata_drop (GstBuffer * buffer, GstMeta ** meta, gpointer user_data)
1105 {
1106   GType drop_api_type = (GType) user_data;
1107   const GstMetaInfo *info = (*meta)->info;
1108
1109   if (info->api == drop_api_type)
1110     *meta = NULL;
1111
1112   return TRUE;
1113 }
1114
1115 static void
1116 add_rtp_source_meta (GstBuffer * outbuf, GstBuffer * rtpbuf)
1117 {
1118   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
1119   GstRTPSourceMeta *meta;
1120   guint32 ssrc;
1121   GType source_meta_api = gst_rtp_source_meta_api_get_type ();
1122
1123   if (!gst_rtp_buffer_map (rtpbuf, GST_MAP_READ, &rtp))
1124     return;
1125
1126   ssrc = gst_rtp_buffer_get_ssrc (&rtp);
1127
1128   /* remove any pre-existing source-meta */
1129   gst_buffer_foreach_meta (outbuf, foreach_metadata_drop,
1130       (gpointer) source_meta_api);
1131
1132   meta = gst_buffer_add_rtp_source_meta (outbuf, &ssrc, NULL, 0);
1133   if (meta != NULL) {
1134     gint i;
1135     gint csrc_count = gst_rtp_buffer_get_csrc_count (&rtp);
1136     for (i = 0; i < csrc_count; i++) {
1137       guint32 csrc = gst_rtp_buffer_get_csrc (&rtp, i);
1138       gst_rtp_source_meta_append_csrc (meta, &csrc, 1);
1139     }
1140   }
1141
1142   gst_rtp_buffer_unmap (&rtp);
1143 }
1144
1145 static void
1146 gst_rtp_base_depayload_add_extension (GstRTPBaseDepayload * rtpbasepayload,
1147     GstRTPHeaderExtension * ext)
1148 {
1149   g_return_if_fail (GST_IS_RTP_HEADER_EXTENSION (ext));
1150   g_return_if_fail (gst_rtp_header_extension_get_id (ext) > 0);
1151
1152   /* XXX: check for duplicate ids? */
1153   GST_OBJECT_LOCK (rtpbasepayload);
1154   g_ptr_array_add (rtpbasepayload->priv->header_exts, gst_object_ref (ext));
1155   GST_OBJECT_UNLOCK (rtpbasepayload);
1156 }
1157
1158 static void
1159 gst_rtp_base_depayload_clear_extensions (GstRTPBaseDepayload * rtpbasepayload)
1160 {
1161   GST_OBJECT_LOCK (rtpbasepayload);
1162   g_ptr_array_set_size (rtpbasepayload->priv->header_exts, 0);
1163   GST_OBJECT_UNLOCK (rtpbasepayload);
1164 }
1165
1166 static gboolean
1167 read_rtp_header_extensions (GstRTPBaseDepayload * depayload,
1168     GstBuffer * input, GstBuffer * output)
1169 {
1170   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
1171   guint16 bit_pattern;
1172   guint8 *pdata;
1173   guint wordlen;
1174   gboolean needs_src_caps_update = FALSE;
1175
1176   if (!input) {
1177     GST_DEBUG_OBJECT (depayload, "no input buffer");
1178     return needs_src_caps_update;
1179   }
1180
1181   if (!gst_rtp_buffer_map (input, GST_MAP_READ, &rtp)) {
1182     GST_WARNING_OBJECT (depayload, "Failed to map buffer");
1183     return needs_src_caps_update;
1184   }
1185
1186   if (gst_rtp_buffer_get_extension_data (&rtp, &bit_pattern, (gpointer) & pdata,
1187           &wordlen)) {
1188     GstRTPHeaderExtensionFlags ext_flags = 0;
1189     gsize bytelen = wordlen * 4;
1190     guint hdr_unit_bytes;
1191     gsize offset = 0;
1192
1193     if (bit_pattern == 0xBEDE) {
1194       /* one byte extensions */
1195       hdr_unit_bytes = 1;
1196       ext_flags |= GST_RTP_HEADER_EXTENSION_ONE_BYTE;
1197     } else if (bit_pattern >> 4 == 0x100) {
1198       /* two byte extensions */
1199       hdr_unit_bytes = 2;
1200       ext_flags |= GST_RTP_HEADER_EXTENSION_TWO_BYTE;
1201     } else {
1202       GST_DEBUG_OBJECT (depayload, "unknown extension bit pattern 0x%02x%02x",
1203           bit_pattern >> 8, bit_pattern & 0xff);
1204       goto out;
1205     }
1206
1207     while (TRUE) {
1208       guint8 read_id, read_len;
1209       GstRTPHeaderExtension *ext = NULL;
1210       guint i;
1211
1212       if (offset + hdr_unit_bytes >= bytelen)
1213         /* not enough remaning data */
1214         break;
1215
1216       if (ext_flags & GST_RTP_HEADER_EXTENSION_ONE_BYTE) {
1217         read_id = GST_READ_UINT8 (pdata + offset) >> 4;
1218         read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1;
1219         offset += 1;
1220
1221         if (read_id == 0)
1222           /* padding */
1223           continue;
1224
1225         if (read_id == 15)
1226           /* special id for possible future expansion */
1227           break;
1228       } else {
1229         read_id = GST_READ_UINT8 (pdata + offset);
1230         offset += 1;
1231
1232         if (read_id == 0)
1233           /* padding */
1234           continue;
1235
1236         read_len = GST_READ_UINT8 (pdata + offset);
1237         offset += 1;
1238       }
1239       GST_TRACE_OBJECT (depayload, "found rtp header extension with id %u and "
1240           "length %u", read_id, read_len);
1241
1242       /* Ignore extension headers where the size does not fit */
1243       if (offset + read_len > bytelen) {
1244         GST_WARNING_OBJECT (depayload, "Extension length extends past the "
1245             "size of the extension data");
1246         break;
1247       }
1248
1249       GST_OBJECT_LOCK (depayload);
1250       for (i = 0; i < depayload->priv->header_exts->len; i++) {
1251         ext = g_ptr_array_index (depayload->priv->header_exts, i);
1252         if (read_id == gst_rtp_header_extension_get_id (ext)) {
1253           gst_object_ref (ext);
1254           break;
1255         }
1256         ext = NULL;
1257       }
1258
1259       if (ext) {
1260         if (!gst_rtp_header_extension_read (ext, ext_flags, &pdata[offset],
1261                 read_len, output)) {
1262           GST_WARNING_OBJECT (depayload, "RTP header extension (%s) could "
1263               "not read payloaded data", GST_OBJECT_NAME (ext));
1264           gst_object_unref (ext);
1265           goto out;
1266         }
1267
1268         if (gst_rtp_header_extension_wants_update_non_rtp_src_caps (ext)) {
1269           needs_src_caps_update = TRUE;
1270         }
1271
1272         gst_object_unref (ext);
1273       }
1274       GST_OBJECT_UNLOCK (depayload);
1275
1276       offset += read_len;
1277     }
1278   }
1279
1280 out:
1281   gst_rtp_buffer_unmap (&rtp);
1282
1283   return needs_src_caps_update;
1284 }
1285
1286 static gboolean
1287 gst_rtp_base_depayload_set_headers (GstRTPBaseDepayload * depayload,
1288     GstBuffer * buffer)
1289 {
1290   GstRTPBaseDepayloadPrivate *priv = depayload->priv;
1291   GstClockTime pts, dts, duration;
1292
1293   pts = GST_BUFFER_PTS (buffer);
1294   dts = GST_BUFFER_DTS (buffer);
1295   duration = GST_BUFFER_DURATION (buffer);
1296
1297   /* apply last incoming timestamp and duration to outgoing buffer if
1298    * not otherwise set. */
1299   if (!GST_CLOCK_TIME_IS_VALID (pts))
1300     GST_BUFFER_PTS (buffer) = priv->pts;
1301   if (!GST_CLOCK_TIME_IS_VALID (dts))
1302     GST_BUFFER_DTS (buffer) = priv->dts;
1303   if (!GST_CLOCK_TIME_IS_VALID (duration))
1304     GST_BUFFER_DURATION (buffer) = priv->duration;
1305
1306   if (G_UNLIKELY (depayload->priv->discont)) {
1307     GST_LOG_OBJECT (depayload, "Marking DISCONT on output buffer");
1308     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1309     depayload->priv->discont = FALSE;
1310   }
1311
1312   /* make sure we only set the timestamp on the first packet */
1313   priv->pts = GST_CLOCK_TIME_NONE;
1314   priv->dts = GST_CLOCK_TIME_NONE;
1315   priv->duration = GST_CLOCK_TIME_NONE;
1316
1317   if (priv->input_buffer) {
1318     if (priv->source_info)
1319       add_rtp_source_meta (buffer, priv->input_buffer);
1320
1321     return read_rtp_header_extensions (depayload, priv->input_buffer, buffer);
1322   }
1323
1324   return FALSE;
1325 }
1326
1327 static GstFlowReturn
1328 gst_rtp_base_depayload_finish_push (GstRTPBaseDepayload * filter,
1329     gboolean is_list, gpointer obj)
1330 {
1331   /* if this is the first buffer send a NEWSEGMENT */
1332   if (G_UNLIKELY (filter->priv->segment_event)) {
1333     gst_pad_push_event (filter->srcpad, filter->priv->segment_event);
1334     filter->priv->segment_event = NULL;
1335     GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer");
1336   }
1337
1338   if (is_list) {
1339     GstBufferList *blist = obj;
1340     return gst_pad_push_list (filter->srcpad, blist);
1341   } else {
1342     GstBuffer *buf = obj;
1343     return gst_pad_push (filter->srcpad, buf);
1344   }
1345 }
1346
1347 static gboolean
1348 gst_rtp_base_depayload_set_src_caps_from_hdrext (GstRTPBaseDepayload * filter)
1349 {
1350   gboolean update_ok = TRUE;
1351   GstCaps *src_caps = gst_pad_get_current_caps (filter->srcpad);
1352
1353   if (src_caps) {
1354     GstCaps *new_caps;
1355     gint i;
1356
1357     new_caps = gst_caps_copy (src_caps);
1358     for (i = 0; i < filter->priv->header_exts->len; i++) {
1359       GstRTPHeaderExtension *ext;
1360
1361       ext = g_ptr_array_index (filter->priv->header_exts, i);
1362       update_ok =
1363           gst_rtp_header_extension_update_non_rtp_src_caps (ext, new_caps);
1364
1365       if (!update_ok) {
1366         GST_ELEMENT_ERROR (filter, STREAM, DECODE,
1367             ("RTP header extension (%s) could not update src caps",
1368                 GST_OBJECT_NAME (ext)), (NULL));
1369         break;
1370       }
1371     }
1372
1373     if (G_UNLIKELY (update_ok && !gst_caps_is_equal (src_caps, new_caps))) {
1374       gst_pad_set_caps (filter->srcpad, new_caps);
1375     }
1376
1377     gst_caps_unref (src_caps);
1378     gst_caps_unref (new_caps);
1379   }
1380
1381   return update_ok;
1382 }
1383
1384 static GstFlowReturn
1385 gst_rtp_base_depayload_do_push (GstRTPBaseDepayload * filter, gboolean is_list,
1386     gpointer obj)
1387 {
1388   GstFlowReturn res;
1389
1390   if (is_list) {
1391     GstBufferList *blist = obj;
1392     guint i;
1393     guint first_not_pushed_idx = 0;
1394
1395     for (i = 0; i < gst_buffer_list_length (blist); ++i) {
1396       GstBuffer *buf = gst_buffer_list_get_writable (blist, i);
1397
1398       if (G_UNLIKELY (gst_rtp_base_depayload_set_headers (filter, buf))) {
1399         /* src caps have changed; push the buffers preceding the current one,
1400          * then apply the new caps on the src pad */
1401         guint j;
1402
1403         for (j = first_not_pushed_idx; j < i; ++j) {
1404           res = gst_rtp_base_depayload_finish_push (filter, FALSE,
1405               gst_buffer_ref (gst_buffer_list_get (blist, j)));
1406           if (G_UNLIKELY (res != GST_FLOW_OK)) {
1407             goto error_list;
1408           }
1409         }
1410         first_not_pushed_idx = i;
1411
1412         if (!gst_rtp_base_depayload_set_src_caps_from_hdrext (filter)) {
1413           res = GST_FLOW_ERROR;
1414           goto error_list;
1415         }
1416       }
1417     }
1418
1419     if (G_LIKELY (first_not_pushed_idx == 0)) {
1420       res = gst_rtp_base_depayload_finish_push (filter, TRUE, blist);
1421       blist = NULL;
1422     } else {
1423       for (i = first_not_pushed_idx; i < gst_buffer_list_length (blist); ++i) {
1424         res = gst_rtp_base_depayload_finish_push (filter, FALSE,
1425             gst_buffer_ref (gst_buffer_list_get (blist, i)));
1426         if (G_UNLIKELY (res != GST_FLOW_OK)) {
1427           break;
1428         }
1429       }
1430     }
1431
1432   error_list:
1433     gst_clear_buffer_list (&blist);
1434   } else {
1435     GstBuffer *buf = obj;
1436     if (G_UNLIKELY (gst_rtp_base_depayload_set_headers (filter, buf))) {
1437       if (!gst_rtp_base_depayload_set_src_caps_from_hdrext (filter)) {
1438         res = GST_FLOW_ERROR;
1439         goto error_buffer;
1440       }
1441     }
1442
1443     res = gst_rtp_base_depayload_finish_push (filter, FALSE, buf);
1444     buf = NULL;
1445
1446   error_buffer:
1447     gst_clear_buffer (&buf);
1448   }
1449
1450   return res;
1451 }
1452
1453 /**
1454  * gst_rtp_base_depayload_push:
1455  * @filter: a #GstRTPBaseDepayload
1456  * @out_buf: (transfer full): a #GstBuffer
1457  *
1458  * Push @out_buf to the peer of @filter. This function takes ownership of
1459  * @out_buf.
1460  *
1461  * This function will by default apply the last incoming timestamp on
1462  * the outgoing buffer when it didn't have a timestamp already.
1463  *
1464  * Returns: a #GstFlowReturn.
1465  */
1466 GstFlowReturn
1467 gst_rtp_base_depayload_push (GstRTPBaseDepayload * filter, GstBuffer * out_buf)
1468 {
1469   GstFlowReturn res;
1470
1471   res = gst_rtp_base_depayload_do_push (filter, FALSE, out_buf);
1472
1473   if (res != GST_FLOW_OK)
1474     filter->priv->process_flow_ret = res;
1475
1476   return res;
1477 }
1478
1479 /**
1480  * gst_rtp_base_depayload_push_list:
1481  * @filter: a #GstRTPBaseDepayload
1482  * @out_list: (transfer full): a #GstBufferList
1483  *
1484  * Push @out_list to the peer of @filter. This function takes ownership of
1485  * @out_list.
1486  *
1487  * Returns: a #GstFlowReturn.
1488  */
1489 GstFlowReturn
1490 gst_rtp_base_depayload_push_list (GstRTPBaseDepayload * filter,
1491     GstBufferList * out_list)
1492 {
1493   GstFlowReturn res;
1494
1495   res = gst_rtp_base_depayload_do_push (filter, TRUE, out_list);
1496
1497   if (res != GST_FLOW_OK)
1498     filter->priv->process_flow_ret = res;
1499
1500   return res;
1501 }
1502
1503 /* convert the PacketLost event from a jitterbuffer to a GAP event.
1504  * subclasses can override this.  */
1505 static gboolean
1506 gst_rtp_base_depayload_packet_lost (GstRTPBaseDepayload * filter,
1507     GstEvent * event)
1508 {
1509   GstClockTime timestamp, duration;
1510   GstEvent *sevent;
1511   const GstStructure *s;
1512   gboolean might_have_been_fec;
1513   gboolean res = TRUE;
1514
1515   s = gst_event_get_structure (event);
1516
1517   /* first start by parsing the timestamp and duration */
1518   timestamp = -1;
1519   duration = -1;
1520
1521   if (!gst_structure_get_clock_time (s, "timestamp", &timestamp) ||
1522       !gst_structure_get_clock_time (s, "duration", &duration)) {
1523     GST_ERROR_OBJECT (filter,
1524         "Packet loss event without timestamp or duration");
1525     return FALSE;
1526   }
1527
1528   sevent = gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_SEGMENT, 0);
1529   if (G_UNLIKELY (!sevent)) {
1530     /* Typically happens if lost event arrives before first buffer */
1531     GST_DEBUG_OBJECT (filter,
1532         "Ignore packet loss because segment event missing");
1533     return FALSE;
1534   }
1535   gst_event_unref (sevent);
1536
1537   if (!gst_structure_get_boolean (s, "might-have-been-fec",
1538           &might_have_been_fec) || !might_have_been_fec) {
1539     /* send GAP event */
1540     sevent = gst_event_new_gap (timestamp, duration);
1541     gst_event_set_gap_flags (sevent, GST_GAP_FLAG_MISSING_DATA);
1542     res = gst_pad_push_event (filter->srcpad, sevent);
1543   }
1544
1545   return res;
1546 }
1547
1548 static GstStateChangeReturn
1549 gst_rtp_base_depayload_change_state (GstElement * element,
1550     GstStateChange transition)
1551 {
1552   GstRTPBaseDepayload *filter;
1553   GstRTPBaseDepayloadPrivate *priv;
1554   GstStateChangeReturn ret;
1555
1556   filter = GST_RTP_BASE_DEPAYLOAD (element);
1557   priv = filter->priv;
1558
1559   switch (transition) {
1560     case GST_STATE_CHANGE_NULL_TO_READY:
1561       break;
1562     case GST_STATE_CHANGE_READY_TO_PAUSED:
1563       filter->need_newsegment = TRUE;
1564       priv->npt_start = 0;
1565       priv->npt_stop = -1;
1566       priv->play_speed = 1.0;
1567       priv->play_scale = 1.0;
1568       priv->clock_base = -1;
1569       priv->ref_ts = -1;
1570       priv->onvif_mode = FALSE;
1571       priv->next_seqnum = -1;
1572       priv->negotiated = FALSE;
1573       priv->discont = FALSE;
1574       priv->segment_seqnum = GST_SEQNUM_INVALID;
1575       break;
1576     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1577       break;
1578     default:
1579       break;
1580   }
1581
1582   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1583
1584   switch (transition) {
1585     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1586       break;
1587     case GST_STATE_CHANGE_PAUSED_TO_READY:
1588       gst_caps_replace (&priv->last_caps, NULL);
1589       gst_event_replace (&priv->segment_event, NULL);
1590       break;
1591     case GST_STATE_CHANGE_READY_TO_NULL:
1592       break;
1593     default:
1594       break;
1595   }
1596   return ret;
1597 }
1598
1599 static GstStructure *
1600 gst_rtp_base_depayload_create_stats (GstRTPBaseDepayload * depayload)
1601 {
1602   GstRTPBaseDepayloadPrivate *priv;
1603   GstStructure *s;
1604   GstClockTime pts = GST_CLOCK_TIME_NONE, dts = GST_CLOCK_TIME_NONE;
1605
1606   priv = depayload->priv;
1607
1608   GST_OBJECT_LOCK (depayload);
1609   if (depayload->segment.format != GST_FORMAT_UNDEFINED) {
1610     pts = gst_segment_to_running_time (&depayload->segment, GST_FORMAT_TIME,
1611         priv->pts);
1612     dts = gst_segment_to_running_time (&depayload->segment, GST_FORMAT_TIME,
1613         priv->dts);
1614   }
1615   GST_OBJECT_UNLOCK (depayload);
1616
1617   s = gst_structure_new ("application/x-rtp-depayload-stats",
1618       "clock_rate", G_TYPE_UINT, depayload->clock_rate,
1619       "npt-start", G_TYPE_UINT64, priv->npt_start,
1620       "npt-stop", G_TYPE_UINT64, priv->npt_stop,
1621       "play-speed", G_TYPE_DOUBLE, priv->play_speed,
1622       "play-scale", G_TYPE_DOUBLE, priv->play_scale,
1623       "running-time-dts", G_TYPE_UINT64, dts,
1624       "running-time-pts", G_TYPE_UINT64, pts,
1625       "seqnum", G_TYPE_UINT, (guint) priv->last_seqnum,
1626       "timestamp", G_TYPE_UINT, (guint) priv->last_rtptime, NULL);
1627
1628   return s;
1629 }
1630
1631
1632 static void
1633 gst_rtp_base_depayload_set_property (GObject * object, guint prop_id,
1634     const GValue * value, GParamSpec * pspec)
1635 {
1636   GstRTPBaseDepayload *depayload;
1637   GstRTPBaseDepayloadPrivate *priv;
1638
1639   depayload = GST_RTP_BASE_DEPAYLOAD (object);
1640   priv = depayload->priv;
1641
1642   switch (prop_id) {
1643     case PROP_SOURCE_INFO:
1644       gst_rtp_base_depayload_set_source_info_enabled (depayload,
1645           g_value_get_boolean (value));
1646       break;
1647     case PROP_MAX_REORDER:
1648       priv->max_reorder = g_value_get_int (value);
1649       break;
1650     case PROP_AUTO_HEADER_EXTENSION:
1651       priv->auto_hdr_ext = g_value_get_boolean (value);
1652       break;
1653     default:
1654       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1655       break;
1656   }
1657 }
1658
1659 static void
1660 gst_rtp_base_depayload_get_property (GObject * object, guint prop_id,
1661     GValue * value, GParamSpec * pspec)
1662 {
1663   GstRTPBaseDepayload *depayload;
1664   GstRTPBaseDepayloadPrivate *priv;
1665
1666   depayload = GST_RTP_BASE_DEPAYLOAD (object);
1667   priv = depayload->priv;
1668
1669   switch (prop_id) {
1670     case PROP_STATS:
1671       g_value_take_boxed (value,
1672           gst_rtp_base_depayload_create_stats (depayload));
1673       break;
1674     case PROP_SOURCE_INFO:
1675       g_value_set_boolean (value,
1676           gst_rtp_base_depayload_is_source_info_enabled (depayload));
1677       break;
1678     case PROP_MAX_REORDER:
1679       g_value_set_int (value, priv->max_reorder);
1680       break;
1681     case PROP_AUTO_HEADER_EXTENSION:
1682       g_value_set_boolean (value, priv->auto_hdr_ext);
1683       break;
1684     default:
1685       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1686       break;
1687   }
1688 }
1689
1690 /**
1691  * gst_rtp_base_depayload_set_source_info_enabled:
1692  * @depayload: a #GstRTPBaseDepayload
1693  * @enable: whether to add meta about RTP sources to buffer
1694  *
1695  * Enable or disable adding #GstRTPSourceMeta to depayloaded buffers.
1696  *
1697  * Since: 1.16
1698  **/
1699 void
1700 gst_rtp_base_depayload_set_source_info_enabled (GstRTPBaseDepayload * depayload,
1701     gboolean enable)
1702 {
1703   depayload->priv->source_info = enable;
1704 }
1705
1706 /**
1707  * gst_rtp_base_depayload_is_source_info_enabled:
1708  * @depayload: a #GstRTPBaseDepayload
1709  *
1710  * Queries whether #GstRTPSourceMeta will be added to depayloaded buffers.
1711  *
1712  * Returns: %TRUE if source-info is enabled.
1713  *
1714  * Since: 1.16
1715  **/
1716 gboolean
1717 gst_rtp_base_depayload_is_source_info_enabled (GstRTPBaseDepayload * depayload)
1718 {
1719   return depayload->priv->source_info;
1720 }