]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/blob - plugins/elements/gstidentity.c
b80c1a275b82729b6f5907909c639a257d60e316
[glsdk/gstreamer0-10.git] / plugins / elements / gstidentity.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *                    2005 Wim Taymans <wim@fluendo.com>
5  *
6  * gstidentity.c: 
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
25 #include <stdlib.h>
27 #ifdef HAVE_CONFIG_H
28 #  include "config.h"
29 #endif
31 #include "../gst-i18n-lib.h"
32 #include "gstidentity.h"
33 #include <gst/gstmarshal.h>
35 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
36     GST_PAD_SINK,
37     GST_PAD_ALWAYS,
38     GST_STATIC_CAPS_ANY);
40 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
41     GST_PAD_SRC,
42     GST_PAD_ALWAYS,
43     GST_STATIC_CAPS_ANY);
45 GST_DEBUG_CATEGORY_STATIC (gst_identity_debug);
46 #define GST_CAT_DEFAULT gst_identity_debug
48 GstElementDetails gst_identity_details = GST_ELEMENT_DETAILS ("Identity",
49     "Generic",
50     "Pass data without modification",
51     "Erik Walthinsen <omega@cse.ogi.edu>");
54 /* Identity signals and args */
55 enum
56 {
57   SIGNAL_HANDOFF,
58   /* FILL ME */
59   LAST_SIGNAL
60 };
62 #define DEFAULT_SLEEP_TIME              0
63 #define DEFAULT_DUPLICATE               1
64 #define DEFAULT_ERROR_AFTER             -1
65 #define DEFAULT_DROP_PROBABILITY        0.0
66 #define DEFAULT_DATARATE                0
67 #define DEFAULT_SILENT                  FALSE
68 #define DEFAULT_DUMP                    FALSE
69 #define DEFAULT_SYNC                    FALSE
70 #define DEFAULT_CHECK_PERFECT           FALSE
72 enum
73 {
74   PROP_0,
75   PROP_SLEEP_TIME,
76   PROP_DUPLICATE,
77   PROP_ERROR_AFTER,
78   PROP_DROP_PROBABILITY,
79   PROP_DATARATE,
80   PROP_SILENT,
81   PROP_LAST_MESSAGE,
82   PROP_DUMP,
83   PROP_SYNC,
84   PROP_CHECK_PERFECT
85 };
88 #define _do_init(bla) \
89     GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element");
91 GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstBaseTransform,
92     GST_TYPE_BASE_TRANSFORM, _do_init);
94 static void gst_identity_finalize (GObject * object);
95 static void gst_identity_set_property (GObject * object, guint prop_id,
96     const GValue * value, GParamSpec * pspec);
97 static void gst_identity_get_property (GObject * object, guint prop_id,
98     GValue * value, GParamSpec * pspec);
100 static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
101 static GstFlowReturn gst_identity_transform (GstBaseTransform * trans,
102     GstBuffer * inbuf, GstBuffer ** outbuf);
103 static gboolean gst_identity_start (GstBaseTransform * trans);
104 static gboolean gst_identity_stop (GstBaseTransform * trans);
106 static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
108 static void
109 gst_identity_base_init (gpointer g_class)
111   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
113   gst_element_class_add_pad_template (gstelement_class,
114       gst_static_pad_template_get (&srctemplate));
115   gst_element_class_add_pad_template (gstelement_class,
116       gst_static_pad_template_get (&sinktemplate));
117   gst_element_class_set_details (gstelement_class, &gst_identity_details);
120 static void
121 gst_identity_finalize (GObject * object)
123   GstIdentity *identity;
125   identity = GST_IDENTITY (object);
127   g_free (identity->last_message);
129   G_OBJECT_CLASS (parent_class)->finalize (object);
132 static void
133 gst_identity_class_init (GstIdentityClass * klass)
135   GObjectClass *gobject_class;
136   GstElementClass *gstelement_class;
137   GstBaseTransformClass *gstbasetrans_class;
139   gobject_class = G_OBJECT_CLASS (klass);
140   gstelement_class = GST_ELEMENT_CLASS (klass);
141   gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
143   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
144   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
146   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SLEEP_TIME,
147       g_param_spec_uint ("sleep-time", "Sleep time",
148           "Microseconds to sleep between processing", 0, G_MAXUINT,
149           DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
150   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUPLICATE,
151       g_param_spec_uint ("duplicate", "Duplicate Buffers",
152           "Push the buffers N times", 0, G_MAXUINT, DEFAULT_DUPLICATE,
153           G_PARAM_READWRITE));
154   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ERROR_AFTER,
155       g_param_spec_int ("error_after", "Error After", "Error after N buffers",
156           G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
157   g_object_class_install_property (G_OBJECT_CLASS (klass),
158       PROP_DROP_PROBABILITY, g_param_spec_float ("drop_probability",
159           "Drop Probability", "The Probability a buffer is dropped", 0.0, 1.0,
160           DEFAULT_DROP_PROBABILITY, G_PARAM_READWRITE));
161   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATARATE,
162       g_param_spec_int ("datarate", "Datarate",
163           "(Re)timestamps buffers with number of bytes per second (0 = inactive)",
164           0, G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
165   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
166       g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT,
167           G_PARAM_READWRITE));
168   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
169       g_param_spec_string ("last-message", "last-message", "last-message", NULL,
170           G_PARAM_READABLE));
171   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
172       g_param_spec_boolean ("dump", "Dump", "Dump buffer contents",
173           DEFAULT_DUMP, G_PARAM_READWRITE));
174   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SYNC,
175       g_param_spec_boolean ("sync", "Synchronize",
176           "Synchronize to pipeline clock", DEFAULT_SYNC, G_PARAM_READWRITE));
177   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CHECK_PERFECT,
178       g_param_spec_boolean ("check-perfect", "Check For Perfect Stream",
179           "Verify that the stream is time- and data-contiguous",
180           DEFAULT_CHECK_PERFECT, G_PARAM_READWRITE));
182   gst_identity_signals[SIGNAL_HANDOFF] =
183       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
184       G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
185       gst_marshal_VOID__BOXED, G_TYPE_NONE, 1,
186       GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
188   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_identity_finalize);
190   gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_identity_event);
191   gstbasetrans_class->transform = GST_DEBUG_FUNCPTR (gst_identity_transform);
192   gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_identity_start);
193   gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_identity_stop);
196 static void
197 gst_identity_init (GstIdentity * identity)
199   identity->sleep_time = DEFAULT_SLEEP_TIME;
200   identity->duplicate = DEFAULT_DUPLICATE;
201   identity->error_after = DEFAULT_ERROR_AFTER;
202   identity->drop_probability = DEFAULT_DROP_PROBABILITY;
203   identity->datarate = DEFAULT_DATARATE;
204   identity->silent = DEFAULT_SILENT;
205   identity->sync = DEFAULT_SYNC;
206   identity->check_perfect = DEFAULT_CHECK_PERFECT;
207   identity->dump = DEFAULT_DUMP;
208   identity->last_message = NULL;
211 static gboolean
212 gst_identity_event (GstBaseTransform * trans, GstEvent * event)
214   GstIdentity *identity;
216   identity = GST_IDENTITY (trans);
218   if (!identity->silent) {
219     g_free (identity->last_message);
221     identity->last_message =
222         g_strdup_printf ("chain   ******* (%s:%s)E (type: %d) %p",
223         GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), event);
225     g_object_notify (G_OBJECT (identity), "last_message");
226   }
227   return TRUE;
230 static void
231 gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf)
233   GstClockTime timestamp;
235   timestamp = GST_BUFFER_TIMESTAMP (buf);
237   /* see if we need to do perfect stream checking */
238   /* invalid timestamp drops us out of check.  FIXME: maybe warn ? */
239   if (timestamp != GST_CLOCK_TIME_NONE) {
240     /* check if we had a previous buffer to compare to */
241     if (identity->prev_timestamp != GST_CLOCK_TIME_NONE) {
242       guint64 offset;
244       if (identity->prev_timestamp + identity->prev_duration != timestamp) {
245         GST_WARNING_OBJECT (identity,
246             "Buffer not time-contiguous with previous one: " "prev ts %"
247             GST_TIME_FORMAT ", prev dur %" GST_TIME_FORMAT ", new ts %"
248             GST_TIME_FORMAT, GST_TIME_ARGS (identity->prev_timestamp),
249             GST_TIME_ARGS (identity->prev_duration), GST_TIME_ARGS (timestamp));
250       }
252       offset = GST_BUFFER_OFFSET (buf);
253       if (identity->prev_offset_end != offset) {
254         GST_WARNING_OBJECT (identity,
255             "Buffer not data-contiguous with previous one: "
256             "prev offset_end %" G_GINT64_FORMAT ", new offset %"
257             G_GINT64_FORMAT, identity->prev_offset_end, offset);
258       }
259     }
260     /* update prev values */
261     identity->prev_timestamp = timestamp;
262     identity->prev_duration = GST_BUFFER_DURATION (buf);
263     identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf);
264   }
267 static GstFlowReturn
268 gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf,
269     GstBuffer ** outbuf)
271   GstFlowReturn ret = GST_FLOW_OK;
272   GstIdentity *identity = GST_IDENTITY (trans);
273   guint i;
275   if (identity->check_perfect)
276     gst_identity_check_perfect (identity, inbuf);
278   if (identity->error_after >= 0) {
279     identity->error_after--;
280     if (identity->error_after == 0) {
281       GST_ELEMENT_ERROR (identity, CORE, FAILED,
282           (_("Failed after iterations as requested.")), (NULL));
283       return GST_FLOW_ERROR;
284     }
285   }
287   if (identity->drop_probability > 0.0) {
288     if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) {
289       g_free (identity->last_message);
290       identity->last_message =
291           g_strdup_printf ("dropping   ******* (%s:%s)i (%d bytes, timestamp: %"
292           GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
293           G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
294           GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf),
295           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
296           GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
297           GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf),
298           GST_BUFFER_FLAGS (inbuf), inbuf);
299       g_object_notify (G_OBJECT (identity), "last-message");
300       return GST_FLOW_OK;
301     }
302   }
304   if (identity->dump) {
305     gst_util_dump_mem (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
306   }
308   for (i = identity->duplicate; i; i--) {
309     GstClockTime time;
311     if (!identity->silent) {
312       g_free (identity->last_message);
313       identity->last_message =
314           g_strdup_printf ("chain   ******* (%s:%s)i (%d bytes, timestamp: %"
315           GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
316           G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
317           GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf),
318           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
319           GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
320           GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf),
321           GST_BUFFER_FLAGS (inbuf), inbuf);
322       g_object_notify (G_OBJECT (identity), "last-message");
323     }
325     time = GST_BUFFER_TIMESTAMP (inbuf);
327     if (identity->datarate > 0) {
328       time = identity->offset * GST_SECOND / identity->datarate;
330       GST_BUFFER_TIMESTAMP (inbuf) = time;
331       GST_BUFFER_DURATION (inbuf) =
332           GST_BUFFER_SIZE (inbuf) * GST_SECOND / identity->datarate;
333     }
335     g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
336         inbuf);
338     if (i > 1)
339       gst_buffer_ref (inbuf);
341     if (identity->sync) {
342       if (GST_ELEMENT (identity)->clock) {
343         /* gst_element_wait (GST_ELEMENT (identity), time); */
344       }
345     }
347     identity->offset += GST_BUFFER_SIZE (inbuf);
349     if (identity->sleep_time)
350       g_usleep (identity->sleep_time);
352     gst_buffer_ref (inbuf);
353     *outbuf = inbuf;
354   }
356   return ret;
359 static void
360 gst_identity_set_property (GObject * object, guint prop_id,
361     const GValue * value, GParamSpec * pspec)
363   GstIdentity *identity;
365   identity = GST_IDENTITY (object);
367   switch (prop_id) {
368     case PROP_SLEEP_TIME:
369       identity->sleep_time = g_value_get_uint (value);
370       break;
371     case PROP_SILENT:
372       identity->silent = g_value_get_boolean (value);
373       break;
374     case PROP_DUPLICATE:
375       identity->duplicate = g_value_get_uint (value);
376       break;
377     case PROP_DUMP:
378       identity->dump = g_value_get_boolean (value);
379       break;
380     case PROP_ERROR_AFTER:
381       identity->error_after = g_value_get_int (value);
382       break;
383     case PROP_DROP_PROBABILITY:
384       identity->drop_probability = g_value_get_float (value);
385       break;
386     case PROP_DATARATE:
387       identity->datarate = g_value_get_int (value);
388       break;
389     case PROP_SYNC:
390       identity->sync = g_value_get_boolean (value);
391       break;
392     case PROP_CHECK_PERFECT:
393       identity->check_perfect = g_value_get_boolean (value);
394       break;
395     default:
396       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
397       break;
398   }
401 static void
402 gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
403     GParamSpec * pspec)
405   GstIdentity *identity;
407   identity = GST_IDENTITY (object);
409   switch (prop_id) {
410     case PROP_SLEEP_TIME:
411       g_value_set_uint (value, identity->sleep_time);
412       break;
413     case PROP_DUPLICATE:
414       g_value_set_uint (value, identity->duplicate);
415       break;
416     case PROP_ERROR_AFTER:
417       g_value_set_int (value, identity->error_after);
418       break;
419     case PROP_DROP_PROBABILITY:
420       g_value_set_float (value, identity->drop_probability);
421       break;
422     case PROP_DATARATE:
423       g_value_set_int (value, identity->datarate);
424       break;
425     case PROP_SILENT:
426       g_value_set_boolean (value, identity->silent);
427       break;
428     case PROP_DUMP:
429       g_value_set_boolean (value, identity->dump);
430       break;
431     case PROP_LAST_MESSAGE:
432       g_value_set_string (value, identity->last_message);
433       break;
434     case PROP_SYNC:
435       g_value_set_boolean (value, identity->sync);
436       break;
437     case PROP_CHECK_PERFECT:
438       g_value_set_boolean (value, identity->check_perfect);
439       break;
440     default:
441       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
442       break;
443   }
446 static gboolean
447 gst_identity_start (GstBaseTransform * trans)
449   GstIdentity *identity;
451   identity = GST_IDENTITY (trans);
453   identity->offset = 0;
454   identity->prev_timestamp = GST_CLOCK_TIME_NONE;
455   identity->prev_duration = GST_CLOCK_TIME_NONE;
456   identity->prev_offset_end = -1;
458   return TRUE;
461 static gboolean
462 gst_identity_stop (GstBaseTransform * trans)
464   GstIdentity *identity;
466   identity = GST_IDENTITY (trans);
468   g_free (identity->last_message);
469   identity->last_message = NULL;
471   return TRUE;