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, %llu)",
224 GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
225 g_object_notify (G_OBJECT (identity), "last-message");
226 gst_buffer_unref (buf);
230 if (identity->dump) {
231 gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
234 for (i = identity->duplicate; i; i--) {
235 if (!identity->silent) {
236 g_free (identity->last_message);
237 identity->last_message = g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, %llu)",
238 GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
239 g_object_notify (G_OBJECT (identity), "last-message");
242 g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
246 gst_buffer_ref (buf);
248 gst_pad_push (identity->srcpad, buf);
250 if (identity->sleep_time)
251 usleep (identity->sleep_time);
256 gst_identity_loop (GstElement *element)
258 GstIdentity *identity;
261 g_return_if_fail (element != NULL);
262 g_return_if_fail (GST_IS_IDENTITY (element));
264 identity = GST_IDENTITY (element);
266 buf = gst_pad_pull (identity->sinkpad);
267 if (GST_IS_EVENT (buf)) {
268 GstEvent *event = GST_EVENT (buf);
270 if (GST_EVENT_IS_INTERRUPT (event)) {
271 gst_event_unref (event);
274 gst_pad_event_default (identity->sinkpad, event);
278 gst_identity_chain (identity->sinkpad, buf);
283 gst_identity_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
285 GstIdentity *identity;
287 /* it's not null if we got it, but it might not be ours */
288 g_return_if_fail (GST_IS_IDENTITY (object));
290 identity = GST_IDENTITY (object);
294 identity->loop_based = g_value_get_boolean (value);
295 if (identity->loop_based) {
296 gst_element_set_loop_function (GST_ELEMENT (identity), gst_identity_loop);
297 gst_pad_set_chain_function (identity->sinkpad, NULL);
300 gst_pad_set_chain_function (identity->sinkpad, gst_identity_chain);
301 gst_element_set_loop_function (GST_ELEMENT (identity), NULL);
305 identity->sleep_time = g_value_get_uint (value);
308 identity->silent = g_value_get_boolean (value);
311 identity->duplicate = g_value_get_uint (value);
314 identity->dump = g_value_get_boolean (value);
316 case ARG_ERROR_AFTER:
317 identity->error_after = g_value_get_int (value);
319 case ARG_DROP_PROBABILITY:
320 identity->drop_probability = g_value_get_float (value);
327 static void gst_identity_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
328 GstIdentity *identity;
330 /* it's not null if we got it, but it might not be ours */
331 g_return_if_fail (GST_IS_IDENTITY (object));
333 identity = GST_IDENTITY (object);
337 g_value_set_boolean (value, identity->loop_based);
340 g_value_set_uint (value, identity->sleep_time);
343 g_value_set_uint (value, identity->duplicate);
345 case ARG_ERROR_AFTER:
346 g_value_set_int (value, identity->error_after);
348 case ARG_DROP_PROBABILITY:
349 g_value_set_float (value, identity->drop_probability);
352 g_value_set_boolean (value, identity->silent);
355 g_value_set_boolean (value, identity->dump);
357 case ARG_LAST_MESSAGE:
358 g_value_set_string (value, identity->last_message);
361 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);