fsvalve: Ignore errors if dropping is set to true
[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 gboolean gst_valve_event (GstPad *pad, GstEvent *event);
77 static GstFlowReturn gst_valve_buffer_alloc (GstPad * pad, guint64 offset,
78     guint size, GstCaps * caps, GstBuffer ** buf);
79 static GstFlowReturn gst_valve_chain (GstPad *pad, GstBuffer *buffer);
80 static GstCaps *gst_valve_getcaps (GstPad *pad);
81
82 static void
83 _do_init (GType type)
84 {
85   GST_DEBUG_CATEGORY_INIT
86     (valve_debug, "valve", 0, "Valve");
87 }
88
89 GST_BOILERPLATE_FULL (GstValve, gst_valve, GstElement,
90     GST_TYPE_ELEMENT, _do_init);
91
92 static void
93 gst_valve_base_init (gpointer klass)
94 {
95   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
96
97   gst_element_class_add_pad_template (element_class,
98       gst_static_pad_template_get (&srctemplate));
99   gst_element_class_add_pad_template (element_class,
100       gst_static_pad_template_get (&sinktemplate));
101
102   gst_element_class_set_details (element_class, &gst_valve_details);
103 }
104
105 static void
106 gst_valve_class_init (GstValveClass *klass)
107 {
108   GObjectClass *gobject_class;
109
110   gobject_class = (GObjectClass *) klass;
111
112   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_valve_set_property);
113   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_valve_get_property);
114
115   g_object_class_install_property (gobject_class, ARG_DROP,
116       g_param_spec_boolean ("drop",
117         "Drops all buffers if TRUE",
118         "If this property if TRUE, the element will drop all buffers, if its FALSE, it will let them through",
119           FALSE, G_PARAM_READWRITE));
120
121   parent_class = g_type_class_peek_parent (klass);
122 }
123
124 static void
125 gst_valve_init (GstValve *valve, GstValveClass *klass)
126 {
127   valve->drop = FALSE;
128   valve->discont = FALSE;
129
130   valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
131   gst_pad_set_getcaps_function (valve->srcpad,
132       GST_DEBUG_FUNCPTR (gst_valve_getcaps));
133   gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad);
134
135   valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
136   gst_pad_set_chain_function (valve->sinkpad,
137       GST_DEBUG_FUNCPTR (gst_valve_chain));
138   gst_pad_set_event_function (valve->sinkpad,
139       GST_DEBUG_FUNCPTR (gst_valve_event));
140   gst_pad_set_bufferalloc_function (valve->sinkpad,
141       GST_DEBUG_FUNCPTR (gst_valve_buffer_alloc));
142   gst_pad_set_getcaps_function (valve->sinkpad,
143       GST_DEBUG_FUNCPTR (gst_valve_getcaps));
144   gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad);
145 }
146
147
148 static void
149 gst_valve_set_property (GObject *object,
150     guint prop_id, const GValue *value, GParamSpec *pspec)
151 {
152   GstValve *valve = GST_VALVE (object);
153
154   switch (prop_id) {
155     default:
156       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
157       break;
158     case ARG_DROP:
159       GST_OBJECT_LOCK (object);
160       valve->drop = g_value_get_boolean (value);
161       GST_OBJECT_UNLOCK (object);
162       break;
163   }
164 }
165
166 static void
167 gst_valve_get_property (GObject *object,
168     guint prop_id, GValue *value, GParamSpec *pspec)
169 {
170   GstValve *valve = GST_VALVE (object);
171
172   switch (prop_id) {
173     default:
174       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
175       break;
176     case ARG_DROP:
177       GST_OBJECT_LOCK (object);
178       g_value_set_boolean (value, valve->drop);
179       GST_OBJECT_UNLOCK (object);
180       break;
181   }
182 }
183
184 static GstFlowReturn
185 gst_valve_chain (GstPad *pad, GstBuffer *buffer)
186 {
187   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
188   GstFlowReturn ret = GST_FLOW_OK;
189   gboolean drop;
190
191   GST_OBJECT_LOCK (GST_OBJECT (valve));
192   drop = valve->drop;
193
194   if (!drop && valve->discont)
195   {
196     buffer = gst_buffer_make_metadata_writable (buffer);
197     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
198     valve->discont = FALSE;
199   }
200   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
201
202   if (drop)
203     gst_buffer_unref (buffer);
204   else
205     ret = gst_pad_push (valve->srcpad, buffer);
206
207
208   GST_OBJECT_LOCK (GST_OBJECT (valve));
209   if (valve->drop)
210     ret = GST_FLOW_OK;
211   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
212
213   gst_object_unref (valve);
214
215   return ret;
216 }
217
218
219 static gboolean
220 gst_valve_event (GstPad *pad, GstEvent *event)
221 {
222   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
223   gboolean ret = TRUE;
224   gboolean drop;
225
226   GST_OBJECT_LOCK (GST_OBJECT (valve));
227   drop = valve->drop;
228   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
229
230   if (drop)
231     gst_event_unref (event);
232   else
233     ret = gst_pad_push_event (valve->srcpad, event);
234
235   GST_OBJECT_LOCK (GST_OBJECT (valve));
236   if (valve->drop)
237     ret = TRUE;
238   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
239
240   gst_object_unref (valve);
241   return ret;
242 }
243
244 static GstFlowReturn
245 gst_valve_buffer_alloc (GstPad * pad, guint64 offset, guint size,
246                         GstCaps * caps, GstBuffer ** buf)
247 {
248   GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
249   GstFlowReturn ret = GST_FLOW_OK;
250   gboolean drop;
251
252   GST_OBJECT_LOCK (GST_OBJECT (valve));
253   drop = valve->drop;
254   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
255
256   if (drop)
257     *buf = NULL;
258   else
259     ret = gst_pad_alloc_buffer (valve->srcpad, offset, size, caps, buf);
260
261   GST_OBJECT_LOCK (GST_OBJECT (valve));
262   if (valve->drop)
263     ret = GST_FLOW_OK;
264   GST_OBJECT_UNLOCK (GST_OBJECT (valve));
265
266   gst_object_unref (valve);
267
268   return ret;
269 }
270
271
272 gboolean
273 gst_valve_plugin_init (GstPlugin *plugin)
274 {
275   return gst_element_register (plugin, "fsvalve",
276       GST_RANK_MARGINAL, GST_TYPE_VALVE);
277 }
278
279 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
280     GST_VERSION_MINOR,
281     "fsvalve",
282     "Valve",
283     gst_valve_plugin_init, VERSION, "LGPL", "Farsight", "http://farsight.sf.net")
284
285 static GstCaps *
286 gst_valve_getcaps (GstPad *pad)
287 {
288   GstValve *valve = GST_VALVE (gst_pad_get_parent (pad));
289   GstCaps *caps;
290
291   if (pad == valve->sinkpad)
292     caps = gst_pad_peer_get_caps (valve->srcpad);
293   else
294     caps = gst_pad_peer_get_caps (valve->sinkpad);
295
296   if (caps == NULL)
297     caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
298
299   gst_object_unref (valve);
300
301   return caps;
302 }