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.
30 #include "../gst-i18n-lib.h"
31 #include "gstidentity.h"
32 #include <gst/gstmarshal.h>
34 GST_DEBUG_CATEGORY_STATIC (gst_identity_debug);
35 #define GST_CAT_DEFAULT gst_identity_debug
37 GstElementDetails gst_identity_details = GST_ELEMENT_DETAILS ("Identity",
39 "Pass data without modification",
40 "Erik Walthinsen <omega@cse.ogi.edu>");
43 /* Identity signals and args */
65 #define _do_init(bla) \
66 GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element");
68 GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstElement, GST_TYPE_ELEMENT,
71 static void gst_identity_finalize (GObject * object);
72 static void gst_identity_set_property (GObject * object, guint prop_id,
73 const GValue * value, GParamSpec * pspec);
74 static void gst_identity_get_property (GObject * object, guint prop_id,
75 GValue * value, GParamSpec * pspec);
77 static void gst_identity_chain (GstPad * pad, GstData * _data);
79 static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
82 gst_identity_base_init (gpointer g_class)
84 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
86 gst_element_class_set_details (gstelement_class, &gst_identity_details);
90 gst_identity_finalize (GObject * object)
92 GstIdentity *identity;
94 identity = GST_IDENTITY (object);
96 g_free (identity->last_message);
98 G_OBJECT_CLASS (parent_class)->finalize (object);
102 gst_identity_class_init (GstIdentityClass * klass)
104 GObjectClass *gobject_class;
106 gobject_class = G_OBJECT_CLASS (klass);
109 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
110 g_param_spec_boolean ("loop-based", "Loop-based",
111 "Set to TRUE to use loop-based rather than chain-based scheduling",
112 TRUE, G_PARAM_READWRITE));
113 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SLEEP_TIME,
114 g_param_spec_uint ("sleep-time", "Sleep time",
115 "Microseconds to sleep between processing", 0, G_MAXUINT, 0,
117 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUPLICATE,
118 g_param_spec_uint ("duplicate", "Duplicate Buffers",
119 "Push the buffers N times", 0, G_MAXUINT, 1, G_PARAM_READWRITE));
120 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_AFTER,
121 g_param_spec_int ("error_after", "Error After", "Error after N buffers",
122 G_MININT, G_MAXINT, -1, G_PARAM_READWRITE));
123 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DROP_PROBABILITY,
124 g_param_spec_float ("drop_probability", "Drop Probability",
125 "The Probability a buffer is dropped", 0.0, 1.0, 0.0,
127 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
128 g_param_spec_boolean ("silent", "silent", "silent", FALSE,
130 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
131 g_param_spec_string ("last-message", "last-message", "last-message", NULL,
133 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
134 g_param_spec_boolean ("dump", "Dump", "Dump buffer contents", FALSE,
137 gst_identity_signals[SIGNAL_HANDOFF] =
138 g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
139 G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
140 gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, GST_TYPE_BUFFER);
142 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_identity_finalize);
143 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
144 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
148 gst_identity_init (GstIdentity * identity)
150 identity->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
151 gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
152 gst_pad_set_chain_function (identity->sinkpad,
153 GST_DEBUG_FUNCPTR (gst_identity_chain));
154 gst_pad_set_link_function (identity->sinkpad, gst_pad_proxy_pad_link);
155 gst_pad_set_getcaps_function (identity->sinkpad, gst_pad_proxy_getcaps);
157 identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
158 gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
159 gst_pad_set_link_function (identity->srcpad, gst_pad_proxy_pad_link);
160 gst_pad_set_getcaps_function (identity->srcpad, gst_pad_proxy_getcaps);
162 identity->loop_based = FALSE;
163 identity->sleep_time = 0;
164 identity->duplicate = 1;
165 identity->error_after = -1;
166 identity->drop_probability = 0.0;
167 identity->silent = FALSE;
168 identity->dump = FALSE;
169 identity->last_message = NULL;
170 identity->srccaps = NULL;
174 gst_identity_chain (GstPad * pad, GstData * _data)
176 GstBuffer *buf = GST_BUFFER (_data);
177 GstIdentity *identity;
180 g_return_if_fail (pad != NULL);
181 g_return_if_fail (GST_IS_PAD (pad));
182 g_return_if_fail (buf != NULL);
184 identity = GST_IDENTITY (gst_pad_get_parent (pad));
186 if (identity->error_after >= 0) {
187 identity->error_after--;
188 if (identity->error_after == 0) {
189 gst_buffer_unref (buf);
190 GST_ELEMENT_ERROR (identity, CORE, FAILED,
191 (_("Failed after iterations as requested.")), (NULL));
196 if (identity->drop_probability > 0.0) {
197 if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) {
198 g_free (identity->last_message);
199 identity->last_message =
200 g_strdup_printf ("dropping ******* (%s:%s)i (%d bytes, %"
201 G_GINT64_FORMAT ")", GST_DEBUG_PAD_NAME (identity->sinkpad),
202 GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
203 g_object_notify (G_OBJECT (identity), "last-message");
204 gst_buffer_unref (buf);
208 if (identity->dump) {
209 gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
212 for (i = identity->duplicate; i; i--) {
213 if (!identity->silent) {
214 g_free (identity->last_message);
215 identity->last_message =
216 g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, %"
217 GST_TIME_FORMAT ")", GST_DEBUG_PAD_NAME (identity->sinkpad),
218 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
219 g_object_notify (G_OBJECT (identity), "last-message");
222 g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
226 gst_buffer_ref (buf);
228 gst_pad_push (identity->srcpad, GST_DATA (buf));
230 if (identity->sleep_time)
231 g_usleep (identity->sleep_time);
236 gst_identity_loop (GstElement * element)
238 GstIdentity *identity;
241 g_return_if_fail (element != NULL);
242 g_return_if_fail (GST_IS_IDENTITY (element));
244 identity = GST_IDENTITY (element);
246 buf = GST_BUFFER (gst_pad_pull (identity->sinkpad));
247 if (GST_IS_EVENT (buf)) {
248 GstEvent *event = GST_EVENT (buf);
250 if (GST_EVENT_IS_INTERRUPT (event)) {
251 gst_event_unref (event);
253 gst_pad_event_default (identity->sinkpad, event);
256 gst_identity_chain (identity->sinkpad, GST_DATA (buf));
261 gst_identity_set_property (GObject * object, guint prop_id,
262 const GValue * value, GParamSpec * pspec)
264 GstIdentity *identity;
266 /* it's not null if we got it, but it might not be ours */
267 g_return_if_fail (GST_IS_IDENTITY (object));
269 identity = GST_IDENTITY (object);
273 identity->loop_based = g_value_get_boolean (value);
274 if (identity->loop_based) {
275 gst_element_set_loop_function (GST_ELEMENT (identity),
277 gst_pad_set_chain_function (identity->sinkpad, NULL);
279 gst_pad_set_chain_function (identity->sinkpad, gst_identity_chain);
280 gst_element_set_loop_function (GST_ELEMENT (identity), NULL);
284 identity->sleep_time = g_value_get_uint (value);
287 identity->silent = g_value_get_boolean (value);
290 identity->duplicate = g_value_get_uint (value);
293 identity->dump = g_value_get_boolean (value);
295 case ARG_ERROR_AFTER:
296 identity->error_after = g_value_get_int (value);
298 case ARG_DROP_PROBABILITY:
299 identity->drop_probability = g_value_get_float (value);
302 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
308 gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
311 GstIdentity *identity;
313 /* it's not null if we got it, but it might not be ours */
314 g_return_if_fail (GST_IS_IDENTITY (object));
316 identity = GST_IDENTITY (object);
320 g_value_set_boolean (value, identity->loop_based);
323 g_value_set_uint (value, identity->sleep_time);
326 g_value_set_uint (value, identity->duplicate);
328 case ARG_ERROR_AFTER:
329 g_value_set_int (value, identity->error_after);
331 case ARG_DROP_PROBABILITY:
332 g_value_set_float (value, identity->drop_probability);
335 g_value_set_boolean (value, identity->silent);
338 g_value_set_boolean (value, identity->dump);
340 case ARG_LAST_MESSAGE:
341 g_value_set_string (value, identity->last_message);
344 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);