702b3e56b72541b916ad6edee9efb304da7e9039
[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  * SECTION:element-valve
26  *
27  * The valve is a simple element that drops buffers when the #GstValve::drop
28  * property is set to %TRUE and lets then through otherwise.
29  *
30  * Any downstream error received while the #GstValve::drop property is %FALSE
31  * is ignored. So downstream element can be set to  %GST_STATE_NULL and removed,
32  * without using pad blocking.
33  *
34  * Last reviewed on 2008-02-10 (0.10.11)
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include "gstvalve.h"
42
43 #include <string.h>
44
45 GST_DEBUG_CATEGORY (valve_debug);
46 #define GST_CAT_DEFAULT (valve_debug)
47
48 /* elementfactory information */
49 static const GstElementDetails gst_valve_details =
50 GST_ELEMENT_DETAILS ("Valve element",
51     "Filter",
52     "This element drops all packets when drop is TRUE",
53     "Olivier Crete <olivier.crete@collabora.co.uk>");
54
55
56 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
57     GST_PAD_SINK,
58     GST_PAD_ALWAYS,
59     GST_STATIC_CAPS_ANY);
60
61 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
62     GST_PAD_SRC,
63     GST_PAD_ALWAYS,
64     GST_STATIC_CAPS_ANY);
65
66 /* Valve signals and args */
67 enum
68 {
69   /* FILL ME */
70   LAST_SIGNAL
71 };
72
73 enum
74 {
75   ARG_0,
76   ARG_DROP,
77 };
78
79
80
81
82 static void gst_valve_set_property (GObject * object,
83     guint prop_id, const GValue * value, GParamSpec * pspec);
84 static void gst_valve_get_property (GObject * object,
85     guint prop_id, GValue * value, GParamSpec * pspec);
86
87 static gboolean gst_valve_event (GstPad * pad, GstEvent * event);
88 static GstFlowReturn gst_valve_buffer_alloc (GstPad * pad, guint64 offset,
89     guint size, GstCaps * caps, GstBuffer ** buf);
90 static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer);
91 static GstCaps *gst_valve_getcaps (GstPad * pad);
92
93 static void
94 _do_init (GType type)
95 {
96   GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve");
97 }
98
99 GST_BOILERPLATE_FULL (GstValve, gst_valve, GstElement,
100     GST_TYPE_ELEMENT, _do_init);
101
102 static void
103 gst_valve_base_init (gpointer klass)
104 {
105   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
106
107   gst_element_class_add_pad_template (element_class,
108       gst_static_pad_template_get (&srctemplate));
109   gst_element_class_add_pad_template (element_class,
110       gst_static_pad_template_get (&sinktemplate));
111
112   gst_element_class_set_details (element_class, &gst_valve_details);
113 }
114
115 static void
116 gst_valve_class_init (GstValveClass * klass)
117 {
118   GObjectClass *gobject_class;
119
120   gobject_class = (GObjectClass *) klass;
121
122   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_valve_set_property);
123   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_valve_get_property);
124
125   g_object_class_install_property (gobject_class, ARG_DROP,
126       g_param_spec_boolean ("drop",
127           "Drops all buffers if TRUE",
128           "If this property if TRUE, the element will drop all buffers, if its FALSE, it will let them through",
129           FALSE, G_PARAM_READWRITE));
130
131   parent_class = g_type_class_peek_parent (klass);
132 }
133
134 static void
135 gst_valve_init (GstValve * valve, GstValveClass * klass)
136 {
137   valve->drop = FALSE;
138   valve->discont = FALSE;
139
140   valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
141   gst_pad_set_getcaps_function (valve->srcpad,
142       GST_DEBUG_FUNCPTR (gst_valve_getcaps));
143   gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad);
144
145   valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
146   gst_pad_set_chain_function (valve->sinkpad,
147       GST_DEBUG_FUNCPTR (gst_valve_chain));
148   gst_pad_set_event_function (valve->sinkpad,
149       GST_DEBUG_FUNCPTR (gst_valve_event));
150   gst_pad_set_bufferalloc_function (valve->sinkpad,
151       GST_DEBUG_FUNCPTR (gst_valve_buffer_alloc));
152   gst_pad_set_getcaps_function (valve->sinkpad,
153       GST_DEBUG_FUNCPTR (gst_valve_getcaps));
154   gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad);
155 }
156
157
158 static void
159 gst_valve_set_property (GObject * object,
160     guint prop_id, const GValue * value, GParamSpec * pspec)
161 {
162   GstValve *valve = GST_VALVE (object);
163
164   switch (prop_id) {
165     default:
166       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
167       break;
168     case ARG_DROP:
169       GST_OBJECT_LOCK (object);
170       valve->drop = g_value_get_boolean (value);
171       GST_OBJECT_UNLOCK (object);
172       break;
173   }
174 }
175
176 static void
177 gst_valve_get_property (GObject * object,
178     guint prop_id, GValue * value, GParamSpec * pspec)
179 {
180   GstValve *valve = GST_VALVE (object);
181
182   switch (prop_id) {
183     default:
184       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
185       break;
186     case ARG_DROP:
187       GST_OBJECT_LOCK (object);
188       g_value_set_boolean (value, valve->drop);
189       GST_OBJECT_UNLOCK (object);
190       break;
191   }
192 }
193
194 static GstFlowReturn
195 gst_valve_chain (GstPad * pad, GstBuffer * buffer)
196 {
197   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
198   GstFlowReturn ret = GST_FLOW_OK;
199   gboolean drop;
200
201   GST_OBJECT_LOCK (GST_OBJECT (valve));
202   drop = valve->drop;
203
204   if (!drop && valve->discont) {
205     buffer = gst_buffer_make_metadata_writable (buffer);
206     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
207     valve->discont = FALSE;
208   }
209   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
210
211   if (drop)
212     gst_buffer_unref (buffer);
213   else
214     ret = gst_pad_push (valve->srcpad, buffer);
215
216
217   GST_OBJECT_LOCK (GST_OBJECT (valve));
218   if (valve->drop)
219     ret = GST_FLOW_OK;
220   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
221
222   gst_object_unref (valve);
223
224   return ret;
225 }
226
227
228 static gboolean
229 gst_valve_event (GstPad * pad, GstEvent * event)
230 {
231   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
232   gboolean ret = TRUE;
233   gboolean drop;
234
235   GST_OBJECT_LOCK (GST_OBJECT (valve));
236   drop = valve->drop;
237   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
238
239   if (drop)
240     gst_event_unref (event);
241   else
242     ret = gst_pad_push_event (valve->srcpad, event);
243
244   GST_OBJECT_LOCK (GST_OBJECT (valve));
245   if (valve->drop)
246     ret = TRUE;
247   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
248
249   gst_object_unref (valve);
250   return ret;
251 }
252
253 static GstFlowReturn
254 gst_valve_buffer_alloc (GstPad * pad, guint64 offset, guint size,
255     GstCaps * caps, GstBuffer ** buf)
256 {
257   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
258   GstFlowReturn ret = GST_FLOW_OK;
259   gboolean drop;
260
261   GST_OBJECT_LOCK (GST_OBJECT (valve));
262   drop = valve->drop;
263   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
264
265   if (drop)
266     *buf = NULL;
267   else
268     ret = gst_pad_alloc_buffer (valve->srcpad, offset, size, caps, buf);
269
270   GST_OBJECT_LOCK (GST_OBJECT (valve));
271   if (valve->drop)
272     ret = GST_FLOW_OK;
273   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
274
275   gst_object_unref (valve);
276
277   return ret;
278 }
279
280 static GstCaps *
281 gst_valve_getcaps (GstPad * pad)
282 {
283   GstValve *valve = GST_VALVE (gst_pad_get_parent (pad));
284   GstCaps *caps;
285
286   if (pad == valve->sinkpad)
287     caps = gst_pad_peer_get_caps (valve->srcpad);
288   else
289     caps = gst_pad_peer_get_caps (valve->sinkpad);
290
291   if (caps == NULL)
292     caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
293
294   gst_object_unref (valve);
295
296   return caps;
297 }
298
299
300 static gboolean
301 plugin_init (GstPlugin * plugin)
302 {
303   return gst_element_register (plugin, "valve",
304       GST_RANK_MARGINAL, GST_TYPE_VALVE);
305 }
306
307 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
308     GST_VERSION_MINOR,
309     "valve",
310     "Valve",
311     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)