rtpptdemux: do no assume sink caps are non NULL
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpstorage.c
1 /* GStreamer plugin for forward error correction
2  * Copyright (C) 2017 Pexip
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Author: Mikhail Fludkov <misha@pexip.com>
19  */
20
21 #include "gstrtpstorage.h"
22
23 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
24     GST_PAD_SINK,
25     GST_PAD_ALWAYS,
26     GST_STATIC_CAPS ("application/x-rtp")
27     );
28
29 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
30     GST_PAD_SRC,
31     GST_PAD_ALWAYS,
32     GST_STATIC_CAPS ("application/x-rtp")
33     );
34
35 enum
36 {
37   PROP_0,
38   PROP_SIZE_TIME,
39   PROP_INTERNAL_STORAGE,
40   N_PROPERTIES
41 };
42
43 static GParamSpec *klass_properties[N_PROPERTIES] = { NULL, };
44
45 #define DEFAULT_SIZE_TIME (0)
46
47 GST_DEBUG_CATEGORY_STATIC (gst_rtp_storage_debug);
48 #define GST_CAT_DEFAULT (gst_rtp_storage_debug)
49
50 G_DEFINE_TYPE (GstRtpStorage, gst_rtp_storage, GST_TYPE_ELEMENT);
51
52 static GstFlowReturn
53 gst_rtp_storage_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
54 {
55   GstRtpStorage *self = GST_RTP_STORAGE (parent);;
56
57   if (rtp_storage_append_buffer (self->storage, buf))
58     return gst_pad_push (self->srcpad, buf);
59   return GST_FLOW_OK;
60 }
61
62 static void
63 gst_rtp_storage_set_property (GObject * object, guint prop_id,
64     const GValue * value, GParamSpec * pspec)
65 {
66   GstRtpStorage *self = GST_RTP_STORAGE (object);
67
68   if (GST_LEVEL_DEBUG <= gst_debug_category_get_threshold (GST_CAT_DEFAULT)) {
69     gchar *val_str = gst_value_serialize (value);
70     GST_DEBUG_OBJECT (object, "Setting property \"%s\" to %s", pspec->name,
71         val_str);
72     g_free (val_str);
73   }
74
75   switch (prop_id) {
76     case PROP_SIZE_TIME:
77       rtp_storage_set_size (self->storage, g_value_get_uint64 (value));
78       break;
79     default:
80       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
81       break;
82   }
83 }
84
85 static void
86 gst_rtp_storage_get_property (GObject * object, guint prop_id,
87     GValue * value, GParamSpec * pspec)
88 {
89   GstRtpStorage *self = GST_RTP_STORAGE (object);
90   switch (prop_id) {
91     case PROP_SIZE_TIME:
92       g_value_set_uint64 (value, rtp_storage_get_size (self->storage));
93       break;
94     case PROP_INTERNAL_STORAGE:
95     {
96       g_value_set_object (value, self->storage);
97       break;
98     }
99     default:
100       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101       break;
102   }
103
104   if (GST_LEVEL_LOG <= gst_debug_category_get_threshold (GST_CAT_DEFAULT)) {
105     gchar *val_str = gst_value_serialize (value);
106     GST_LOG_OBJECT (object, "Returning property \"%s\" %s", pspec->name,
107         val_str);
108     g_free (val_str);
109   }
110 }
111
112 static void
113 gst_rtp_storage_init (GstRtpStorage * self)
114 {
115   self->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
116   self->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
117   GST_PAD_SET_PROXY_CAPS (self->sinkpad);
118   GST_PAD_SET_PROXY_ALLOCATION (self->sinkpad);
119   gst_pad_set_chain_function (self->sinkpad, gst_rtp_storage_chain);
120
121   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
122   gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
123
124   self->storage = rtp_storage_new ();
125 }
126
127 static void
128 gst_rtp_storage_dispose (GObject * obj)
129 {
130   GstRtpStorage *self = GST_RTP_STORAGE (obj);
131   g_object_unref (self->storage);
132   G_OBJECT_CLASS (gst_rtp_storage_parent_class)->dispose (obj);
133 }
134
135 static void
136 gst_rtp_storage_class_init (GstRtpStorageClass * klass)
137 {
138   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
139   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
140
141   GST_DEBUG_CATEGORY_INIT (gst_rtp_storage_debug,
142       "rtpstorage", 0, "RTP Storage");
143
144   gst_element_class_add_pad_template (element_class,
145       gst_static_pad_template_get (&srctemplate));
146   gst_element_class_add_pad_template (element_class,
147       gst_static_pad_template_get (&sinktemplate));
148
149   gst_element_class_set_static_metadata (element_class,
150       "RTP storage",
151       "Analyzer/RTP",
152       "Helper element for various purposes "
153       "(ex. recovering from packet loss using RED/FEC). "
154       "Saves given number of RTP packets. "
155       "Should be instantiated before jitterbuffer",
156       "Mikhail Fludkov <misha@pexip.com>");
157
158   gobject_class->set_property = gst_rtp_storage_set_property;
159   gobject_class->get_property = gst_rtp_storage_get_property;
160   gobject_class->dispose = gst_rtp_storage_dispose;
161
162   klass_properties[PROP_SIZE_TIME] =
163       g_param_spec_uint64 ("size-time", "Storage size (in ns)",
164       "The amount of data to keep in the storage (in ns, 0-disable)", 0,
165       G_MAXUINT64, DEFAULT_SIZE_TIME,
166       G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
167
168   klass_properties[PROP_INTERNAL_STORAGE] =
169       g_param_spec_object ("internal-storage", "Internal storage",
170       "Internal RtpStorage object", G_TYPE_OBJECT,
171       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
172
173   g_object_class_install_properties (gobject_class, N_PROPERTIES,
174       klass_properties);
175 }