Branch data Line data Source code
1 : : /* GStreamer valve element
2 : : * Copyright 2007-2009 Collabora Ltd
3 : : * @author: Olivier Crete <olivier.crete@collabora.co.uk>
4 : : * Copyright 2007-2009 Nokia Corporation
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Library General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Library General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Library General Public
17 : : * License along with this library; if not, write to the
18 : : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 : : * Boston, MA 02111-1307, USA.
20 : : *
21 : : */
22 : :
23 : : /**
24 : : * SECTION:element-valve
25 : : *
26 : : * The valve is a simple element that drops buffers when the #GstValve:drop
27 : : * property is set to %TRUE and lets then through otherwise.
28 : : *
29 : : * Any downstream error received while the #GstValve:drop property is %FALSE
30 : : * is ignored. So downstream element can be set to %GST_STATE_NULL and removed,
31 : : * without using pad blocking.
32 : : *
33 : : * This element was previously part of gst-plugins-farsight, and then
34 : : * gst-plugins-bad.
35 : : *
36 : : * Documentation last reviewed on 2010-12-30 (0.10.31)
37 : : *
38 : : * Since: 0.10.32
39 : : */
40 : :
41 : : #ifdef HAVE_CONFIG_H
42 : : #include "config.h"
43 : : #endif
44 : :
45 : : #include "gstvalve.h"
46 : :
47 : : #include <string.h>
48 : :
49 : : GST_DEBUG_CATEGORY_STATIC (valve_debug);
50 : : #define GST_CAT_DEFAULT (valve_debug)
51 : :
52 : : static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
53 : : GST_PAD_SINK,
54 : : GST_PAD_ALWAYS,
55 : : GST_STATIC_CAPS_ANY);
56 : :
57 : : static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
58 : : GST_PAD_SRC,
59 : : GST_PAD_ALWAYS,
60 : : GST_STATIC_CAPS_ANY);
61 : :
62 : : enum
63 : : {
64 : : PROP_0,
65 : : PROP_DROP
66 : : };
67 : :
68 : : #define DEFAULT_DROP FALSE
69 : :
70 : : static void gst_valve_set_property (GObject * object,
71 : : guint prop_id, const GValue * value, GParamSpec * pspec);
72 : : static void gst_valve_get_property (GObject * object,
73 : : guint prop_id, GValue * value, GParamSpec * pspec);
74 : :
75 : : static gboolean gst_valve_event (GstPad * pad, GstEvent * event);
76 : : static GstFlowReturn gst_valve_buffer_alloc (GstPad * pad, guint64 offset,
77 : : guint size, GstCaps * caps, GstBuffer ** buf);
78 : : static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer);
79 : : static GstCaps *gst_valve_getcaps (GstPad * pad);
80 : :
81 : : #define _do_init(bla) \
82 : : GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve");
83 : :
84 [ + + ][ + - ]: 174 : GST_BOILERPLATE_FULL (GstValve, gst_valve, GstElement,
85 : 174 : GST_TYPE_ELEMENT, _do_init);
86 : :
87 : : static void
88 : 9 : gst_valve_base_init (gpointer klass)
89 : : {
90 : 9 : GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
91 : :
92 : 9 : gst_element_class_add_pad_template (element_class,
93 : : gst_static_pad_template_get (&srctemplate));
94 : 9 : gst_element_class_add_pad_template (element_class,
95 : : gst_static_pad_template_get (&sinktemplate));
96 : :
97 : 9 : gst_element_class_set_details_simple (element_class, "Valve element",
98 : : "Filter", "Drops buffers and events or lets them through",
99 : : "Olivier Crete <olivier.crete@collabora.co.uk>");
100 : 9 : }
101 : :
102 : : static void
103 : 9 : gst_valve_class_init (GstValveClass * klass)
104 : : {
105 : : GObjectClass *gobject_class;
106 : :
107 : 9 : gobject_class = (GObjectClass *) klass;
108 : :
109 : 9 : gobject_class->set_property = gst_valve_set_property;
110 : 9 : gobject_class->get_property = gst_valve_get_property;
111 : :
112 : 9 : g_object_class_install_property (gobject_class, PROP_DROP,
113 : : g_param_spec_boolean ("drop", "Drop buffers and events",
114 : : "Whether to drop buffers and events or let them through",
115 : : DEFAULT_DROP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
116 : 9 : }
117 : :
118 : : static void
119 : 4 : gst_valve_init (GstValve * valve, GstValveClass * klass)
120 : : {
121 : 4 : valve->drop = FALSE;
122 : 4 : valve->discont = FALSE;
123 : :
124 : 4 : valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
125 : 4 : gst_pad_set_getcaps_function (valve->srcpad,
126 : 4 : GST_DEBUG_FUNCPTR (gst_valve_getcaps));
127 : 4 : gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad);
128 : :
129 : 4 : valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
130 : 4 : gst_pad_set_chain_function (valve->sinkpad,
131 : 4 : GST_DEBUG_FUNCPTR (gst_valve_chain));
132 : 4 : gst_pad_set_event_function (valve->sinkpad,
133 : 4 : GST_DEBUG_FUNCPTR (gst_valve_event));
134 : 4 : gst_pad_set_bufferalloc_function (valve->sinkpad,
135 : 4 : GST_DEBUG_FUNCPTR (gst_valve_buffer_alloc));
136 : 4 : gst_pad_set_getcaps_function (valve->sinkpad,
137 : 4 : GST_DEBUG_FUNCPTR (gst_valve_getcaps));
138 : 4 : gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad);
139 : 4 : }
140 : :
141 : :
142 : : static void
143 : 2 : gst_valve_set_property (GObject * object,
144 : : guint prop_id, const GValue * value, GParamSpec * pspec)
145 : : {
146 : 2 : GstValve *valve = GST_VALVE (object);
147 : :
148 [ + - ]: 2 : switch (prop_id) {
149 : : case PROP_DROP:
150 : 2 : g_atomic_int_set (&valve->drop, g_value_get_boolean (value));
151 : 2 : break;
152 : : default:
153 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
154 : 0 : break;
155 : : }
156 : 2 : }
157 : :
158 : : static void
159 : 0 : gst_valve_get_property (GObject * object,
160 : : guint prop_id, GValue * value, GParamSpec * pspec)
161 : : {
162 : 0 : GstValve *valve = GST_VALVE (object);
163 : :
164 [ # # ]: 0 : switch (prop_id) {
165 : : case PROP_DROP:
166 : 0 : g_value_set_boolean (value, g_atomic_int_get (&valve->drop));
167 : 0 : break;
168 : : default:
169 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
170 : 0 : break;
171 : : }
172 : 0 : }
173 : :
174 : : static GstFlowReturn
175 : 4 : gst_valve_chain (GstPad * pad, GstBuffer * buffer)
176 : : {
177 : 4 : GstValve *valve = GST_VALVE (GST_OBJECT_PARENT (pad));
178 : 4 : GstFlowReturn ret = GST_FLOW_OK;
179 : :
180 [ + + ]: 4 : if (g_atomic_int_get (&valve->drop)) {
181 : 2 : gst_buffer_unref (buffer);
182 : 2 : valve->discont = TRUE;
183 : : } else {
184 [ - + ]: 2 : if (valve->discont) {
185 : 0 : buffer = gst_buffer_make_metadata_writable (buffer);
186 : 0 : GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
187 : 0 : valve->discont = FALSE;
188 : : }
189 : :
190 : 2 : ret = gst_pad_push (valve->srcpad, buffer);
191 : : }
192 : :
193 : :
194 : : /* Ignore errors if "drop" was changed while the thread was blocked
195 : : * downwards
196 : : */
197 [ + + ]: 4 : if (g_atomic_int_get (&valve->drop))
198 : 2 : ret = GST_FLOW_OK;
199 : :
200 : 4 : return ret;
201 : : }
202 : :
203 : :
204 : : static gboolean
205 : 2 : gst_valve_event (GstPad * pad, GstEvent * event)
206 : : {
207 : 2 : GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
208 : 2 : gboolean ret = TRUE;
209 : :
210 [ + + ]: 2 : if (g_atomic_int_get (&valve->drop))
211 : 1 : gst_event_unref (event);
212 : : else
213 : 1 : ret = gst_pad_push_event (valve->srcpad, event);
214 : :
215 : : /* Ignore errors if "drop" was changed while the thread was blocked
216 : : * downwards.
217 : : */
218 [ + + ]: 2 : if (g_atomic_int_get (&valve->drop))
219 : 1 : ret = TRUE;
220 : :
221 : 2 : gst_object_unref (valve);
222 : 2 : return ret;
223 : : }
224 : :
225 : : static GstFlowReturn
226 : 2 : gst_valve_buffer_alloc (GstPad * pad, guint64 offset, guint size,
227 : : GstCaps * caps, GstBuffer ** buf)
228 : : {
229 : 2 : GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
230 : 2 : GstFlowReturn ret = GST_FLOW_OK;
231 : :
232 [ + + ]: 2 : if (g_atomic_int_get (&valve->drop))
233 : 1 : *buf = NULL;
234 : : else
235 : 1 : ret = gst_pad_alloc_buffer (valve->srcpad, offset, size, caps, buf);
236 : :
237 : : /* Ignore errors if "drop" was changed while the thread was blocked
238 : : * downwards
239 : : */
240 [ + + ]: 2 : if (g_atomic_int_get (&valve->drop))
241 : 1 : ret = GST_FLOW_OK;
242 : :
243 : 2 : gst_object_unref (valve);
244 : :
245 : 2 : return ret;
246 : : }
247 : :
248 : : static GstCaps *
249 : 2 : gst_valve_getcaps (GstPad * pad)
250 : : {
251 : 2 : GstValve *valve = GST_VALVE (gst_pad_get_parent (pad));
252 : : GstCaps *caps;
253 : :
254 [ + + ]: 2 : if (pad == valve->sinkpad)
255 : 1 : caps = gst_pad_peer_get_caps (valve->srcpad);
256 : : else
257 : 1 : caps = gst_pad_peer_get_caps (valve->sinkpad);
258 : :
259 [ + + ]: 2 : if (caps == NULL)
260 : 1 : caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
261 : :
262 : 2 : gst_object_unref (valve);
263 : :
264 : 2 : return caps;
265 : : }
|