2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 #include <gstidentity.h>
28 GstElementDetails gst_identity_details = {
32 "Pass data without modification",
34 "Erik Walthinsen <omega@cse.ogi.edu>",
39 /* Identity signals and args */
59 static void gst_identity_class_init (GstIdentityClass *klass);
60 static void gst_identity_init (GstIdentity *identity);
62 static void gst_identity_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
63 static void gst_identity_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
65 static void gst_identity_chain (GstPad *pad, GstBuffer *buf);
67 static GstElementClass *parent_class = NULL;
68 static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
71 gst_identity_get_type (void)
73 static GType identity_type = 0;
76 static const GTypeInfo identity_info = {
77 sizeof(GstIdentityClass), NULL,
79 (GClassInitFunc)gst_identity_class_init,
84 (GInstanceInitFunc)gst_identity_init,
86 identity_type = g_type_register_static (GST_TYPE_ELEMENT, "GstIdentity", &identity_info, 0);
92 gst_identity_class_init (GstIdentityClass *klass)
94 GObjectClass *gobject_class;
96 gobject_class = (GObjectClass*)klass;
98 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
100 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
101 g_param_spec_boolean ("loop-based", "Loop-based", "Set to TRUE to use loop-based rather than chain-based scheduling",
102 TRUE, G_PARAM_READWRITE));
103 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SLEEP_TIME,
104 g_param_spec_uint ("sleep-time", "Sleep time", "Microseconds to sleep between processing",
105 0, G_MAXUINT, 0, G_PARAM_READWRITE));
106 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUPLICATE,
107 g_param_spec_uint ("duplicate", "Duplicate Buffers", "Push the buffers N times",
108 0, G_MAXUINT, 1, G_PARAM_READWRITE));
109 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_AFTER,
110 g_param_spec_int ("error_after", "Error After", "Error after N buffers",
111 G_MININT, G_MAXINT, -1, G_PARAM_READWRITE));
112 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DROP_PROBABILITY,
113 g_param_spec_float ("drop_probability", "Drop Probability", "The Probability a buffer is dropped",
114 0.0, 1.0, 0.0, G_PARAM_READWRITE));
115 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
116 g_param_spec_boolean ("silent", "silent", "silent",
117 FALSE, G_PARAM_READWRITE));
118 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
119 g_param_spec_string ("last-message", "last-message", "last-message",
120 NULL, G_PARAM_READABLE));
121 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
122 g_param_spec_boolean("dump","Dump","Dump buffer contents",
123 FALSE, G_PARAM_READWRITE));
125 gst_identity_signals[SIGNAL_HANDOFF] =
126 g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
127 G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
128 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
131 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
132 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
135 static GstBufferPool*
136 gst_identity_get_bufferpool (GstPad *pad)
138 GstIdentity *identity;
140 identity = GST_IDENTITY (gst_pad_get_parent (pad));
142 return gst_pad_get_bufferpool (identity->srcpad);
146 gst_identity_getcaps (GstPad *pad, GstCaps *caps)
148 GstIdentity *identity;
151 identity = GST_IDENTITY (gst_pad_get_parent (pad));
152 otherpad = (pad == identity->srcpad ? identity->sinkpad : identity->srcpad);
154 return gst_pad_get_allowed_caps (otherpad);
157 static GstPadLinkReturn
158 gst_identity_link (GstPad *pad, GstCaps *caps)
160 GstIdentity *identity;
163 identity = GST_IDENTITY (gst_pad_get_parent (pad));
164 otherpad = (pad == identity->srcpad ? identity->sinkpad : identity->srcpad);
166 if (GST_CAPS_IS_FIXED (caps))
167 return gst_pad_try_set_caps (otherpad, caps);
169 return GST_PAD_LINK_DELAYED;
173 gst_identity_init (GstIdentity *identity)
175 identity->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
176 gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
177 gst_pad_set_chain_function (identity->sinkpad, GST_DEBUG_FUNCPTR (gst_identity_chain));
178 gst_pad_set_bufferpool_function (identity->sinkpad, gst_identity_get_bufferpool);
179 gst_pad_set_link_function (identity->sinkpad, gst_identity_link);
180 gst_pad_set_getcaps_function (identity->sinkpad, gst_identity_getcaps);
182 identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
183 gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
184 gst_pad_set_link_function (identity->srcpad, gst_identity_link);
185 gst_pad_set_getcaps_function (identity->srcpad, gst_identity_getcaps);
187 identity->loop_based = FALSE;
188 identity->sleep_time = 0;
189 identity->duplicate = 1;
190 identity->error_after = -1;
191 identity->drop_probability = 0.0;
192 identity->silent = FALSE;
193 identity->dump = FALSE;
194 identity->last_message = NULL;
198 gst_identity_chain (GstPad *pad, GstBuffer *buf)
200 GstIdentity *identity;
203 g_return_if_fail (pad != NULL);
204 g_return_if_fail (GST_IS_PAD (pad));
205 g_return_if_fail (buf != NULL);
207 identity = GST_IDENTITY (gst_pad_get_parent (pad));
209 if (identity->error_after >= 0) {
210 identity->error_after--;
211 if (identity->error_after == 0) {
212 gst_buffer_unref (buf);
213 gst_element_error (GST_ELEMENT (identity), "errored after iterations as requested");
218 if (identity->drop_probability > 0.0) {
219 if ((gfloat)(1.0*rand()/(RAND_MAX)) < identity->drop_probability) {
220 if (identity->last_message != NULL) {
221 g_free (identity->last_message);
223 identity->last_message = g_strdup_printf ("dropping ******* (%s:%s)i (%d bytes, %"
225 GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
226 g_object_notify (G_OBJECT (identity), "last-message");
227 gst_buffer_unref (buf);
231 if (identity->dump) {
232 gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
235 for (i = identity->duplicate; i; i--) {
236 if (!identity->silent) {
237 g_free (identity->last_message);
238 identity->last_message = g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, %"
240 GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
241 g_object_notify (G_OBJECT (identity), "last-message");
244 g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
248 gst_buffer_ref (buf);
250 gst_pad_push (identity->srcpad, buf);
252 if (identity->sleep_time)
253 usleep (identity->sleep_time);
258 gst_identity_loop (GstElement *element)
260 GstIdentity *identity;
263 g_return_if_fail (element != NULL);
264 g_return_if_fail (GST_IS_IDENTITY (element));
266 identity = GST_IDENTITY (element);
268 buf = gst_pad_pull (identity->sinkpad);
269 if (GST_IS_EVENT (buf)) {
270 GstEvent *event = GST_EVENT (buf);
272 if (GST_EVENT_IS_INTERRUPT (event)) {
273 gst_event_unref (event);
276 gst_pad_event_default (identity->sinkpad, event);
280 gst_identity_chain (identity->sinkpad, buf);
285 gst_identity_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
287 GstIdentity *identity;
289 /* it's not null if we got it, but it might not be ours */
290 g_return_if_fail (GST_IS_IDENTITY (object));
292 identity = GST_IDENTITY (object);
296 identity->loop_based = g_value_get_boolean (value);
297 if (identity->loop_based) {
298 gst_element_set_loop_function (GST_ELEMENT (identity), gst_identity_loop);
299 gst_pad_set_chain_function (identity->sinkpad, NULL);
302 gst_pad_set_chain_function (identity->sinkpad, gst_identity_chain);
303 gst_element_set_loop_function (GST_ELEMENT (identity), NULL);
307 identity->sleep_time = g_value_get_uint (value);
310 identity->silent = g_value_get_boolean (value);
313 identity->duplicate = g_value_get_uint (value);
316 identity->dump = g_value_get_boolean (value);
318 case ARG_ERROR_AFTER:
319 identity->error_after = g_value_get_int (value);
321 case ARG_DROP_PROBABILITY:
322 identity->drop_probability = g_value_get_float (value);
329 static void gst_identity_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
330 GstIdentity *identity;
332 /* it's not null if we got it, but it might not be ours */
333 g_return_if_fail (GST_IS_IDENTITY (object));
335 identity = GST_IDENTITY (object);
339 g_value_set_boolean (value, identity->loop_based);
342 g_value_set_uint (value, identity->sleep_time);
345 g_value_set_uint (value, identity->duplicate);
347 case ARG_ERROR_AFTER:
348 g_value_set_int (value, identity->error_after);
350 case ARG_DROP_PROBABILITY:
351 g_value_set_float (value, identity->drop_probability);
354 g_value_set_boolean (value, identity->silent);
357 g_value_set_boolean (value, identity->dump);
359 case ARG_LAST_MESSAGE:
360 g_value_set_string (value, identity->last_message);
363 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);