d70f8ba29ceb6f17f4e05ff5b9a98f6f21cf126c
[platform/upstream/gstreamer.git] / plugins / elements / gstvalve.c
1 /*
2  * Farsight Voice+Video library
3  *
4  *  Copyright 2007 Collabora Ltd, 
5  *  Copyright 2007 Nokia Corporation
6  *   @author: Olivier Crete <olivier.crete@collabora.co.uk>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "gstvalve.h"
30
31 #include <string.h>
32
33 GST_DEBUG_CATEGORY (valve_debug);
34 #define GST_CAT_DEFAULT (valve_debug)
35
36 /* elementfactory information */
37 static const GstElementDetails gst_valve_details =
38 GST_ELEMENT_DETAILS (
39   "Valve element",
40   "Filter",
41   "This element drops all packets when drop is TRUE",
42   "Olivier Crete <olivier.crete@collabora.co.uk>");
43
44
45 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
46     GST_PAD_SINK,
47     GST_PAD_ALWAYS,
48     GST_STATIC_CAPS_ANY);
49
50 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
51     GST_PAD_SRC,
52     GST_PAD_ALWAYS,
53     GST_STATIC_CAPS_ANY);
54
55 /* Valve signals and args */
56 enum
57 {
58   /* FILL ME */
59   LAST_SIGNAL
60 };
61
62 enum
63 {
64   ARG_0,
65   ARG_DROP,
66 };
67
68
69
70
71 static void gst_valve_set_property (GObject *object,
72     guint prop_id, const GValue * value, GParamSpec * pspec);
73 static void gst_valve_get_property (GObject *object,
74     guint prop_id, GValue *value, GParamSpec *pspec);
75
76 static GstFlowReturn gst_valve_transform_ip (GstBaseTransform *trans,
77     GstBuffer *buf);
78 static gboolean gst_valve_event (GstBaseTransform *trans, GstEvent *event);
79 static GstFlowReturn gst_valve_buffer_alloc (GstPad * pad, guint64 offset,
80     guint size, GstCaps * caps, GstBuffer ** buf);
81 static GstFlowReturn gst_valve_prepare_output_buffer (GstBaseTransform *trans,
82     GstBuffer * in_buf, gint out_size, GstCaps * out_caps,
83     GstBuffer ** out_buf);
84
85 static void
86 _do_init (GType type)
87 {
88   GST_DEBUG_CATEGORY_INIT
89     (valve_debug, "valve", 0, "Valve");
90 }
91
92 GST_BOILERPLATE_FULL (GstValve, gst_valve, GstBaseTransform,
93     GST_TYPE_BASE_TRANSFORM, _do_init);
94
95 static void
96 gst_valve_base_init (gpointer klass)
97 {
98   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
99
100   gst_element_class_add_pad_template (element_class,
101       gst_static_pad_template_get (&srctemplate));
102   gst_element_class_add_pad_template (element_class,
103       gst_static_pad_template_get (&sinktemplate));
104
105   gst_element_class_set_details (element_class, &gst_valve_details);
106 }
107
108 static void
109 gst_valve_class_init (GstValveClass *klass)
110 {
111   GObjectClass *gobject_class;
112   GstBaseTransformClass *gstbasetransform_class;
113
114   gobject_class = (GObjectClass *) klass;
115   gstbasetransform_class = (GstBaseTransformClass *) klass;
116
117   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_valve_set_property);
118   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_valve_get_property);
119
120   gstbasetransform_class->transform_ip =
121       GST_DEBUG_FUNCPTR (gst_valve_transform_ip);
122   gstbasetransform_class->prepare_output_buffer =
123       GST_DEBUG_FUNCPTR (gst_valve_prepare_output_buffer);
124   gstbasetransform_class->event =
125       GST_DEBUG_FUNCPTR (gst_valve_event);
126   gstbasetransform_class->src_event =
127       GST_DEBUG_FUNCPTR (gst_valve_event);
128
129   g_object_class_install_property (gobject_class, ARG_DROP,
130       g_param_spec_boolean ("drop",
131         "Drops all buffers if TRUE",
132         "If this property if TRUE, the element will drop all buffers, if its FALSE, it will let them through",
133           FALSE, G_PARAM_READWRITE));
134
135   parent_class = g_type_class_peek_parent (klass);
136 }
137
138 static void
139 gst_valve_init (GstValve *valve, GstValveClass *klass)
140 {
141
142   valve->drop = FALSE;
143   valve->discont = FALSE;
144
145   valve->original_allocfunc =
146     GST_BASE_TRANSFORM (valve)->sinkpad->bufferallocfunc;
147
148   gst_pad_set_bufferalloc_function (
149       GST_BASE_TRANSFORM (valve)->sinkpad,
150       GST_DEBUG_FUNCPTR(gst_valve_buffer_alloc));
151
152
153 #if GST_VERSION_MINOR >= 10 &&  GST_VERSION_MICRO >= 13
154   gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (valve), FALSE);
155 #endif
156
157 }
158
159
160 static void
161 gst_valve_set_property (GObject *object,
162     guint prop_id, const GValue *value, GParamSpec *pspec)
163 {
164   GstValve *valve = GST_VALVE (object);
165
166   switch (prop_id) {
167     default:
168       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
169       break;
170     case ARG_DROP:
171       GST_OBJECT_LOCK (object);
172       valve->drop = g_value_get_boolean (value);
173       GST_OBJECT_UNLOCK (object);
174       break;
175   }
176 }
177
178 static void
179 gst_valve_get_property (GObject *object,
180     guint prop_id, GValue *value, GParamSpec *pspec)
181 {
182   GstValve *valve = GST_VALVE (object);
183
184   switch (prop_id) {
185     default:
186       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187       break;
188     case ARG_DROP:
189       GST_OBJECT_LOCK (object);
190       g_value_set_boolean (value, valve->drop);
191       GST_OBJECT_UNLOCK (object);
192       break;
193   }
194 }
195
196 static GstFlowReturn
197 gst_valve_prepare_output_buffer (GstBaseTransform *trans, GstBuffer * in_buf,
198                                  gint out_size, GstCaps * out_caps,
199                                  GstBuffer ** out_buf)
200 {
201   GstValve *valve = GST_VALVE (trans);
202   GstFlowReturn ret = GST_FLOW_OK;
203
204   GST_OBJECT_LOCK (GST_OBJECT (trans));
205   if (valve->drop)
206   {
207 #if GST_VERSION_MINOR >= 10 &&  GST_VERSION_MICRO >= 13
208     ret = GST_BASE_TRANSFORM_FLOW_DROPPED;
209 #endif
210     *out_buf = NULL;
211     valve->discont = TRUE;
212   }
213   else
214   {
215     /* Always return a reffed buffer, which in case of returning the input
216      * buffer means adding an extra ref to it */
217     if (valve->discont)
218     {
219       if (gst_buffer_is_metadata_writable (in_buf))
220       {
221         *out_buf = gst_buffer_ref (in_buf);
222       }
223       else
224       {
225         *out_buf = gst_buffer_create_sub (in_buf, 0, GST_BUFFER_SIZE (in_buf));
226       }
227       GST_BUFFER_FLAG_SET (*out_buf, GST_BUFFER_FLAG_DISCONT);
228       valve->discont = FALSE;
229     }
230     else
231     {
232       *out_buf = gst_buffer_ref(in_buf);
233     }
234   }
235   GST_OBJECT_UNLOCK (GST_OBJECT (trans));
236
237   return ret;
238 }
239
240 static GstFlowReturn
241 gst_valve_transform_ip (GstBaseTransform *trans, GstBuffer *buf)
242 {
243   return GST_FLOW_OK;
244 }
245
246
247 static gboolean
248 gst_valve_event (GstBaseTransform *trans, GstEvent *event)
249 {
250   GstValve *valve = GST_VALVE (trans);
251   gboolean ret = TRUE;
252
253   GST_OBJECT_LOCK (GST_OBJECT (trans));
254   if (valve->drop)
255     ret = FALSE;
256   GST_OBJECT_UNLOCK (GST_OBJECT (trans));
257
258   return ret;
259 }
260
261 static GstFlowReturn
262 gst_valve_buffer_alloc (GstPad * pad, guint64 offset, guint size,
263                         GstCaps * caps, GstBuffer ** buf)
264 {
265   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
266   GstFlowReturn ret = GST_FLOW_OK;
267
268   GST_OBJECT_LOCK (GST_OBJECT (valve));
269   if (valve->drop)
270   {
271     GST_OBJECT_UNLOCK (GST_OBJECT (valve));
272     *buf = gst_buffer_new_and_alloc (size);
273     GST_BUFFER_OFFSET (*buf) = offset;
274     gst_buffer_set_caps (*buf, caps);
275   }
276   else
277   {
278     GstPadBufferAllocFunction allocfunc = valve->original_allocfunc;
279     GST_OBJECT_UNLOCK (GST_OBJECT (valve));
280     ret = allocfunc (pad, offset, size, caps, buf);
281   }
282
283   gst_object_unref (valve);
284
285   return ret;
286 }
287
288
289 gboolean
290 gst_valve_plugin_init (GstPlugin *plugin)
291 {
292   return gst_element_register (plugin, "fsvalve",
293       GST_RANK_MARGINAL, GST_TYPE_VALVE);
294 }
295
296 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
297     GST_VERSION_MINOR,
298     "fsvalve",
299     "Valve",
300     gst_valve_plugin_init, VERSION, "LGPL", "Farsight", "http://farsight.sf.net")