3 * Copyright (C) 2015 Vivia Nikolaidou <vivia@toolsonair.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * SECTION:element-errorignore
25 * Passes through all packets, until it encounters GST_FLOW_ERROR or
26 * GST_FLOW_NOT_NEGOTIATED (configurable). At that point it will unref the
27 * buffers and return GST_FLOW_OK (configurable) - until the next
28 * READY_TO_PAUSED, RECONFIGURE or FLUSH_STOP.
30 * ## Example launch line
32 * gst-launch-1.0 videotestsrc ! errorignore ! autovideosink
41 #include "gstdebugutilsbadelements.h"
42 #include "gsterrorignore.h"
44 #define GST_CAT_DEFAULT gst_error_ignore_debug
45 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
51 PROP_IGNORE_NOTLINKED,
52 PROP_IGNORE_NOTNEGOTIATED,
57 static void gst_error_ignore_set_property (GObject * object, guint prop_id,
58 const GValue * value, GParamSpec * pspec);
59 static void gst_error_ignore_get_property (GObject * object, guint prop_id,
60 GValue * value, GParamSpec * pspec);
62 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
67 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
72 #define parent_class gst_error_ignore_parent_class
73 G_DEFINE_TYPE (GstErrorIgnore, gst_error_ignore, GST_TYPE_ELEMENT);
74 GST_ELEMENT_REGISTER_DEFINE (errorignore, "errorignore",
75 GST_RANK_NONE, gst_error_ignore_get_type ());
77 static GstFlowReturn gst_error_ignore_sink_chain (GstPad * pad,
78 GstObject * parent, GstBuffer * inbuf);
79 static gboolean gst_error_ignore_sink_event (GstPad * pad, GstObject * parent,
81 static GstStateChangeReturn gst_error_ignore_change_state (GstElement * element,
82 GstStateChange transition);
85 gst_error_ignore_class_init (GstErrorIgnoreClass * klass)
87 GstElementClass *gstelement_class;
88 GObjectClass *object_class = G_OBJECT_CLASS (klass);
90 GST_DEBUG_CATEGORY_INIT (gst_error_ignore_debug, "errorignore", 0,
91 "Convert some GstFlowReturn types into others");
93 gstelement_class = (GstElementClass *) klass;
95 gst_element_class_set_static_metadata (gstelement_class,
96 "Convert some GstFlowReturn types into others", "Generic",
97 "Pass through all packets but ignore some GstFlowReturn types",
98 "Vivia Nikolaidou <vivia@toolsonair.com>");
100 gst_element_class_add_static_pad_template (gstelement_class, &src_template);
101 gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
103 gstelement_class->change_state = gst_error_ignore_change_state;
105 /* define virtual function pointers */
106 object_class->set_property = gst_error_ignore_set_property;
107 object_class->get_property = gst_error_ignore_get_property;
109 /* define properties */
110 g_object_class_install_property (object_class, PROP_IGNORE_ERROR,
111 g_param_spec_boolean ("ignore-error", "Ignore GST_FLOW_ERROR",
112 "Whether to ignore GST_FLOW_ERROR",
113 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
115 g_object_class_install_property (object_class, PROP_IGNORE_NOTLINKED,
116 g_param_spec_boolean ("ignore-notlinked", "Ignore GST_FLOW_NOT_LINKED",
117 "Whether to ignore GST_FLOW_NOT_LINKED",
118 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
120 g_object_class_install_property (object_class, PROP_IGNORE_NOTNEGOTIATED,
121 g_param_spec_boolean ("ignore-notnegotiated",
122 "Ignore GST_FLOW_NOT_NEGOTIATED",
123 "Whether to ignore GST_FLOW_NOT_NEGOTIATED",
124 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
127 * GstErrorIgnore:ignore-eos:
131 g_object_class_install_property (object_class, PROP_IGNORE_EOS,
132 g_param_spec_boolean ("ignore-eos",
133 "Ignore GST_FLOW_EOS", "Whether to ignore GST_FLOW_EOS",
134 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
136 g_object_class_install_property (object_class, PROP_CONVERT_TO,
137 g_param_spec_enum ("convert-to", "GstFlowReturn to convert to",
138 "Which GstFlowReturn value we should convert to when ignoring",
139 GST_TYPE_FLOW_RETURN,
140 GST_FLOW_NOT_LINKED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
144 gst_error_ignore_init (GstErrorIgnore * self)
146 self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
147 gst_pad_set_chain_function (self->sinkpad,
148 GST_DEBUG_FUNCPTR (gst_error_ignore_sink_chain));
149 gst_pad_set_event_function (self->sinkpad,
150 GST_DEBUG_FUNCPTR (gst_error_ignore_sink_event));
151 GST_PAD_SET_PROXY_ALLOCATION (self->sinkpad);
152 GST_PAD_SET_PROXY_CAPS (self->sinkpad);
153 GST_PAD_SET_PROXY_SCHEDULING (self->sinkpad);
154 gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
156 self->srcpad = gst_pad_new_from_static_template (&src_template, "src");
157 gst_pad_use_fixed_caps (self->srcpad);
158 GST_PAD_SET_PROXY_ALLOCATION (self->srcpad);
159 GST_PAD_SET_PROXY_CAPS (self->srcpad);
160 GST_PAD_SET_PROXY_SCHEDULING (self->srcpad);
161 gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
163 self->keep_pushing = TRUE;
164 self->ignore_error = TRUE;
165 self->ignore_notlinked = FALSE;
166 self->ignore_notnegotiated = TRUE;
167 self->ignore_eos = FALSE;
168 self->convert_to = GST_FLOW_NOT_LINKED;
172 gst_error_ignore_set_property (GObject * object, guint prop_id,
173 const GValue * value, GParamSpec * pspec)
175 GstErrorIgnore *self = GST_ERROR_IGNORE (object);
178 case PROP_IGNORE_ERROR:
179 self->ignore_error = g_value_get_boolean (value);
181 case PROP_IGNORE_NOTLINKED:
182 self->ignore_notlinked = g_value_get_boolean (value);
184 case PROP_IGNORE_NOTNEGOTIATED:
185 self->ignore_notnegotiated = g_value_get_boolean (value);
187 case PROP_IGNORE_EOS:
188 self->ignore_eos = g_value_get_boolean (value);
190 case PROP_CONVERT_TO:
191 self->convert_to = g_value_get_enum (value);
194 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
200 gst_error_ignore_get_property (GObject * object, guint prop_id, GValue * value,
203 GstErrorIgnore *self = GST_ERROR_IGNORE (object);
206 case PROP_IGNORE_ERROR:
207 g_value_set_boolean (value, self->ignore_error);
209 case PROP_IGNORE_NOTLINKED:
210 g_value_set_boolean (value, self->ignore_notlinked);
212 case PROP_IGNORE_NOTNEGOTIATED:
213 g_value_set_boolean (value, self->ignore_notnegotiated);
215 case PROP_IGNORE_EOS:
216 g_value_set_boolean (value, self->ignore_eos);
218 case PROP_CONVERT_TO:
219 g_value_set_enum (value, self->convert_to);
222 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
228 gst_error_ignore_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
230 GstErrorIgnore *self = GST_ERROR_IGNORE (parent);
233 GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event));
235 switch (GST_EVENT_TYPE (event)) {
237 case GST_EVENT_FLUSH_STOP:
238 self->keep_pushing = TRUE;
241 ret = gst_pad_event_default (pad, parent, event);
249 gst_error_ignore_sink_chain (GstPad * pad, GstObject * parent,
252 GstErrorIgnore *self = GST_ERROR_IGNORE (parent);
253 GstFlowReturn ret = GST_FLOW_OK;
255 if (gst_pad_check_reconfigure (pad))
256 self->keep_pushing = TRUE;
258 if (self->keep_pushing) {
259 ret = gst_pad_push (self->srcpad, inbuf);
260 self->keep_pushing = (ret == GST_FLOW_OK);
262 gst_buffer_unref (inbuf);
265 if ((ret == GST_FLOW_ERROR && self->ignore_error) ||
266 (ret == GST_FLOW_NOT_LINKED && self->ignore_notlinked) ||
267 (ret == GST_FLOW_EOS && self->ignore_eos) ||
268 (ret == GST_FLOW_NOT_NEGOTIATED && self->ignore_notnegotiated))
269 return self->convert_to;
274 static GstStateChangeReturn
275 gst_error_ignore_change_state (GstElement * element, GstStateChange transition)
277 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
278 GstErrorIgnore *self = GST_ERROR_IGNORE (element);
280 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
281 if (ret == GST_STATE_CHANGE_FAILURE)
284 switch (transition) {
285 case GST_STATE_CHANGE_READY_TO_PAUSED:
286 self->keep_pushing = TRUE;