From 7be792fa138dcb4634eb893074042b7440e56594 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 15 Apr 2009 16:03:27 +0300 Subject: debug: rename debug to debugutils to avoid clash with --disable-debug. Fixes #562168 --- configure.ac | 4 +- docs/plugins/Makefile.am | 4 +- gst/debug/Makefile.am | 49 --- gst/debug/breakmydata.c | 297 ------------------ gst/debug/debug.vcproj | 166 ---------- gst/debug/efence.c | 537 --------------------------------- gst/debug/efence.h | 50 --- gst/debug/efence.vcproj | 148 --------- gst/debug/gstdebug.c | 63 ---- gst/debug/gstnavigationtest.c | 357 ---------------------- gst/debug/gstnavigationtest.h | 68 ----- gst/debug/gstnavseek.c | 340 --------------------- gst/debug/gstnavseek.h | 60 ---- gst/debug/gstpushfilesrc.c | 195 ------------ gst/debug/gstpushfilesrc.h | 56 ---- gst/debug/gsttaginject.c | 204 ------------- gst/debug/gsttaginject.h | 66 ---- gst/debug/navigationtest.vcproj | 148 --------- gst/debug/negotiation.c | 287 ------------------ gst/debug/progressreport.c | 478 ----------------------------- gst/debug/progressreport.h | 66 ---- gst/debug/rndbuffersize.c | 371 ----------------------- gst/debug/testplugin.c | 318 -------------------- gst/debug/tests.c | 568 ----------------------------------- gst/debug/tests.h | 43 --- gst/debugutils/Makefile.am | 49 +++ gst/debugutils/breakmydata.c | 297 ++++++++++++++++++ gst/debugutils/debug.vcproj | 166 ++++++++++ gst/debugutils/efence.c | 537 +++++++++++++++++++++++++++++++++ gst/debugutils/efence.h | 50 +++ gst/debugutils/efence.vcproj | 148 +++++++++ gst/debugutils/gstdebug.c | 63 ++++ gst/debugutils/gstnavigationtest.c | 357 ++++++++++++++++++++++ gst/debugutils/gstnavigationtest.h | 68 +++++ gst/debugutils/gstnavseek.c | 340 +++++++++++++++++++++ gst/debugutils/gstnavseek.h | 60 ++++ gst/debugutils/gstpushfilesrc.c | 195 ++++++++++++ gst/debugutils/gstpushfilesrc.h | 56 ++++ gst/debugutils/gsttaginject.c | 204 +++++++++++++ gst/debugutils/gsttaginject.h | 66 ++++ gst/debugutils/navigationtest.vcproj | 148 +++++++++ gst/debugutils/negotiation.c | 287 ++++++++++++++++++ gst/debugutils/progressreport.c | 478 +++++++++++++++++++++++++++++ gst/debugutils/progressreport.h | 66 ++++ gst/debugutils/rndbuffersize.c | 371 +++++++++++++++++++++++ gst/debugutils/testplugin.c | 318 ++++++++++++++++++++ gst/debugutils/tests.c | 568 +++++++++++++++++++++++++++++++++++ gst/debugutils/tests.h | 43 +++ 48 files changed, 4939 insertions(+), 4939 deletions(-) delete mode 100644 gst/debug/Makefile.am delete mode 100644 gst/debug/breakmydata.c delete mode 100644 gst/debug/debug.vcproj delete mode 100644 gst/debug/efence.c delete mode 100644 gst/debug/efence.h delete mode 100644 gst/debug/efence.vcproj delete mode 100644 gst/debug/gstdebug.c delete mode 100644 gst/debug/gstnavigationtest.c delete mode 100644 gst/debug/gstnavigationtest.h delete mode 100644 gst/debug/gstnavseek.c delete mode 100644 gst/debug/gstnavseek.h delete mode 100644 gst/debug/gstpushfilesrc.c delete mode 100644 gst/debug/gstpushfilesrc.h delete mode 100644 gst/debug/gsttaginject.c delete mode 100644 gst/debug/gsttaginject.h delete mode 100644 gst/debug/navigationtest.vcproj delete mode 100644 gst/debug/negotiation.c delete mode 100644 gst/debug/progressreport.c delete mode 100644 gst/debug/progressreport.h delete mode 100644 gst/debug/rndbuffersize.c delete mode 100644 gst/debug/testplugin.c delete mode 100644 gst/debug/tests.c delete mode 100644 gst/debug/tests.h create mode 100644 gst/debugutils/Makefile.am create mode 100644 gst/debugutils/breakmydata.c create mode 100644 gst/debugutils/debug.vcproj create mode 100644 gst/debugutils/efence.c create mode 100644 gst/debugutils/efence.h create mode 100644 gst/debugutils/efence.vcproj create mode 100644 gst/debugutils/gstdebug.c create mode 100644 gst/debugutils/gstnavigationtest.c create mode 100644 gst/debugutils/gstnavigationtest.h create mode 100644 gst/debugutils/gstnavseek.c create mode 100644 gst/debugutils/gstnavseek.h create mode 100644 gst/debugutils/gstpushfilesrc.c create mode 100644 gst/debugutils/gstpushfilesrc.h create mode 100644 gst/debugutils/gsttaginject.c create mode 100644 gst/debugutils/gsttaginject.h create mode 100644 gst/debugutils/navigationtest.vcproj create mode 100644 gst/debugutils/negotiation.c create mode 100644 gst/debugutils/progressreport.c create mode 100644 gst/debugutils/progressreport.h create mode 100644 gst/debugutils/rndbuffersize.c create mode 100644 gst/debugutils/testplugin.c create mode 100644 gst/debugutils/tests.c create mode 100644 gst/debugutils/tests.h diff --git a/configure.ac b/configure.ac index 3a4fd2d0..bb12f78d 100644 --- a/configure.ac +++ b/configure.ac @@ -290,7 +290,7 @@ AG_GST_CHECK_PLUGIN(auparse) AG_GST_CHECK_PLUGIN(autodetect) AG_GST_CHECK_PLUGIN(avi) AG_GST_CHECK_PLUGIN(cutter) -AG_GST_CHECK_PLUGIN(debug) +AG_GST_CHECK_PLUGIN(debugutils) AG_GST_CHECK_PLUGIN(effectv) AG_GST_CHECK_PLUGIN(equalizer) AG_GST_CHECK_PLUGIN(id3demux) @@ -1065,7 +1065,7 @@ gst/auparse/Makefile gst/autodetect/Makefile gst/avi/Makefile gst/cutter/Makefile -gst/debug/Makefile +gst/debugutils/Makefile gst/effectv/Makefile gst/equalizer/Makefile gst/id3demux/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 753fd1b7..478d04b6 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -135,8 +135,8 @@ EXTRA_HFILES = \ $(top_srcdir)/gst/avi/gstavimux.h \ $(top_srcdir)/gst/avi/gstavisubtitle.h \ $(top_srcdir)/gst/cutter/gstcutter.h \ - $(top_srcdir)/gst/debug/gsttaginject.h \ - $(top_srcdir)/gst/debug/progressreport.h \ + $(top_srcdir)/gst/debugutils/gsttaginject.h \ + $(top_srcdir)/gst/debugutils/progressreport.h \ $(top_srcdir)/gst/equalizer/gstiirequalizer.h \ $(top_srcdir)/gst/equalizer/gstiirequalizer3bands.h \ $(top_srcdir)/gst/equalizer/gstiirequalizer10bands.h \ diff --git a/gst/debug/Makefile.am b/gst/debug/Makefile.am deleted file mode 100644 index 8c53cdf3..00000000 --- a/gst/debug/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -if GST_HAVE_MMAP -EFENCE_PLUGIN=libgstefence.la -else -EFENCE_PLUGIN= -endif - -plugin_LTLIBRARIES = $(EFENCE_PLUGIN) libgstdebug.la libgstnavigationtest.la - -noinst_HEADERS = \ - efence.h \ - gstnavigationtest.h \ - gstnavseek.h \ - gstpushfilesrc.h \ - gsttaginject.h \ - progressreport.h \ - tests.h - -libgstefence_la_SOURCES = efence.c -libgstefence_la_CFLAGS = $(GST_CFLAGS) -libgstefence_la_LIBADD = $(GST_LIBS) -libgstefence_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstefence_la_LIBTOOLFLAGS = --tag=disable-static - -libgstnavigationtest_la_SOURCES = gstnavigationtest.c -libgstnavigationtest_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \ - $(GST_PLUGINS_BASE_CFLAGS) -libgstnavigationtest_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ - $(GST_PLUGINS_BASE_LIBS) -lgstvideo-@GST_MAJORMINOR@ $(LIBM) -libgstnavigationtest_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstnavigationtest_la_LIBTOOLFLAGS = --tag=disable-static - -libgstdebug_la_SOURCES = \ - gstdebug.c \ - breakmydata.c \ - gstnavseek.c \ - gstpushfilesrc.c \ - gsttaginject.c \ - rndbuffersize.c \ - progressreport.c \ - tests.c \ - testplugin.c - -# negotiation.c - -libgstdebug_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) -libgstdebug_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) -libgstdebug_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstdebug_la_LIBTOOLFLAGS = --tag=disable-static - diff --git a/gst/debug/breakmydata.c b/gst/debug/breakmydata.c deleted file mode 100644 index 63e30b6c..00000000 --- a/gst/debug/breakmydata.c +++ /dev/null @@ -1,297 +0,0 @@ -/* GStreamer - * Copyright (C) 2004 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/** - * SECTION:element-breakmydata - * - * This element modifies the contents of the buffer it is passed randomly - * according to the parameters set. - * It otherwise acts as an identity. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include - -GST_DEBUG_CATEGORY_STATIC (gst_break_my_data_debug); -#define GST_CAT_DEFAULT gst_break_my_data_debug - -#define GST_TYPE_BREAK_MY_DATA \ - (gst_break_my_data_get_type()) -#define GST_BREAK_MY_DATA(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BREAK_MY_DATA,GstBreakMyData)) -#define GST_BREAK_MY_DATA_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BREAK_MY_DATA,GstBreakMyDataClass)) -#define GST_IS_BREAK_MY_DATA(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BREAK_MY_DATA)) -#define GST_IS_BREAK_MY_DATA_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BREAK_MY_DATA)) - -enum -{ - ARG_0, - ARG_SEED, - ARG_SET_TO, - ARG_SKIP, - ARG_PROBABILITY -}; - -typedef struct _GstBreakMyData GstBreakMyData; -typedef struct _GstBreakMyDataClass GstBreakMyDataClass; - -struct _GstBreakMyData -{ - GstBaseTransform basetransform; - - GRand *rand; - guint skipped; - - guint32 seed; - gint set; - guint skip; - gdouble probability; -}; - -struct _GstBreakMyDataClass -{ - GstBaseTransformClass parent_class; -}; - -static void gst_break_my_data_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_break_my_data_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static GstFlowReturn gst_break_my_data_transform_ip (GstBaseTransform * trans, - GstBuffer * buf); -static gboolean gst_break_my_data_stop (GstBaseTransform * trans); -static gboolean gst_break_my_data_start (GstBaseTransform * trans); - -static const GstElementDetails details = GST_ELEMENT_DETAILS ("Break my data", - "Testing", - "randomly change data in the stream", - "Benjamin Otte "); - -GstStaticPadTemplate bmd_src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -GstStaticPadTemplate bmd_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_break_my_data_debug, "breakmydata", 0, \ - "debugging category for breakmydata element"); - -GST_BOILERPLATE_FULL (GstBreakMyData, gst_break_my_data, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); - - -static void -gst_break_my_data_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&bmd_sink_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&bmd_src_template)); - - gst_element_class_set_details (gstelement_class, &details); -} - -static void -gst_break_my_data_class_init (GstBreakMyDataClass * klass) -{ - GstBaseTransformClass *gstbasetrans_class; - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (klass); - gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); - - gobject_class->set_property = - GST_DEBUG_FUNCPTR (gst_break_my_data_set_property); - gobject_class->get_property = - GST_DEBUG_FUNCPTR (gst_break_my_data_get_property); - - g_object_class_install_property (gobject_class, ARG_SEED, - g_param_spec_uint ("seed", "seed", - "seed for randomness (initialized when going from READY to PAUSED)", - 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, ARG_SET_TO, - g_param_spec_int ("set-to", "set-to", - "set changed bytes to this value (-1 means random value", - -1, G_MAXUINT8, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, ARG_SKIP, - g_param_spec_uint ("skip", "skip", - "amount of bytes skipped at the beginning of stream", - 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, ARG_PROBABILITY, - g_param_spec_double ("probability", "probability", - "probability for each byte in the buffer to be changed", 0.0, 1.0, - 0.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - gstbasetrans_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_break_my_data_transform_ip); - gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_break_my_data_start); - gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_break_my_data_stop); -} - -static void -gst_break_my_data_init (GstBreakMyData * bmd, GstBreakMyDataClass * g_class) -{ - gst_base_transform_set_in_place (GST_BASE_TRANSFORM (bmd), TRUE); - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (bmd), TRUE); -} - -static void -gst_break_my_data_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstBreakMyData *bmd = GST_BREAK_MY_DATA (object); - - GST_OBJECT_LOCK (bmd); - - switch (prop_id) { - case ARG_SEED: - bmd->seed = g_value_get_uint (value); - break; - case ARG_SET_TO: - bmd->set = g_value_get_int (value); - break; - case ARG_SKIP: - bmd->skip = g_value_get_uint (value); - break; - case ARG_PROBABILITY: - bmd->probability = g_value_get_double (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - GST_OBJECT_UNLOCK (bmd); -} - -static void -gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstBreakMyData *bmd = GST_BREAK_MY_DATA (object); - - GST_OBJECT_LOCK (bmd); - - switch (prop_id) { - case ARG_SEED: - g_value_set_uint (value, bmd->seed); - break; - case ARG_SET_TO: - g_value_set_int (value, bmd->set); - break; - case ARG_SKIP: - g_value_set_uint (value, bmd->skip); - break; - case ARG_PROBABILITY: - g_value_set_double (value, bmd->probability); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - GST_OBJECT_UNLOCK (bmd); -} - -static GstFlowReturn -gst_break_my_data_transform_ip (GstBaseTransform * trans, GstBuffer * buf) -{ - GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); - guint i, size; - - g_return_val_if_fail (gst_buffer_is_writable (buf), GST_FLOW_ERROR); - - GST_OBJECT_LOCK (bmd); - - if (bmd->skipped < bmd->skip) { - i = bmd->skip - bmd->skipped; - } else { - i = 0; - } - - size = GST_BUFFER_SIZE (buf); - - GST_LOG_OBJECT (bmd, - "got buffer %p (size %u, timestamp %" G_GUINT64_FORMAT ", offset %" - G_GUINT64_FORMAT "", buf, size, GST_BUFFER_TIMESTAMP (buf), - GST_BUFFER_OFFSET (buf)); - - for (; i < size; i++) { - if (g_rand_double_range (bmd->rand, 0, 1.0) <= bmd->probability) { - guint8 new; - - if (bmd->set < 0) { - new = g_rand_int_range (bmd->rand, 0, 256); - } else { - new = bmd->set; - } - GST_INFO_OBJECT (bmd, "changing byte %u from 0x%02X to 0x%02X", i, - (guint) GST_READ_UINT8 (GST_BUFFER_DATA (buf) + i), - (guint) ((guint8) new)); - GST_BUFFER_DATA (buf)[i] = new; - } - } - /* don't overflow */ - bmd->skipped += MIN (G_MAXUINT - bmd->skipped, GST_BUFFER_SIZE (buf)); - - GST_OBJECT_UNLOCK (bmd); - - return GST_FLOW_OK; -} - -static gboolean -gst_break_my_data_start (GstBaseTransform * trans) -{ - GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); - - GST_OBJECT_LOCK (bmd); - bmd->rand = g_rand_new_with_seed (bmd->seed); - bmd->skipped = 0; - GST_OBJECT_UNLOCK (bmd); - - return TRUE; -} - -static gboolean -gst_break_my_data_stop (GstBaseTransform * trans) -{ - GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); - - GST_OBJECT_LOCK (bmd); - g_rand_free (bmd->rand); - bmd->rand = NULL; - GST_OBJECT_UNLOCK (bmd); - - return TRUE; -} diff --git a/gst/debug/debug.vcproj b/gst/debug/debug.vcproj deleted file mode 100644 index 3093ae7b..00000000 --- a/gst/debug/debug.vcproj +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gst/debug/efence.c b/gst/debug/efence.c deleted file mode 100644 index a46bf1ac..00000000 --- a/gst/debug/efence.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * GStreamer - * Copyright (C) 1999-2001 Erik Walthinsen - * Copyright (C) 2002 David A. Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include - -#include -#include -#include - -#include "efence.h" - -#ifndef MAP_ANONYMOUS -#ifdef MAP_ANON -#define MAP_ANONYMOUS MAP_ANON -#else -/* assume we don't need it */ -#define MAP_ANONYMOUS 0 -#endif -#endif - -GST_DEBUG_CATEGORY_STATIC (gst_efence_debug); -#define GST_CAT_DEFAULT gst_efence_debug - -static const GstElementDetails plugin_details = -GST_ELEMENT_DETAILS ("Electric Fence", - "Testing", - "This element converts a stream of normal GStreamer buffers into a " - "stream of buffers that are allocated in such a way that out-of-bounds " - "access to data in the buffer is more likely to cause segmentation " - "faults. This allocation method is very similar to the debugging tool " - "\"Electric Fence\".", - "David A. Schleef "); - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - ARG_FENCE_TOP -}; - -static GstStaticPadTemplate gst_efence_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate gst_efence_src_factory = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static void gst_efence_base_init (gpointer g_class); -static void gst_efence_class_init (GstEFenceClass * klass); -static void gst_efence_init (GstEFence * filter); - -static void gst_efence_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_efence_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstFlowReturn gst_efence_chain (GstPad * pad, GstBuffer * buf); -static GstFlowReturn gst_efence_getrange (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer); -static gboolean gst_efence_checkgetrange (GstPad * pad); -static gboolean gst_efence_activate_src_pull (GstPad * pad, gboolean active); - -static GstElementClass *parent_class = NULL; - -typedef struct _GstFencedBuffer GstFencedBuffer; -struct _GstFencedBuffer -{ - GstBuffer buffer; - void *region; - unsigned int length; -}; - -GType gst_fenced_buffer_get_type (void); -static void gst_fenced_buffer_finalize (GstFencedBuffer * buf); -static GstFencedBuffer *gst_fenced_buffer_copy (const GstBuffer * buffer); -static void *gst_fenced_buffer_alloc (GstBuffer * buffer, unsigned int length, - gboolean fence_top); -static GstFlowReturn gst_efence_buffer_alloc (GstPad * pad, guint64 offset, - guint size, GstCaps * caps, GstBuffer ** buf); - -#define GST_TYPE_FENCED_BUFFER (gst_fenced_buffer_get_type()) - -#define GST_IS_FENCED_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_FENCED_BUFFER)) -#define GST_FENCED_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_FENCED_BUFFER, GstFencedBuffer)) - -GType -gst_gst_efence_get_type (void) -{ - static GType plugin_type = 0; - - if (!plugin_type) { - static const GTypeInfo plugin_info = { - sizeof (GstEFenceClass), - gst_efence_base_init, - NULL, - (GClassInitFunc) gst_efence_class_init, - NULL, - NULL, - sizeof (GstEFence), - 0, - (GInstanceInitFunc) gst_efence_init, - }; - - plugin_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstEFence", &plugin_info, 0); - } - return plugin_type; -} - -static void -gst_efence_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_efence_sink_factory)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_efence_src_factory)); - gst_element_class_set_details (element_class, &plugin_details); -} - -/* initialize the plugin's class */ -static void -gst_efence_class_init (GstEFenceClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->set_property = gst_efence_set_property; - gobject_class->get_property = gst_efence_get_property; - - g_object_class_install_property (gobject_class, ARG_FENCE_TOP, - g_param_spec_boolean ("fence_top", "Fence Top", - "Align buffers with top of fenced region", TRUE, G_PARAM_READWRITE)); -} - -/* initialize the new element - * instantiate pads and add them to element - * set functions - * initialize structure - */ -static void -gst_efence_init (GstEFence * filter) -{ - filter->sinkpad = - gst_pad_new_from_static_template (&gst_efence_sink_factory, "sink"); - gst_pad_set_getcaps_function (filter->sinkpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); - gst_pad_set_setcaps_function (filter->sinkpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps)); - gst_pad_set_chain_function (filter->sinkpad, - GST_DEBUG_FUNCPTR (gst_efence_chain)); - gst_pad_set_bufferalloc_function (filter->sinkpad, - GST_DEBUG_FUNCPTR (gst_efence_buffer_alloc)); - gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); - - filter->srcpad = - gst_pad_new_from_static_template (&gst_efence_src_factory, "src"); - gst_pad_set_getcaps_function (filter->srcpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); - gst_pad_set_setcaps_function (filter->srcpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps)); - gst_pad_set_checkgetrange_function (filter->srcpad, - GST_DEBUG_FUNCPTR (gst_efence_checkgetrange)); - gst_pad_set_getrange_function (filter->srcpad, - GST_DEBUG_FUNCPTR (gst_efence_getrange)); - gst_pad_set_activatepull_function (filter->srcpad, - GST_DEBUG_FUNCPTR (gst_efence_activate_src_pull)); - - gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); - - filter->fence_top = TRUE; -} - -/* chain function - * this function does the actual processing - */ - -static GstFlowReturn -gst_efence_chain (GstPad * pad, GstBuffer * buffer) -{ - GstEFence *efence; - GstBuffer *copy; - - efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); - g_return_val_if_fail (GST_IS_EFENCE (efence), GST_FLOW_ERROR); - - if (GST_IS_FENCED_BUFFER (buffer)) { - GST_DEBUG_OBJECT (efence, "Passing on existing fenced buffer with caps %" - GST_PTR_FORMAT, GST_BUFFER_CAPS (buffer)); - return gst_pad_push (efence->srcpad, buffer); - } - - copy = (GstBuffer *) gst_fenced_buffer_copy (buffer); - - GST_DEBUG_OBJECT (efence, "Pushing newly fenced buffer with caps %" - GST_PTR_FORMAT ", data=%p, size=%u", GST_BUFFER_CAPS (copy), - GST_BUFFER_DATA (copy), GST_BUFFER_SIZE (copy)); - - gst_buffer_unref (buffer); - - return gst_pad_push (efence->srcpad, copy); -} - -static GstFlowReturn -gst_efence_getrange (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer) -{ - GstEFence *efence; - GstFlowReturn ret; - GstBuffer *ownbuf; - GstPad *peer; - - efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); - - peer = gst_pad_get_peer (efence->sinkpad); - if (!peer) - return GST_FLOW_NOT_LINKED; - - if ((ret = gst_pad_get_range (peer, offset, length, buffer)) != GST_FLOW_OK) - goto beach; - - ownbuf = (GstBuffer *) gst_fenced_buffer_copy (*buffer); - gst_buffer_unref ((GstBuffer *) * buffer); - *buffer = ownbuf; - -beach: - gst_object_unref (peer); - return ret; -} - -static gboolean -gst_efence_checkgetrange (GstPad * pad) -{ - GstEFence *efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); - - return gst_pad_check_pull_range (efence->sinkpad); -} - -static gboolean -gst_efence_activate_src_pull (GstPad * pad, gboolean active) -{ - GstEFence *efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); - - return gst_pad_activate_pull (efence->sinkpad, active); -} - -static GstFlowReturn -gst_efence_buffer_alloc (GstPad * pad, guint64 offset, - guint size, GstCaps * caps, GstBuffer ** buf) -{ - GstBuffer *buffer; - GstEFence *efence; - - g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); - g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); - - efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); - - buffer = (GstBuffer *) gst_mini_object_new (GST_TYPE_FENCED_BUFFER); - - GST_BUFFER_DATA (buffer) = gst_fenced_buffer_alloc (buffer, size, - efence->fence_top); - GST_BUFFER_SIZE (buffer) = size; - GST_BUFFER_OFFSET (buffer) = offset; - - if (caps) - gst_buffer_set_caps (buffer, caps); - - *buf = buffer; - - GST_DEBUG_OBJECT (efence, "Allocated buffer of size %u, caps: %" - GST_PTR_FORMAT, GST_BUFFER_SIZE (buffer), GST_BUFFER_CAPS (buffer)); - - return GST_FLOW_OK; -} - -static void -gst_efence_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstEFence *filter; - - g_return_if_fail (GST_IS_EFENCE (object)); - filter = GST_EFENCE (object); - - switch (prop_id) { - case ARG_FENCE_TOP: - filter->fence_top = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_efence_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstEFence *filter; - - g_return_if_fail (GST_IS_EFENCE (object)); - filter = GST_EFENCE (object); - - switch (prop_id) { - case ARG_FENCE_TOP: - g_value_set_boolean (value, filter->fence_top); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and pad templates - * register the features - */ -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "efence", GST_RANK_NONE, GST_TYPE_EFENCE)) - return FALSE; - - GST_DEBUG_CATEGORY_INIT (gst_efence_debug, "efence", 0, - "Debug output from the efence element"); - - /* plugin initialisation succeeded */ - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "efence", - "This element converts a stream of normal GStreamer buffers into a " - "stream of buffers that are allocated in such a way that out-of-bounds " - "access to data in the buffer is more likely to cause segmentation " - "faults. This allocation method is very similar to the debugging tool " - "\"Electric Fence\".", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); - - -static GstBufferClass *fenced_buffer_parent_class = NULL; - -static void -gst_fenced_buffer_finalize (GstFencedBuffer * buffer) -{ - GstFencedBuffer *fenced_buffer; - - GST_DEBUG ("free buffer=%p", buffer); - - fenced_buffer = GST_FENCED_BUFFER (buffer); - - /* free our data */ - if (GST_BUFFER_DATA (buffer)) { - GST_DEBUG ("free region %p %d", fenced_buffer->region, - fenced_buffer->length); - munmap (fenced_buffer->region, fenced_buffer->length); - } - - GST_MINI_OBJECT_CLASS (fenced_buffer_parent_class)->finalize (GST_MINI_OBJECT - (buffer)); -} - -static GstFencedBuffer * -gst_fenced_buffer_copy (const GstBuffer * buffer) -{ - GstBuffer *copy; - void *ptr; - guint mask; - - g_return_val_if_fail (buffer != NULL, NULL); - - /* create a fresh new buffer */ - copy = (GstBuffer *) gst_mini_object_new (GST_TYPE_FENCED_BUFFER); - - /* we simply copy everything from our parent */ - ptr = gst_fenced_buffer_alloc (GST_BUFFER (copy), - GST_BUFFER_SIZE (buffer), TRUE); - memcpy (ptr, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); - - /* copy relevant flags */ - mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS | - GST_BUFFER_FLAG_DELTA_UNIT; - GST_MINI_OBJECT (copy)->flags |= GST_MINI_OBJECT (buffer)->flags & mask; - - GST_BUFFER_DATA (copy) = ptr; - GST_BUFFER_SIZE (copy) = GST_BUFFER_SIZE (buffer); - GST_BUFFER_TIMESTAMP (copy) = GST_BUFFER_TIMESTAMP (buffer); - GST_BUFFER_DURATION (copy) = GST_BUFFER_DURATION (buffer); - GST_BUFFER_OFFSET (copy) = GST_BUFFER_OFFSET (buffer); - GST_BUFFER_OFFSET_END (copy) = GST_BUFFER_OFFSET_END (buffer); - - if (GST_BUFFER_CAPS (buffer)) - GST_BUFFER_CAPS (copy) = gst_caps_ref (GST_BUFFER_CAPS (buffer)); - else - GST_BUFFER_CAPS (copy) = NULL; - - GST_DEBUG ("Copied buffer %p with ts %" GST_TIME_FORMAT - ", caps: %" GST_PTR_FORMAT, buffer, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (copy)), GST_BUFFER_CAPS (copy)); - - return GST_FENCED_BUFFER (copy); -} - -void * -gst_fenced_buffer_alloc (GstBuffer * buffer, unsigned int length, - gboolean fence_top) -{ - int alloc_size; - void *region; - GstFencedBuffer *fenced_buffer = (GstFencedBuffer *) buffer; - int page_size; - - GST_DEBUG ("buffer=%p length=%d fence_top=%d", buffer, length, fence_top); - - if (length == 0) - return NULL; - -#ifdef _SC_PAGESIZE - page_size = sysconf (_SC_PAGESIZE); -#else - page_size = getpagesize (); -#endif - - /* Allocate a complete page, and one on either side */ - alloc_size = ((length - 1) & ~(page_size - 1)) + page_size; - alloc_size += 2 * page_size; - - region = mmap (NULL, alloc_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (region == MAP_FAILED) { - g_warning ("mmap failed"); - return NULL; - } -#if 0 - munmap (region, page_size); - munmap (region + alloc_size - page_size, page_size); - - fenced_buffer->region = region + page_size; - fenced_buffer->length = alloc_size - page_size; -#else - mprotect (region, page_size, PROT_NONE); - mprotect ((char *) region + alloc_size - page_size, page_size, PROT_NONE); - - fenced_buffer->region = region; - fenced_buffer->length = alloc_size; -#endif - - GST_DEBUG ("new region %p %d", fenced_buffer->region, fenced_buffer->length); - - if (fence_top) { - int offset; - - /* Align to top of region, but force alignment to 4 bytes */ - offset = alloc_size - page_size - length; - offset &= ~0x3; - return (void *) ((char *) region + offset); - } else { - return (void *) ((char *) region + page_size); - } -} - -static void -gst_fenced_buffer_class_init (gpointer g_class, gpointer class_data) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); - - fenced_buffer_parent_class = g_type_class_peek_parent (g_class); - - mini_object_class->finalize = - (GstMiniObjectFinalizeFunction) gst_fenced_buffer_finalize; - mini_object_class->copy = (GstMiniObjectCopyFunction) gst_fenced_buffer_copy; -} - -GType -gst_fenced_buffer_get_type (void) -{ - static GType fenced_buf_type = 0; - - if (G_UNLIKELY (!fenced_buf_type)) { - static const GTypeInfo fenced_buf_info = { - sizeof (GstBufferClass), - NULL, - NULL, - (GClassInitFunc) gst_fenced_buffer_class_init, - NULL, - NULL, - sizeof (GstFencedBuffer), - 0, - NULL, - }; - - fenced_buf_type = g_type_register_static (GST_TYPE_BUFFER, - "GstFencedBuffer", &fenced_buf_info, 0); - } - return fenced_buf_type; -} diff --git a/gst/debug/efence.h b/gst/debug/efence.h deleted file mode 100644 index 7c4acb5d..00000000 --- a/gst/debug/efence.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * efence.h - */ - -#ifndef __GST_EFENCE_H__ -#define __GST_EFENCE_H__ - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/* #define's don't like whitespacey bits */ -#define GST_TYPE_EFENCE \ - (gst_gst_efence_get_type()) -#define GST_EFENCE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EFENCE,GstEFence)) -#define GST_EFENCE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EFENCE,GstEFenceClass)) -#define GST_IS_EFENCE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EFENCE)) -#define GST_IS_EFENCE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EFENCE)) - - typedef struct _GstEFence GstEFence; - typedef struct _GstEFenceClass GstEFenceClass; - - struct _GstEFence - { - GstElement element; - - GstPad *sinkpad, *srcpad; - - gboolean fence_top; - }; - - struct _GstEFenceClass - { - GstElementClass parent_class; - }; - - GType gst_gst_efence_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __GST_EFENCE_H__ */ diff --git a/gst/debug/efence.vcproj b/gst/debug/efence.vcproj deleted file mode 100644 index c01fcd28..00000000 --- a/gst/debug/efence.vcproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gst/debug/gstdebug.c b/gst/debug/gstdebug.c deleted file mode 100644 index 53f24d50..00000000 --- a/gst/debug/gstdebug.c +++ /dev/null @@ -1,63 +0,0 @@ -/* GStreamer - * Copyright (C) 2004 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -GType gst_break_my_data_get_type (void); -GType gst_rnd_buffer_size_get_type (void); -GType gst_navseek_get_type (void); -GType gst_progress_report_get_type (void); -GType gst_tag_inject_get_type (void); -GType gst_test_get_type (void); -/* -GType gst_push_file_src_get_type (void); -GType gst_gst_negotiation_get_type (void); -*/ - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "breakmydata", GST_RANK_NONE, - gst_break_my_data_get_type ()) - || !gst_element_register (plugin, "rndbuffersize", GST_RANK_NONE, - gst_rnd_buffer_size_get_type ()) - || !gst_element_register (plugin, "navseek", GST_RANK_NONE, - gst_navseek_get_type ()) || -/* !gst_element_register (plugin, "pushfilesrc", GST_RANK_NONE, gst_push_file_src_get_type ()) || */ -/* !gst_element_register (plugin, "negotiation", GST_RANK_NONE, gst_gst_negotiation_get_type ()) || */ - !gst_element_register (plugin, "progressreport", GST_RANK_NONE, - gst_progress_report_get_type ()) - || !gst_element_register (plugin, "taginject", GST_RANK_NONE, - gst_tag_inject_get_type ()) - || !gst_element_register (plugin, "testsink", GST_RANK_NONE, - gst_test_get_type ())) - return FALSE; - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "debug", - "elements for testing and debugging", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/debug/gstnavigationtest.c b/gst/debug/gstnavigationtest.c deleted file mode 100644 index 5c339252..00000000 --- a/gst/debug/gstnavigationtest.c +++ /dev/null @@ -1,357 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * Copyright (C) <2003> David Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstnavigationtest.h" -#include -#include - -#include - -#ifdef _MSC_VER -#define rint(x) (floor((x)+0.5)) -#endif - -GST_DEBUG_CATEGORY_STATIC (navigationtest_debug); -#define GST_CAT_DEFAULT navigationtest_debug - -static const GstElementDetails navigationtest_details = -GST_ELEMENT_DETAILS ("Video navigation test", - "Filter/Effect/Video", - "Handle navigation events showing a black square following mouse pointer", - "David Schleef "); - -static GstStaticPadTemplate gst_navigationtest_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) - ); - -static GstStaticPadTemplate gst_navigationtest_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) - ); - -static GstVideoFilterClass *parent_class = NULL; - -static gboolean -gst_navigationtest_handle_src_event (GstPad * pad, GstEvent * event) -{ - GstNavigationtest *navtest; - const gchar *type; - - navtest = GST_NAVIGATIONTEST (GST_PAD_PARENT (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NAVIGATION: - { - const GstStructure *s = gst_event_get_structure (event); - gint fps_n, fps_d; - - fps_n = gst_value_get_fraction_numerator ((&navtest->framerate)); - fps_d = gst_value_get_fraction_denominator ((&navtest->framerate)); - - type = gst_structure_get_string (s, "event"); - if (g_str_equal (type, "mouse-move")) { - gst_structure_get_double (s, "pointer_x", &navtest->x); - gst_structure_get_double (s, "pointer_y", &navtest->y); - } else if (g_str_equal (type, "mouse-button-press")) { - ButtonClick *click = g_new (ButtonClick, 1); - - gst_structure_get_double (s, "pointer_x", &click->x); - gst_structure_get_double (s, "pointer_y", &click->y); - click->images_left = (fps_n + fps_d - 1) / fps_d; - /* green */ - click->cy = 150; - click->cu = 46; - click->cv = 21; - navtest->clicks = g_slist_prepend (navtest->clicks, click); - } else if (g_str_equal (type, "mouse-button-release")) { - ButtonClick *click = g_new (ButtonClick, 1); - - gst_structure_get_double (s, "pointer_x", &click->x); - gst_structure_get_double (s, "pointer_y", &click->y); - click->images_left = (fps_n + fps_d - 1) / fps_d; - /* red */ - click->cy = 76; - click->cu = 85; - click->cv = 255; - navtest->clicks = g_slist_prepend (navtest->clicks, click); - } - break; - } - default: - break; - } - return gst_pad_event_default (pad, event); -} - -/* Useful macros */ -#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) -#define GST_VIDEO_I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2) -#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2) - -#define GST_VIDEO_I420_Y_OFFSET(w,h) (0) -#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h))) -#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) - -#define GST_VIDEO_I420_SIZE(w,h) (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) - -static gboolean -gst_navigationtest_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, - guint * size) -{ - GstNavigationtest *navtest; - GstStructure *structure; - gboolean ret = FALSE; - gint width, height; - - navtest = GST_NAVIGATIONTEST (btrans); - - structure = gst_caps_get_structure (caps, 0); - - if (gst_structure_get_int (structure, "width", &width) && - gst_structure_get_int (structure, "height", &height)) { - *size = GST_VIDEO_I420_SIZE (width, height); - ret = TRUE; - GST_DEBUG_OBJECT (navtest, "our frame size is %d bytes (%dx%d)", *size, - width, height); - } - - return ret; -} - -static gboolean -gst_navigationtest_set_caps (GstBaseTransform * btrans, GstCaps * incaps, - GstCaps * outcaps) -{ - GstNavigationtest *navtest = GST_NAVIGATIONTEST (btrans); - gboolean ret = FALSE; - GstStructure *structure; - - structure = gst_caps_get_structure (incaps, 0); - - if (gst_structure_get_int (structure, "width", &navtest->width) && - gst_structure_get_int (structure, "height", &navtest->height)) { - const GValue *framerate; - - framerate = gst_structure_get_value (structure, "framerate"); - if (framerate && GST_VALUE_HOLDS_FRACTION (framerate)) { - g_value_copy (framerate, &navtest->framerate); - ret = TRUE; - } - } - - return ret; -} - -static void -draw_box_planar411 (guint8 * dest, int width, int height, int x, int y, - guint8 colory, guint8 coloru, guint8 colorv) -{ - int x1, x2, y1, y2; - guint8 *d = dest; - - if (x < 0 || y < 0 || x >= width || y >= height) - return; - - x1 = MAX (x - 5, 0); - x2 = MIN (x + 5, width); - y1 = MAX (y - 5, 0); - y2 = MIN (y + 5, height); - - for (y = y1; y < y2; y++) { - for (x = x1; x < x2; x++) { - ((guint8 *) d)[y * GST_VIDEO_I420_Y_ROWSTRIDE (width) + x] = colory; - } - } - - d = dest + GST_VIDEO_I420_U_OFFSET (width, height); - x1 /= 2; - x2 /= 2; - y1 /= 2; - y2 /= 2; - for (y = y1; y < y2; y++) { - for (x = x1; x < x2; x++) { - ((guint8 *) d)[y * GST_VIDEO_I420_U_ROWSTRIDE (width) + x] = coloru; - } - } - - d = dest + GST_VIDEO_I420_V_OFFSET (width, height); - for (y = y1; y < y2; y++) { - for (x = x1; x < x2; x++) { - ((guint8 *) d)[y * GST_VIDEO_I420_V_ROWSTRIDE (width) + x] = colorv; - } - } -} - -static GstFlowReturn -gst_navigationtest_transform (GstBaseTransform * trans, GstBuffer * in, - GstBuffer * out) -{ - GstNavigationtest *navtest = GST_NAVIGATIONTEST (trans); - GSList *walk; - GstFlowReturn ret = GST_FLOW_OK; - - /* do something interesting here. This simply copies the source - * to the destination. */ - gst_buffer_copy_metadata (out, in, GST_BUFFER_COPY_TIMESTAMPS); - - memcpy (GST_BUFFER_DATA (out), GST_BUFFER_DATA (in), - MIN (GST_BUFFER_SIZE (in), GST_BUFFER_SIZE (out))); - - walk = navtest->clicks; - while (walk) { - ButtonClick *click = walk->data; - - walk = g_slist_next (walk); - draw_box_planar411 (GST_BUFFER_DATA (out), navtest->width, navtest->height, - rint (click->x), rint (click->y), click->cy, click->cu, click->cv); - if (--click->images_left < 1) { - navtest->clicks = g_slist_remove (navtest->clicks, click); - g_free (click); - } - } - draw_box_planar411 (GST_BUFFER_DATA (out), navtest->width, navtest->height, - rint (navtest->x), rint (navtest->y), 0, 128, 128); - - return ret; -} - -static GstStateChangeReturn -gst_navigationtest_change_state (GstElement * element, - GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstNavigationtest *navtest = GST_NAVIGATIONTEST (element); - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - /* downwards state changes */ - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - { - g_slist_foreach (navtest->clicks, (GFunc) g_free, NULL); - g_slist_free (navtest->clicks); - navtest->clicks = NULL; - break; - } - default: - break; - } - - return ret; -} - -static void -gst_navigationtest_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details (element_class, &navigationtest_details); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_navigationtest_sink_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_navigationtest_src_template)); -} - -static void -gst_navigationtest_class_init (gpointer klass, gpointer class_data) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - GstBaseTransformClass *trans_class; - - gobject_class = (GObjectClass *) klass; - element_class = (GstElementClass *) klass; - trans_class = (GstBaseTransformClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - element_class->change_state = - GST_DEBUG_FUNCPTR (gst_navigationtest_change_state); - - trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_navigationtest_set_caps); - trans_class->get_unit_size = - GST_DEBUG_FUNCPTR (gst_navigationtest_get_unit_size); - trans_class->transform = GST_DEBUG_FUNCPTR (gst_navigationtest_transform); -} - -static void -gst_navigationtest_init (GTypeInstance * instance, gpointer g_class) -{ - GstNavigationtest *navtest = GST_NAVIGATIONTEST (instance); - GstBaseTransform *btrans = GST_BASE_TRANSFORM (instance); - - gst_pad_set_event_function (btrans->srcpad, - GST_DEBUG_FUNCPTR (gst_navigationtest_handle_src_event)); - - navtest->x = -1; - navtest->y = -1; - g_value_init (&navtest->framerate, GST_TYPE_FRACTION); -} - -GType -gst_navigationtest_get_type (void) -{ - static GType navigationtest_type = 0; - - if (!navigationtest_type) { - static const GTypeInfo navigationtest_info = { - sizeof (GstNavigationtestClass), - gst_navigationtest_base_init, - NULL, - gst_navigationtest_class_init, - NULL, - NULL, - sizeof (GstNavigationtest), - 0, - gst_navigationtest_init, - }; - - navigationtest_type = g_type_register_static (GST_TYPE_VIDEO_FILTER, - "GstNavigationtest", &navigationtest_info, 0); - } - return navigationtest_type; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - GST_DEBUG_CATEGORY_INIT (navigationtest_debug, "navigationtest", 0, - "navigationtest"); - - return gst_element_register (plugin, "navigationtest", GST_RANK_NONE, - GST_TYPE_NAVIGATIONTEST); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "navigationtest", - "Template for a video filter", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/debug/gstnavigationtest.h b/gst/debug/gstnavigationtest.h deleted file mode 100644 index efdbb228..00000000 --- a/gst/debug/gstnavigationtest.h +++ /dev/null @@ -1,68 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __GST_NAVIGATIONTEST_H__ -#define __GST_NAVIGATIONTEST_H__ - -#include - -G_BEGIN_DECLS -#define GST_TYPE_NAVIGATIONTEST \ - (gst_navigationtest_get_type()) -#define GST_NAVIGATIONTEST(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NAVIGATIONTEST,GstNavigationtest)) -#define GST_NAVIGATIONTEST_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NAVIGATIONTEST,GstNavigationtestClass)) -#define GST_IS_NAVIGATIONTEST(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NAVIGATIONTEST)) -#define GST_IS_NAVIGATIONTEST_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NAVIGATIONTEST)) -typedef struct _GstNavigationtest GstNavigationtest; -typedef struct _GstNavigationtestClass GstNavigationtestClass; - -typedef struct -{ - gdouble x; - gdouble y; - gint images_left; - guint8 cy, cu, cv; -} ButtonClick; - -struct _GstNavigationtest -{ - GstVideoFilter videofilter; - - gint width, height; - - GValue framerate; - gdouble x, y; - - GSList *clicks; -}; - -struct _GstNavigationtestClass -{ - GstVideoFilterClass parent_class; -}; - -GType gst_navigationtest_get_type (void); - -G_END_DECLS -#endif /* __GST_NAVIGATIONTEST_H__ */ diff --git a/gst/debug/gstnavseek.c b/gst/debug/gstnavseek.c deleted file mode 100644 index c47bf42f..00000000 --- a/gst/debug/gstnavseek.c +++ /dev/null @@ -1,340 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * Copyright (C) <2003> David Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * This file was (probably) generated from gstnavseek.c, - * gstnavseek.c,v 1.7 2003/11/08 02:48:59 dschleef Exp - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstnavseek.h" -#include -#include - -enum -{ - ARG_0, - ARG_SEEKOFFSET -}; - -GstStaticPadTemplate navseek_src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -GstStaticPadTemplate navseek_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static const GstElementDetails navseek_details = -GST_ELEMENT_DETAILS ("Seek based on left-right arrows", - "Filter/Video", - "Seek based on navigation keys left-right", - "Jan Schmidt "); - -static gboolean gst_navseek_event (GstBaseTransform * trans, GstEvent * event); -static GstFlowReturn gst_navseek_transform_ip (GstBaseTransform * basetrans, - GstBuffer * buf); -static gboolean gst_navseek_handle_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_navseek_stop (GstBaseTransform * trans); -static gboolean gst_navseek_start (GstBaseTransform * trans); - -static void gst_navseek_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_navseek_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -GST_BOILERPLATE (GstNavSeek, gst_navseek, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM); - -static void -gst_navseek_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&navseek_sink_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&navseek_src_template)); - - gst_element_class_set_details (element_class, &navseek_details); -} - -static void -gst_navseek_class_init (GstNavSeekClass * klass) -{ - GstBaseTransformClass *gstbasetrans_class; - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (klass); - gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); - - gobject_class->set_property = gst_navseek_set_property; - gobject_class->get_property = gst_navseek_get_property; - - g_object_class_install_property (gobject_class, - ARG_SEEKOFFSET, g_param_spec_double ("seek-offset", "Seek Offset", - "Time in seconds to seek by", 0.0, G_MAXDOUBLE, 5.0, - G_PARAM_READWRITE)); - - gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_navseek_event); - gstbasetrans_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_navseek_transform_ip); - gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_navseek_start); - gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_navseek_stop); -} - -static void -gst_navseek_init (GstNavSeek * navseek, GstNavSeekClass * g_class) -{ - gst_pad_set_event_function (GST_BASE_TRANSFORM (navseek)->srcpad, - GST_DEBUG_FUNCPTR (gst_navseek_handle_src_event)); - - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (navseek), TRUE); - - navseek->seek_offset = 5.0; - navseek->loop = FALSE; - navseek->grab_seg_start = FALSE; - navseek->grab_seg_end = FALSE; - navseek->segment_start = GST_CLOCK_TIME_NONE; - navseek->segment_end = GST_CLOCK_TIME_NONE; -} - -static void -gst_navseek_seek (GstNavSeek * navseek, gint64 offset) -{ - GstFormat peer_format = GST_FORMAT_TIME; - gboolean ret; - GstPad *peer_pad; - gint64 peer_value; - - /* Query for the current time then attempt to set to time + offset */ - peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); - ret = gst_pad_query_position (peer_pad, &peer_format, &peer_value); - - if (ret && peer_format == GST_FORMAT_TIME) { - GstEvent *event; - - peer_value += offset; - if (peer_value < 0) - peer_value = 0; - - event = gst_event_new_seek (1.0, GST_FORMAT_TIME, - GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, - GST_SEEK_TYPE_SET, peer_value, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); - - gst_pad_send_event (peer_pad, event); - } - - gst_object_unref (peer_pad); -} - -static void -gst_navseek_segseek (GstNavSeek * navseek) -{ - GstEvent *event; - GstPad *peer_pad; - - if ((navseek->segment_start == GST_CLOCK_TIME_NONE) || - (navseek->segment_end == GST_CLOCK_TIME_NONE) || - (!GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad))) { - return; - } - - if (navseek->loop) { - event = - gst_event_new_seek (1.0, GST_FORMAT_TIME, - GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT, - GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET, - navseek->segment_end); - } else { - event = - gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE, - GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET, - navseek->segment_end); - } - - peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); - gst_pad_send_event (peer_pad, event); - gst_object_unref (peer_pad); -} - -static gboolean -gst_navseek_handle_src_event (GstPad * pad, GstEvent * event) -{ - GstNavSeek *navseek; - gboolean ret = TRUE; - - navseek = GST_NAVSEEK (GST_PAD_PARENT (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NAVIGATION: - /* Check for a keyup and convert left/right to a seek event */ - { - const GstStructure *structure; - const gchar *event_type; - - structure = gst_event_get_structure (event); - g_return_val_if_fail (structure != NULL, FALSE); - - event_type = gst_structure_get_string (structure, "event"); - g_return_val_if_fail (event_type != NULL, FALSE); - - if (strcmp (event_type, "key-press") == 0) { - const gchar *key; - - key = gst_structure_get_string (structure, "key"); - g_return_val_if_fail (key != NULL, FALSE); - - if (strcmp (key, "Left") == 0) { - /* Seek backward by 5 secs */ - gst_navseek_seek (navseek, -1.0 * navseek->seek_offset * GST_SECOND); - } else if (strcmp (key, "Right") == 0) { - /* Seek forward */ - gst_navseek_seek (navseek, navseek->seek_offset * GST_SECOND); - } else if (strcmp (key, "s") == 0) { - /* Grab the next frame as the start frame of a segment */ - navseek->grab_seg_start = TRUE; - } else if (strcmp (key, "e") == 0) { - /* Grab the next frame as the end frame of a segment */ - navseek->grab_seg_end = TRUE; - } else if (strcmp (key, "l") == 0) { - /* Toggle the loop flag. If we have both start and end segment times send a seek */ - navseek->loop = !navseek->loop; - gst_navseek_segseek (navseek); - } - } else { - break; - } - gst_event_unref (event); - event = NULL; - } - break; - default: - break; - } - - if (event && GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad)) { - GstPad *peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); - - ret = gst_pad_send_event (peer_pad, event); - gst_object_unref (peer_pad); - } - - return ret; -} - -static void -gst_navseek_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstNavSeek *navseek = GST_NAVSEEK (object); - - switch (prop_id) { - case ARG_SEEKOFFSET: - GST_OBJECT_LOCK (navseek); - navseek->seek_offset = g_value_get_double (value); - GST_OBJECT_UNLOCK (navseek); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_navseek_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstNavSeek *navseek = GST_NAVSEEK (object); - - switch (prop_id) { - case ARG_SEEKOFFSET: - GST_OBJECT_LOCK (navseek); - g_value_set_double (value, navseek->seek_offset); - GST_OBJECT_UNLOCK (navseek); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_navseek_event (GstBaseTransform * trans, GstEvent * event) -{ - GstNavSeek *navseek = GST_NAVSEEK (trans); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - GST_OBJECT_LOCK (navseek); - if (navseek->loop) - gst_navseek_segseek (navseek); - GST_OBJECT_UNLOCK (navseek); - break; - default: - break; - } - return GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event); -} - -static GstFlowReturn -gst_navseek_transform_ip (GstBaseTransform * basetrans, GstBuffer * buf) -{ - GstNavSeek *navseek = GST_NAVSEEK (basetrans); - - GST_OBJECT_LOCK (navseek); - - if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { - if (navseek->grab_seg_start) { - navseek->segment_start = GST_BUFFER_TIMESTAMP (buf); - navseek->segment_end = GST_CLOCK_TIME_NONE; - navseek->grab_seg_start = FALSE; - } - - if (navseek->grab_seg_end) { - navseek->segment_end = GST_BUFFER_TIMESTAMP (buf); - navseek->grab_seg_end = FALSE; - gst_navseek_segseek (navseek); - } - } - - GST_OBJECT_UNLOCK (navseek); - - return GST_FLOW_OK; -} - -static gboolean -gst_navseek_start (GstBaseTransform * trans) -{ - /* anything we should be doing here? */ - return TRUE; -} - -static gboolean -gst_navseek_stop (GstBaseTransform * trans) -{ - /* anything we should be doing here? */ - return TRUE; -} diff --git a/gst/debug/gstnavseek.h b/gst/debug/gstnavseek.h deleted file mode 100644 index af7e9d21..00000000 --- a/gst/debug/gstnavseek.h +++ /dev/null @@ -1,60 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __GST_NAVSEEK_H__ -#define __GST_NAVSEEK_H__ - - -#include -#include - -G_BEGIN_DECLS -#define GST_TYPE_NAVSEEK \ - (gst_navseek_get_type()) -#define GST_NAVSEEK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NAVSEEK,GstNavSeek)) -#define GST_NAVSEEK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NAVSEEK,GstNavSeekClass)) -#define GST_IS_NAVSEEK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NAVSEEK)) -#define GST_IS_NAVSEEK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NAVSEEK)) -typedef struct _GstNavSeek GstNavSeek; -typedef struct _GstNavSeekClass GstNavSeekClass; - -struct _GstNavSeek -{ - GstBaseTransform basetransform; - - gdouble seek_offset; - gboolean loop; - gboolean grab_seg_start; - gboolean grab_seg_end; - GstClockTime segment_start; - GstClockTime segment_end; -}; - -struct _GstNavSeekClass -{ - GstBaseTransformClass parent_class; -}; - -G_END_DECLS -#endif /* __GST_NAVSEEK_H__ */ diff --git a/gst/debug/gstpushfilesrc.c b/gst/debug/gstpushfilesrc.c deleted file mode 100644 index 47daa83e..00000000 --- a/gst/debug/gstpushfilesrc.c +++ /dev/null @@ -1,195 +0,0 @@ -/* GStreamer Push File Source - * Copyright (C) <2007> Tim-Philipp Müller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-pushfilesrc - * @see_also: filesrc - * - * This element is only useful for debugging purposes. It implements an URI - * protocol handler for the 'pushfile' protocol and behaves like a file source - * element that cannot be activated in pull-mode. This makes it very easy to - * debug demuxers or decoders that can operate both pull and push-based in - * connection with the playbin element (which creates a source based on the - * URI passed). - * - * - * Example launch line - * |[ - * gst-launch -m playbin uri=pushfile:///home/you/some/file.ogg - * ]| This plays back the given file using playbin, with the demuxer operating - * push-based. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstpushfilesrc.h" - -#include - -GST_DEBUG_CATEGORY_STATIC (pushfilesrc_debug); -#define GST_CAT_DEFAULT pushfilesrc_debug - -static const GstElementDetails pushfilesrc_details = -GST_ELEMENT_DETAILS ("Push File Source", - "Testing", - "Implements pushfile:// URI-handler for push-based file access", - "Tim-Philipp Müller "); - -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static void gst_push_file_src_uri_handler_init (gpointer g_iface, - gpointer iface_data); -static void gst_file_push_src_add_uri_handler (GType type); - -GST_BOILERPLATE_FULL (GstPushFileSrc, gst_push_file_src, GstBin, GST_TYPE_BIN, - gst_file_push_src_add_uri_handler); - -static void -gst_file_push_src_add_uri_handler (GType type) -{ - static const GInterfaceInfo info = { - gst_push_file_src_uri_handler_init, - NULL, - NULL - }; - - g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &info); - GST_DEBUG_CATEGORY_INIT (pushfilesrc_debug, "pushfilesrc", 0, - "pushfilesrc element"); -} - -static void -gst_push_file_src_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&srctemplate)); - - gst_element_class_set_details (element_class, &pushfilesrc_details); -} - -static void -gst_push_file_src_dispose (GObject * obj) -{ - GstPushFileSrc *src = GST_PUSH_FILE_SRC (obj); - - if (src->srcpad) { - gst_element_remove_pad (GST_ELEMENT (src), src->srcpad); - src->srcpad = NULL; - } - if (src->filesrc) { - gst_bin_remove (GST_BIN (src), src->filesrc); - src->filesrc = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (obj); -} - -static void -gst_push_file_src_class_init (GstPushFileSrcClass * g_class) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (g_class); - - gobject_class->dispose = gst_push_file_src_dispose; -} - -static gboolean -gst_push_file_src_ghostpad_checkgetrange (GstPad * pad) -{ - return FALSE; -} - -static void -gst_push_file_src_init (GstPushFileSrc * src, GstPushFileSrcClass * g_class) -{ - src->filesrc = gst_element_factory_make ("filesrc", "real-filesrc"); - if (src->filesrc) { - GstPad *pad; - - gst_bin_add (GST_BIN (src), src->filesrc); - pad = gst_element_get_static_pad (src->filesrc, "src"); - g_assert (pad != NULL); - src->srcpad = gst_ghost_pad_new ("src", pad); - /* FIXME^H^HCORE: try pushfile:///foo/bar.ext ! typefind ! fakesink without - * this and watch core bugginess (some pad stays in flushing state) */ - gst_pad_set_checkgetrange_function (src->srcpad, - GST_DEBUG_FUNCPTR (gst_push_file_src_ghostpad_checkgetrange)); - gst_element_add_pad (GST_ELEMENT (src), src->srcpad); - gst_object_unref (pad); - } -} - -/*** GSTURIHANDLER INTERFACE *************************************************/ - -static GstURIType -gst_push_file_src_uri_get_type (void) -{ - return GST_URI_SRC; -} - -static gchar ** -gst_push_file_src_uri_get_protocols (void) -{ - static gchar *protocols[] = { "pushfile", NULL }; - - return protocols; -} - -static const gchar * -gst_push_file_src_uri_get_uri (GstURIHandler * handler) -{ - GstPushFileSrc *src = GST_PUSH_FILE_SRC (handler); - - if (src->filesrc == NULL) - return NULL; - - return gst_uri_handler_get_uri (GST_URI_HANDLER (src->filesrc)); -} - -static gboolean -gst_push_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) -{ - GstPushFileSrc *src = GST_PUSH_FILE_SRC (handler); - - if (src->filesrc == NULL || !g_str_has_prefix (uri, "pushfile://")) - return FALSE; - - /* skip 'push' bit */ - return gst_uri_handler_set_uri (GST_URI_HANDLER (src->filesrc), uri + 4); -} - -static void -gst_push_file_src_uri_handler_init (gpointer g_iface, gpointer iface_data) -{ - GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; - - iface->get_type = gst_push_file_src_uri_get_type; - iface->get_protocols = gst_push_file_src_uri_get_protocols; - iface->get_uri = gst_push_file_src_uri_get_uri; - iface->set_uri = gst_push_file_src_uri_set_uri; -} diff --git a/gst/debug/gstpushfilesrc.h b/gst/debug/gstpushfilesrc.h deleted file mode 100644 index d9333444..00000000 --- a/gst/debug/gstpushfilesrc.h +++ /dev/null @@ -1,56 +0,0 @@ -/* GStreamer Push File Source - * Copyright (C) <2007> Tim-Philipp Müller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_PUSH_FILE_SRC_H__ -#define __GST_PUSH_FILE_SRC_H__ - -#include - -G_BEGIN_DECLS -#define GST_TYPE_PUSH_FILE_SRC \ - (gst_push_file_src_get_type()) -#define GST_PUSH_FILE_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PUSH_FILE_SRC,GstPushFileSrc)) -#define GST_PUSH_FILE_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PUSH_FILE_SRC,GstPushFileSrcClass)) -#define GST_IS_PUSH_FILE_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PUSH_FILE_SRC)) -#define GST_IS_PUSH_FILE_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PUSH_FILE_SRC)) -typedef struct _GstPushFileSrc GstPushFileSrc; -typedef struct _GstPushFileSrcClass GstPushFileSrcClass; - -struct _GstPushFileSrc -{ - GstBin parent; - - /*< private > */ - GstElement *filesrc; - GstPad *srcpad; -}; - -struct _GstPushFileSrcClass -{ - GstBinClass parent_class; -}; - -GType gst_push_file_src_get_type (void); - -G_END_DECLS -#endif /* __GST_PUSH_FILE_SRC_H__ */ diff --git a/gst/debug/gsttaginject.c b/gst/debug/gsttaginject.c deleted file mode 100644 index 3429fb14..00000000 --- a/gst/debug/gsttaginject.c +++ /dev/null @@ -1,204 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Stefan Kost - * - * gsttaginject.c: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/** - * SECTION:element-taginject - * - * Element that injects new metadata tags, but passes incomming data through - * unmodified. - * - * - * Example launch lines - * |[ - * gst-launch audiotestsrc num-buffers=100 ! taginject tags="title=testsrc,artist=gstreamer" ! vorbisenc ! oggmux ! filesink location=test.ogg - * ]| set title and artist - * |[ - * gst-launch audiotestsrc num-buffers=100 ! taginject tags="keywords=\"testone,audio\",title=\"audio testtone\"" ! vorbisenc ! oggmux ! filesink location=test.ogg - * ]| set keywords and title demonstrating quoting of special chars - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "gsttaginject.h" - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -GST_DEBUG_CATEGORY_STATIC (gst_tag_inject_debug); -#define GST_CAT_DEFAULT gst_tag_inject_debug - -enum -{ - PROP_TAGS = 1 -}; - - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_tag_inject_debug, "taginject", 0, "tag inject element"); - -GST_BOILERPLATE_FULL (GstTagInject, gst_tag_inject, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); - -static void gst_tag_inject_finalize (GObject * object); -static void gst_tag_inject_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_tag_inject_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstFlowReturn gst_tag_inject_transform_ip (GstBaseTransform * trans, - GstBuffer * buf); -static gboolean gst_tag_inject_start (GstBaseTransform * trans); - - -static void -gst_tag_inject_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details_simple (gstelement_class, - "TagInject", - "Generic", "inject metadata tags", "Stefan Kost "); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&srctemplate)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sinktemplate)); -} - -static void -gst_tag_inject_finalize (GObject * object) -{ - GstTagInject *self = GST_TAG_INJECT (object); - - if (self->tags) { - gst_tag_list_free (self->tags); - self->tags = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_tag_inject_class_init (GstTagInjectClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseTransformClass *gstbasetrans_class; - - gobject_class = G_OBJECT_CLASS (klass); - gstelement_class = GST_ELEMENT_CLASS (klass); - gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); - - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_tag_inject_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_tag_inject_get_property); - - g_object_class_install_property (gobject_class, PROP_TAGS, - g_param_spec_string ("tags", "taglist", - "List of tags to inject into the target file", - NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); - - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_tag_inject_finalize); - - gstbasetrans_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_tag_inject_transform_ip); - - gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_tag_inject_start); -} - -static void -gst_tag_inject_init (GstTagInject * self, GstTagInjectClass * g_class) -{ - self->tags = NULL; -} - -static GstFlowReturn -gst_tag_inject_transform_ip (GstBaseTransform * trans, GstBuffer * buf) -{ - GstTagInject *self = GST_TAG_INJECT (trans); - - if (G_UNLIKELY (!self->tags_sent)) { - self->tags_sent = TRUE; - /* send tags */ - if (self->tags && !gst_tag_list_is_empty (self->tags)) { - GST_DEBUG ("tag event :%" GST_PTR_FORMAT, self->tags); - gst_element_found_tags (GST_ELEMENT (trans), - gst_tag_list_copy (self->tags)); - } - } - - return GST_FLOW_OK; -} - -static void -gst_tag_inject_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstTagInject *self = GST_TAG_INJECT (object); - - switch (prop_id) { - case PROP_TAGS:{ - gchar *structure = - g_strdup_printf ("taglist,%s", g_value_get_string (value)); - if (!(self->tags = gst_structure_from_string (structure, NULL))) { - GST_WARNING ("unparsable taglist = '%s'", structure); - } - g_free (structure); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_tag_inject_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - /*GstTagInject *self = GST_TAG_INJECT (object); */ - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_tag_inject_start (GstBaseTransform * trans) -{ - GstTagInject *self = GST_TAG_INJECT (trans); - - /* we need to sent tags _transform_ip() once */ - self->tags_sent = FALSE; - - return TRUE; -} diff --git a/gst/debug/gsttaginject.h b/gst/debug/gsttaginject.h deleted file mode 100644 index 8e8de1ee..00000000 --- a/gst/debug/gsttaginject.h +++ /dev/null @@ -1,66 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Stefan Kost - * - * gsttaginject.h: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __GST_TAG_INJECT_H__ -#define __GST_TAG_INJECT_H__ - - -#include -#include - -G_BEGIN_DECLS -#define GST_TYPE_TAG_INJECT \ - (gst_tag_inject_get_type()) -#define GST_TAG_INJECT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TAG_INJECT,GstTagInject)) -#define GST_TAG_INJECT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TAG_INJECT,GstTagInjectClass)) -#define GST_IS_TAG_INJECT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TAG_INJECT)) -#define GST_IS_TAG_INJECT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TAG_INJECT)) -typedef struct _GstTagInject GstTagInject; -typedef struct _GstTagInjectClass GstTagInjectClass; - -/** - * GstTagInject: - * - * Opaque #GstTagInject data structure - */ -struct _GstTagInject -{ - GstBaseTransform element; - - /*< private > */ - GstTagList *tags; - gboolean tags_sent; -}; - -struct _GstTagInjectClass -{ - GstBaseTransformClass parent_class; -}; - -GType gst_tag_inject_get_type (void); - -G_END_DECLS -#endif /* __GST_TAG_INJECT_H__ */ diff --git a/gst/debug/navigationtest.vcproj b/gst/debug/navigationtest.vcproj deleted file mode 100644 index 0bcc0ff7..00000000 --- a/gst/debug/navigationtest.vcproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gst/debug/negotiation.c b/gst/debug/negotiation.c deleted file mode 100644 index 12082273..00000000 --- a/gst/debug/negotiation.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * GStreamer - * Copyright (C) 1999-2001 Erik Walthinsen - * Copyright (C) 2002 David A. Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include - -#include -#include -#include - - -#define GST_TYPE_NEGOTIATION \ - (gst_gst_negotiation_get_type()) -#define GST_NEGOTIATION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NEGOTIATION,GstNegotiation)) -#define GST_NEGOTIATION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NEGOTIATION,GstNegotiation)) -#define GST_IS_NEGOTIATION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NEGOTIATION)) -#define GST_IS_NEGOTIATION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NEGOTIATION)) - -typedef struct _GstNegotiation GstNegotiation; -typedef struct _GstNegotiationClass GstNegotiationClass; - -struct _GstNegotiation -{ - GstElement element; - - GstPad *sinkpad, *srcpad; - - GstCaps *caps; -}; - -struct _GstNegotiationClass -{ - GstElementClass parent_class; -}; - -GType gst_gst_negotiation_get_type (void); - - -static const GstElementDetails plugin_details = -GST_ELEMENT_DETAILS ("Negotiation", - "Testing", - "This element acts like identity, except that one can control how " - "negotiation works", - "David A. Schleef "); - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - ARG_ALLOWED_CAPS -}; - -static GstStaticPadTemplate gst_negotiation_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate gst_negotiation_src_factory = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static void gst_negotiation_base_init (gpointer g_class); -static void gst_negotiation_class_init (GstNegotiationClass * klass); -static void gst_negotiation_init (GstNegotiation * filter); - -static GstCaps *gst_negotiation_getcaps (GstPad * pad); -static GstPadLinkReturn gst_negotiation_pad_link (GstPad * pad, - const GstCaps * caps); - -static void gst_negotiation_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_negotiation_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static void gst_negotiation_update_caps (GstNegotiation * negotiation); -static void gst_negotiation_chain (GstPad * pad, GstData * _data); - -static GstElementClass *parent_class = NULL; - -GType -gst_gst_negotiation_get_type (void) -{ - static GType plugin_type = 0; - - if (!plugin_type) { - static const GTypeInfo plugin_info = { - sizeof (GstNegotiationClass), - gst_negotiation_base_init, - NULL, - (GClassInitFunc) gst_negotiation_class_init, - NULL, - NULL, - sizeof (GstNegotiation), - 0, - (GInstanceInitFunc) gst_negotiation_init, - }; - - plugin_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstNegotiation", &plugin_info, 0); - } - return plugin_type; -} - -static void -gst_negotiation_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_negotiation_sink_factory)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_negotiation_src_factory)); - gst_element_class_set_details (element_class, &plugin_details); -} - -static void -gst_negotiation_class_init (GstNegotiationClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->set_property = gst_negotiation_set_property; - gobject_class->get_property = gst_negotiation_get_property; - - g_object_class_install_property (gobject_class, ARG_ALLOWED_CAPS, - g_param_spec_boxed ("allowed-caps", "Caps", - "The range of formats allowed by " "this element's peers", - GST_TYPE_CAPS, G_PARAM_READABLE)); -} - -static void -gst_negotiation_init (GstNegotiation * filter) -{ - filter->sinkpad = - gst_pad_new_from_static_template (&gst_negotiation_sink_factory, "sink"); - gst_pad_set_getcaps_function (filter->sinkpad, gst_negotiation_getcaps); - gst_pad_set_link_function (filter->sinkpad, gst_negotiation_pad_link); - filter->srcpad = - gst_pad_new_from_static_template (&gst_negotiation_src_factory, "src"); - gst_pad_set_getcaps_function (filter->srcpad, gst_negotiation_getcaps); - gst_pad_set_link_function (filter->srcpad, gst_negotiation_pad_link); - - gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); - gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); - gst_pad_set_chain_function (filter->sinkpad, gst_negotiation_chain); -} - -static GstCaps * -gst_negotiation_getcaps (GstPad * pad) -{ - GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad)); - GstPad *otherpad; - GstCaps *caps; - - otherpad = (pad == negotiation->sinkpad) ? negotiation->srcpad : - negotiation->sinkpad; - - caps = gst_pad_get_allowed_caps (otherpad); - - GST_ERROR ("getcaps called on %" GST_PTR_FORMAT ", returning %" - GST_PTR_FORMAT, pad, caps); - - gst_negotiation_update_caps (negotiation); - gst_object_unref (negotiation); - - return caps; -} - -static GstPadLinkReturn -gst_negotiation_pad_link (GstPad * pad, const GstCaps * caps) -{ - GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad)); - GstPad *otherpad; - GstPadLinkReturn ret; - - otherpad = (pad == negotiation->sinkpad) ? negotiation->srcpad : - negotiation->sinkpad; - - ret = gst_pad_try_set_caps (otherpad, caps); - - GST_ERROR ("pad_link called on %" GST_PTR_FORMAT " with caps %" - GST_PTR_FORMAT ", returning %d", pad, caps, ret); - gst_object_unref (negotiation); - - return ret; -} - -static void -gst_negotiation_update_caps (GstNegotiation * negotiation) -{ - GstCaps *srccaps; - GstCaps *sinkcaps; - GstCaps *icaps; - - srccaps = gst_pad_get_allowed_caps (negotiation->srcpad); - sinkcaps = gst_pad_get_allowed_caps (negotiation->sinkpad); - - icaps = gst_caps_intersect (srccaps, sinkcaps); - gst_caps_free (srccaps); - gst_caps_free (sinkcaps); - - gst_caps_replace (&negotiation->caps, icaps); - g_object_notify (G_OBJECT (negotiation), "allowed-caps"); - GST_DEBUG ("notify %" GST_PTR_FORMAT, icaps); -} - -static void -gst_negotiation_chain (GstPad * pad, GstData * _data) -{ - GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad)); - - gst_pad_push (negotiation->srcpad, _data); - gst_object_unref (negotiation); -} - -static void -gst_negotiation_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstNegotiation *filter; - - g_return_if_fail (GST_IS_NEGOTIATION (object)); - filter = GST_NEGOTIATION (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_negotiation_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstNegotiation *filter; - - g_return_if_fail (GST_IS_NEGOTIATION (object)); - filter = GST_NEGOTIATION (object); - - switch (prop_id) { - case ARG_ALLOWED_CAPS: - g_value_set_boxed (value, filter->caps); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/gst/debug/progressreport.c b/gst/debug/progressreport.c deleted file mode 100644 index 8f2547b3..00000000 --- a/gst/debug/progressreport.c +++ /dev/null @@ -1,478 +0,0 @@ -/* GStreamer Progress Report Element - * Copyright (C) <1999> Erik Walthinsen - * Copyright (C) <2003> David Schleef - * Copyright (C) <2004> Jan Schmidt - * Copyright (C) <2006> Tim-Philipp Müller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-progressreport - * - * The progressreport element can be put into a pipeline to report progress, - * which is done by doing upstream duration and position queries in regular - * (real-time) intervals. Both the interval and the prefered query format - * can be specified via the #GstProgressReport:update-freq and the - * #GstProgressReport:format property. - * - * Element messages containing a "progress" structure are posted on the bus - * whenever progress has been queried (since gst-plugins-good 0.10.6 only). - * - * Since the element was originally designed for debugging purposes, it will - * by default also print information about the current progress to the - * terminal. This can be prevented by setting the #GstProgressReport:silent - * property to %TRUE. - * - * This element is most useful in transcoding pipelines or other situations - * where just querying the pipeline might not lead to the wanted result. For - * progress in TIME format, the element is best placed in a 'raw stream' - * section of the pipeline (or after any demuxers/decoders/parsers). - * - * Three more things should be pointed out: firstly, the element will only - * query progress when data flow happens. If data flow is stalled for some - * reason, no progress messages will be posted. Secondly, there are other - * elements (like qtdemux, for example) that may also post "progress" element - * messages on the bus. Applications should check the source of any element - * messages they receive, if needed. Finally, applications should not take - * action on receiving notification of progress being 100%, they should only - * take action when they receive an EOS message (since the progress reported - * is in reference to an internal point of a pipeline and not the pipeline as - * a whole). - * - * - * Example launch line - * |[ - * gst-launch -m filesrc location=foo.ogg ! decodebin ! progressreport update-freq=1 ! audioconvert ! audioresample ! autoaudiosink - * ]| This shows a progress query where a duration is available. - * |[ - * gst-launch -m audiotestsrc ! progressreport update-freq=1 ! audioconvert ! autoaudiosink - * ]| This shows a progress query where no duration is available. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#include "progressreport.h" - - -enum -{ - ARG_0, - ARG_UPDATE_FREQ, - ARG_SILENT, - ARG_FORMAT -}; - -GstStaticPadTemplate progress_report_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -GstStaticPadTemplate progress_report_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static const GstElementDetails progress_report_details = -GST_ELEMENT_DETAILS ("Progress report", - "Testing", - "Periodically query and report on processing progress", - "Jan Schmidt "); - -#define DEFAULT_UPDATE_FREQ 5 -#define DEFAULT_SILENT FALSE -#define DEFAULT_FORMAT "auto" - -static void gst_progress_report_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_progress_report_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_progress_report_event (GstBaseTransform * trans, - GstEvent * event); -static GstFlowReturn gst_progress_report_transform_ip (GstBaseTransform * trans, - GstBuffer * buf); - -static gboolean gst_progress_report_start (GstBaseTransform * trans); -static gboolean gst_progress_report_stop (GstBaseTransform * trans); - -GST_BOILERPLATE (GstProgressReport, gst_progress_report, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM); - -static void -gst_progress_report_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&progress_report_sink_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&progress_report_src_template)); - - gst_element_class_set_details (element_class, &progress_report_details); -} - -static void -gst_progress_report_finalize (GObject * obj) -{ - GstProgressReport *filter = GST_PROGRESS_REPORT (obj); - - g_free (filter->format); - filter->format = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -gst_progress_report_class_init (GstProgressReportClass * g_class) -{ - GstBaseTransformClass *gstbasetrans_class; - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (g_class); - gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (g_class); - - gobject_class->finalize = gst_progress_report_finalize; - gobject_class->set_property = gst_progress_report_set_property; - gobject_class->get_property = gst_progress_report_get_property; - - g_object_class_install_property (gobject_class, - ARG_UPDATE_FREQ, g_param_spec_int ("update-freq", "Update Frequency", - "Number of seconds between reports when data is flowing", 1, G_MAXINT, - DEFAULT_UPDATE_FREQ, G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - ARG_SILENT, g_param_spec_boolean ("silent", - "Do not print output to stdout", "Do not print output to stdout", - DEFAULT_SILENT, G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - ARG_FORMAT, g_param_spec_string ("format", "format", - "Format to use for the querying", DEFAULT_FORMAT, G_PARAM_READWRITE)); - - gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_progress_report_event); - gstbasetrans_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_progress_report_transform_ip); - gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_progress_report_start); - gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_progress_report_stop); -} - -static void -gst_progress_report_init (GstProgressReport * report, - GstProgressReportClass * g_class) -{ - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (report), TRUE); - - report->update_freq = DEFAULT_UPDATE_FREQ; - report->silent = DEFAULT_SILENT; - report->format = g_strdup (DEFAULT_FORMAT); -} - -static void -gst_progress_report_post_progress (GstProgressReport * filter, - GstFormat format, gint64 current, gint64 total) -{ - GstStructure *s = NULL; - - if (current >= 0 && total > 0) { - gdouble perc; - - perc = gst_util_guint64_to_gdouble (current) * 100.0 / - gst_util_guint64_to_gdouble (total); - perc = CLAMP (perc, 0.0, 100.0); - - /* we provide a "percent" field of integer type to stay compatible - * with qtdemux, but add a second "percent-double" field for those who - * want more precision and are too lazy to calculate it themselves */ - s = gst_structure_new ("progress", "percent", G_TYPE_INT, (gint) perc, - "percent-double", G_TYPE_DOUBLE, perc, "current", G_TYPE_INT64, current, - "total", G_TYPE_INT64, total, NULL); - } else if (current >= 0) { - s = gst_structure_new ("progress", "current", G_TYPE_INT64, current, NULL); - } - - if (s) { - GST_LOG_OBJECT (filter, "posting progress message: %" GST_PTR_FORMAT, s); - gst_structure_set (s, "format", GST_TYPE_FORMAT, format, NULL); - /* can't post it right here because we're holding the object lock */ - filter->pending_msg = gst_message_new_element (GST_OBJECT_CAST (filter), s); - } -} - -static gboolean -gst_progress_report_do_query (GstProgressReport * filter, GstFormat format, - gint hh, gint mm, gint ss) -{ - const gchar *format_name = NULL; - GstPad *sink_pad; - gint64 cur, total; - - sink_pad = GST_BASE_TRANSFORM (filter)->sinkpad; - - GST_LOG_OBJECT (filter, "querying using format %d (%s)", format, - gst_format_get_name (format)); - - if (!gst_pad_query_peer_position (sink_pad, &format, &cur) || - !gst_pad_query_peer_duration (sink_pad, &format, &total)) { - return FALSE; - } - - switch (format) { - case GST_FORMAT_BYTES: - format_name = "bytes"; - break; - case GST_FORMAT_BUFFERS: - format_name = "buffers"; - break; - case GST_FORMAT_PERCENT: - format_name = "percent"; - break; - case GST_FORMAT_TIME: - format_name = "seconds"; - cur /= GST_SECOND; - total /= GST_SECOND; - break; - case GST_FORMAT_DEFAULT:{ - GstCaps *caps; - - format_name = "bogounits"; - caps = GST_PAD_CAPS (GST_BASE_TRANSFORM (filter)->sinkpad); - if (caps && gst_caps_is_fixed (caps) && !gst_caps_is_any (caps)) { - GstStructure *s = gst_caps_get_structure (caps, 0); - const gchar *mime_type = gst_structure_get_name (s); - - if (g_str_has_prefix (mime_type, "video/") || - g_str_has_prefix (mime_type, "image/")) { - format_name = "frames"; - } else if (g_str_has_prefix (mime_type, "audio/")) { - format_name = "samples"; - } - } - break; - } - default:{ - const GstFormatDefinition *details; - - details = gst_format_get_details (format); - if (details) { - format_name = details->nick; - } else { - format_name = "unknown"; - } - break; - } - } - - if (!filter->silent) { - if (total > 0) { - g_print ("%s (%02d:%02d:%02d): %" G_GINT64_FORMAT " / %" - G_GINT64_FORMAT " %s (%4.1f %%)\n", GST_OBJECT_NAME (filter), hh, - mm, ss, cur, total, format_name, (gdouble) cur / total * 100.0); - } else { - g_print ("%s (%02d:%02d:%02d): %" G_GINT64_FORMAT " %s\n", - GST_OBJECT_NAME (filter), hh, mm, ss, cur, format_name); - } - } - - gst_progress_report_post_progress (filter, format, cur, total); - return TRUE; -} - -static void -gst_progress_report_report (GstProgressReport * filter, GTimeVal cur_time) -{ - GstFormat try_formats[] = { GST_FORMAT_TIME, GST_FORMAT_BYTES, - GST_FORMAT_PERCENT, GST_FORMAT_BUFFERS, - GST_FORMAT_DEFAULT - }; - GstMessage *msg; - GstFormat format = GST_FORMAT_UNDEFINED; - gboolean done = FALSE; - glong run_time; - gint hh, mm, ss; - - run_time = cur_time.tv_sec - filter->start_time.tv_sec; - - hh = (run_time / 3600) % 100; - mm = (run_time / 60) % 60; - ss = (run_time % 60); - - GST_OBJECT_LOCK (filter); - - if (filter->format != NULL && strcmp (filter->format, "auto") != 0) { - format = gst_format_get_by_nick (filter->format); - } - - if (format != GST_FORMAT_UNDEFINED) { - done = gst_progress_report_do_query (filter, format, hh, mm, ss); - } else { - gint i; - - for (i = 0; i < G_N_ELEMENTS (try_formats); ++i) { - done = gst_progress_report_do_query (filter, try_formats[i], hh, mm, ss); - if (done) - break; - } - } - - if (!done && !filter->silent) { - g_print ("%s (%2d:%2d:%2d): Could not query position and/or duration\n", - GST_OBJECT_NAME (filter), hh, mm, ss); - } - - msg = filter->pending_msg; - filter->pending_msg = NULL; - GST_OBJECT_UNLOCK (filter); - - if (msg) { - gst_element_post_message (GST_ELEMENT_CAST (filter), msg); - } -} - -static gboolean -gst_progress_report_event (GstBaseTransform * trans, GstEvent * event) -{ - GstProgressReport *filter; - - filter = GST_PROGRESS_REPORT (trans); - - if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { - GTimeVal cur_time; - - g_get_current_time (&cur_time); - gst_progress_report_report (filter, cur_time); - } - return GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event); -} - -static GstFlowReturn -gst_progress_report_transform_ip (GstBaseTransform * trans, GstBuffer * buf) -{ - GstProgressReport *filter; - gboolean need_update; - GTimeVal cur_time; - - g_get_current_time (&cur_time); - - filter = GST_PROGRESS_REPORT (trans); - - /* Check if update_freq seconds have passed since the last update */ - GST_OBJECT_LOCK (filter); - need_update = - ((cur_time.tv_sec - filter->last_report.tv_sec) >= filter->update_freq); - GST_OBJECT_UNLOCK (filter); - - if (need_update) { - gst_progress_report_report (filter, cur_time); - GST_OBJECT_LOCK (filter); - filter->last_report = cur_time; - GST_OBJECT_UNLOCK (filter); - } - - return GST_FLOW_OK; -} - -static gboolean -gst_progress_report_start (GstBaseTransform * trans) -{ - GstProgressReport *filter; - - filter = GST_PROGRESS_REPORT (trans); - - g_get_current_time (&filter->last_report); - filter->start_time = filter->last_report; - - return TRUE; -} - -static gboolean -gst_progress_report_stop (GstBaseTransform * trans) -{ - /* anything we should be doing here? */ - return TRUE; -} - -static void -gst_progress_report_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstProgressReport *filter; - - filter = GST_PROGRESS_REPORT (object); - - switch (prop_id) { - case ARG_UPDATE_FREQ: - GST_OBJECT_LOCK (filter); - filter->update_freq = g_value_get_int (value); - GST_OBJECT_UNLOCK (filter); - break; - case ARG_SILENT: - GST_OBJECT_LOCK (filter); - filter->silent = g_value_get_boolean (value); - GST_OBJECT_UNLOCK (filter); - break; - case ARG_FORMAT: - GST_OBJECT_LOCK (filter); - g_free (filter->format); - filter->format = g_value_dup_string (value); - if (filter->format == NULL) - filter->format = g_strdup ("auto"); - GST_OBJECT_UNLOCK (filter); - break; - default: - break; - } -} - -static void -gst_progress_report_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstProgressReport *filter; - - filter = GST_PROGRESS_REPORT (object); - - switch (prop_id) { - case ARG_UPDATE_FREQ: - GST_OBJECT_LOCK (filter); - g_value_set_int (value, filter->update_freq); - GST_OBJECT_UNLOCK (filter); - break; - case ARG_SILENT: - GST_OBJECT_LOCK (filter); - g_value_set_boolean (value, filter->silent); - GST_OBJECT_UNLOCK (filter); - break; - case ARG_FORMAT: - GST_OBJECT_LOCK (filter); - g_value_set_string (value, filter->format); - GST_OBJECT_UNLOCK (filter); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/gst/debug/progressreport.h b/gst/debug/progressreport.h deleted file mode 100644 index 92886b29..00000000 --- a/gst/debug/progressreport.h +++ /dev/null @@ -1,66 +0,0 @@ -/* GStreamer Progress Report Element - * Copyright (C) <1999> Erik Walthinsen - * Copyright (C) <2003> David Schleef - * Copyright (C) <2004> Jan Schmidt - * Copyright (C) <2006> Tim-Philipp Müller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_PROGRESS_REPORT_H__ -#define __GST_PROGRESS_REPORT_H__ - -#include - -G_BEGIN_DECLS -#define GST_TYPE_PROGRESS_REPORT \ - (gst_progress_report_get_type()) -#define GST_PROGRESS_REPORT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PROGRESS_REPORT,GstProgressReport)) -#define GST_PROGRESS_REPORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PROGRESS_REPORT,GstProgressReportClass)) -#define GST_IS_PROGRESS_REPORT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PROGRESS_REPORT)) -#define GST_IS_PROGRESS_REPORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROGRESS_REPORT)) -typedef struct _GstProgressReport GstProgressReport; -typedef struct _GstProgressReportClass GstProgressReportClass; - -struct _GstProgressReport -{ - GstBaseTransform basetransform; - - GstMessage *pending_msg; - - gint update_freq; - gboolean silent; - GTimeVal start_time; - GTimeVal last_report; - - /* Format used for querying. Using a string here because the - * format might not be registered yet when the property is set */ - gchar *format; -}; - -struct _GstProgressReportClass -{ - GstBaseTransformClass parent_class; -}; - -GType gst_progress_report_get_type (void); - -G_END_DECLS -#endif /* __GST_PROGRESS_REPORT_H__ */ diff --git a/gst/debug/rndbuffersize.c b/gst/debug/rndbuffersize.c deleted file mode 100644 index 7a8abd6b..00000000 --- a/gst/debug/rndbuffersize.c +++ /dev/null @@ -1,371 +0,0 @@ -/* GStreamer - * Copyright (C) 2007 Nokia Corporation (contact ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/** - * SECTION:element-rndbuffersize - * - * This element pulls buffers with random sizes from the source. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -GST_DEBUG_CATEGORY_STATIC (gst_rnd_buffer_size_debug); -#define GST_CAT_DEFAULT gst_rnd_buffer_size_debug - -#define GST_TYPE_RND_BUFFER_SIZE (gst_rnd_buffer_size_get_type()) -#define GST_RND_BUFFER_SIZE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RND_BUFFER_SIZE,GstRndBufferSize)) -#define GST_RND_BUFFER_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RND_BUFFER_SIZE,GstRndBufferSizeClass)) -#define GST_IS_RND_BUFFER_SIZE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RND_BUFFER_SIZE)) -#define GST_IS_RND_BUFFER_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RND_BUFFER_SIZE)) - -typedef struct _GstRndBufferSize GstRndBufferSize; -typedef struct _GstRndBufferSizeClass GstRndBufferSizeClass; - -struct _GstRndBufferSize -{ - GstElement parent; - - /*< private > */ - GRand *rand; - gulong seed; - glong min, max; - - GstPad *sinkpad, *srcpad; - guint64 offset; -}; - -struct _GstRndBufferSizeClass -{ - GstElementClass parent_class; -}; - -enum -{ - ARG_SEED = 1, - ARG_MINIMUM, - ARG_MAXIMUM -}; - -#define DEFAULT_SEED 0 -#define DEFAULT_MIN 1 -#define DEFAULT_MAX (8*1024) - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static void gst_rnd_buffer_size_finalize (GObject * object); -static void gst_rnd_buffer_size_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rnd_buffer_size_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_rnd_buffer_size_activate (GstPad * pad); -static gboolean gst_rnd_buffer_size_activate_pull (GstPad * pad, - gboolean active); -static void gst_rnd_buffer_size_loop (GstRndBufferSize * self); -static GstStateChangeReturn gst_rnd_buffer_size_change_state (GstElement * - element, GstStateChange transition); - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_rnd_buffer_size_debug, "rndbuffersize", 0, \ - "rndbuffersize element"); - -GST_BOILERPLATE_FULL (GstRndBufferSize, gst_rnd_buffer_size, GstElement, - GST_TYPE_ELEMENT, DEBUG_INIT); - - -static void -gst_rnd_buffer_size_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sink_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&src_template)); - - gst_element_class_set_details_simple (gstelement_class, "Random buffer size", - "Testing", "pull random sized buffers", - "Stefan Kost )"); -} - - -static void -gst_rnd_buffer_size_class_init (GstRndBufferSizeClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - - gobject_class->set_property = - GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_set_property); - gobject_class->get_property = - GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_get_property); - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_finalize); - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_change_state); - - /* FIXME 0.11: these should all be int instead of long, to avoid bugs - * when passing these as varargs with g_object_set(), and there was no - * reason to use long in the first place here */ - g_object_class_install_property (gobject_class, ARG_SEED, - g_param_spec_ulong ("seed", "random number seed", - "seed for randomness (initialized when going from READY to PAUSED)", - 0, G_MAXUINT32, DEFAULT_SEED, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, ARG_MINIMUM, - g_param_spec_long ("min", "mininum", "mininum buffer size", - 0, G_MAXINT32, DEFAULT_MIN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, ARG_MAXIMUM, - g_param_spec_long ("max", "maximum", "maximum buffer size", - 1, G_MAXINT32, DEFAULT_MAX, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); -} - -static void -gst_rnd_buffer_size_init (GstRndBufferSize * self, - GstRndBufferSizeClass * g_class) -{ - self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_activate_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_activate)); - gst_pad_set_activatepull_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_activate_pull)); - gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); - - self->srcpad = gst_pad_new_from_static_template (&src_template, "src"); - gst_element_add_pad (GST_ELEMENT (self), self->srcpad); -} - - -static void -gst_rnd_buffer_size_finalize (GObject * object) -{ - GstRndBufferSize *self = GST_RND_BUFFER_SIZE (object); - - if (self->rand) { - g_rand_free (self->rand); - self->rand = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - - -static void -gst_rnd_buffer_size_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRndBufferSize *self = GST_RND_BUFFER_SIZE (object); - - switch (prop_id) { - case ARG_SEED: - self->seed = g_value_get_ulong (value); - break; - case ARG_MINIMUM: - self->min = g_value_get_long (value); - break; - case ARG_MAXIMUM: - self->max = g_value_get_long (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -gst_rnd_buffer_size_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstRndBufferSize *self = GST_RND_BUFFER_SIZE (object); - - switch (prop_id) { - case ARG_SEED: - g_value_set_ulong (value, self->seed); - break; - case ARG_MINIMUM: - g_value_set_long (value, self->min); - break; - case ARG_MAXIMUM: - g_value_set_long (value, self->max); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static gboolean -gst_rnd_buffer_size_activate (GstPad * pad) -{ - if (gst_pad_check_pull_range (pad)) { - return gst_pad_activate_pull (pad, TRUE); - } else { - GST_INFO_OBJECT (pad, "push mode not supported"); - return FALSE; - } -} - - -static gboolean -gst_rnd_buffer_size_activate_pull (GstPad * pad, gboolean active) -{ - GstRndBufferSize *self = GST_RND_BUFFER_SIZE (GST_OBJECT_PARENT (pad)); - - if (active) { - GST_INFO_OBJECT (self, "starting pull"); - return gst_pad_start_task (pad, (GstTaskFunction) gst_rnd_buffer_size_loop, - self); - } else { - GST_INFO_OBJECT (self, "stopping pull"); - return gst_pad_stop_task (pad); - } -} - - -static void -gst_rnd_buffer_size_loop (GstRndBufferSize * self) -{ - GstBuffer *buf = NULL; - GstFlowReturn ret; - guint num_bytes; - - if (G_UNLIKELY (self->min > self->max)) - goto bogus_minmax; - - if (G_UNLIKELY (self->min != self->max)) { - num_bytes = g_rand_int_range (self->rand, self->min, self->max); - } else { - num_bytes = self->min; - } - - GST_LOG_OBJECT (self, "pulling %u bytes at offset %" G_GUINT64_FORMAT, - num_bytes, self->offset); - - ret = gst_pad_pull_range (self->sinkpad, self->offset, num_bytes, &buf); - - if (ret != GST_FLOW_OK) - goto pull_failed; - - if (GST_BUFFER_SIZE (buf) < num_bytes) { - GST_WARNING_OBJECT (self, "short buffer: %u bytes", GST_BUFFER_SIZE (buf)); - } - - self->offset += GST_BUFFER_SIZE (buf); - - ret = gst_pad_push (self->srcpad, buf); - - if (ret != GST_FLOW_OK) - goto push_failed; - - return; - -pause_task: - { - GST_DEBUG_OBJECT (self, "pausing task"); - gst_pad_pause_task (self->sinkpad); - return; - } - -pull_failed: - { - if (ret == GST_FLOW_UNEXPECTED) { - GST_DEBUG_OBJECT (self, "eos"); - gst_pad_push_event (self->srcpad, gst_event_new_eos ()); - } else { - GST_WARNING_OBJECT (self, "pull_range flow: %s", gst_flow_get_name (ret)); - } - goto pause_task; - } - -push_failed: - { - GST_DEBUG_OBJECT (self, "push flow: %s", gst_flow_get_name (ret)); - if (ret == GST_FLOW_UNEXPECTED) { - GST_DEBUG_OBJECT (self, "eos"); - gst_pad_push_event (self->srcpad, gst_event_new_eos ()); - } else if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { - GST_ELEMENT_ERROR (self, STREAM, FAILED, - ("Internal data stream error."), - ("streaming stopped, reason: %s", gst_flow_get_name (ret))); - } - goto pause_task; - } - -bogus_minmax: - { - GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, - ("The minimum buffer size is smaller than the maximum buffer size."), - ("buffer sizes: max=%ld, min=%ld", self->min, self->max)); - goto pause_task; - } -} - -static GstStateChangeReturn -gst_rnd_buffer_size_change_state (GstElement * element, - GstStateChange transition) -{ - GstRndBufferSize *self = GST_RND_BUFFER_SIZE (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - self->offset = 0; - if (!self->rand) { - self->rand = g_rand_new_with_seed (self->seed); - } - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (self->rand) { - g_rand_free (self->rand); - self->rand = NULL; - } - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - return ret; -} diff --git a/gst/debug/testplugin.c b/gst/debug/testplugin.c deleted file mode 100644 index dbb1e618..00000000 --- a/gst/debug/testplugin.c +++ /dev/null @@ -1,318 +0,0 @@ -/* GStreamer - * Copyright (C) 2004 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include "tests.h" - -GST_DEBUG_CATEGORY_STATIC (gst_test_debug); -#define GST_CAT_DEFAULT gst_test_debug - -/* This plugin does all the tests registered in the tests.h file - */ - -#define GST_TYPE_TEST \ - (gst_test_get_type()) -#define GST_TEST(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST,GstTest)) -#define GST_TEST_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST,GstTestClass)) -#define GST_TEST_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_TEST,GstTestClass)) -#define GST_IS_TEST(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST)) -#define GST_IS_TEST_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST)) - -typedef struct _GstTest GstTest; -typedef struct _GstTestClass GstTestClass; - -struct _GstTest -{ - GstBaseSink basesink; - - gpointer tests[TESTS_COUNT]; - GValue values[TESTS_COUNT]; -}; - -struct _GstTestClass -{ - GstBaseSinkClass parent_class; - - gchar *param_names[2 * TESTS_COUNT]; -}; - -static void gst_test_finalize (GstTest * test); - -static gboolean gst_test_start (GstBaseSink * trans); -static gboolean gst_test_stop (GstBaseSink * trans); -static gboolean gst_test_sink_event (GstBaseSink * basesink, GstEvent * event); -static GstFlowReturn gst_test_render_buffer (GstBaseSink * basesink, - GstBuffer * buf); - -static void gst_test_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_test_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - - -static const GstElementDetails details = GST_ELEMENT_DETAILS ("Test plugin", - "Testing", - "perform a number of tests", - "Benjamin Otte "); - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_test_debug, "testsink", 0, \ - "debugging category for testsink element"); - -GST_BOILERPLATE_FULL (GstTest, gst_test, GstBaseSink, GST_TYPE_BASE_SINK, - DEBUG_INIT); - - -static void -gst_test_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sinktemplate)); - - gst_element_class_set_details (gstelement_class, &details); -} - -static void -gst_test_class_init (GstTestClass * klass) -{ - GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - guint i; - - object_class->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property); - object_class->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property); - - object_class->finalize = (GObjectFinalizeFunc) gst_test_finalize; - - for (i = 0; i < TESTS_COUNT; i++) { - GParamSpec *spec; - - spec = tests[i].get_spec (&tests[i], FALSE); - klass->param_names[2 * i] = g_strdup (g_param_spec_get_name (spec)); - g_object_class_install_property (object_class, 2 * i + 1, spec); - spec = tests[i].get_spec (&tests[i], TRUE); - klass->param_names[2 * i + 1] = g_strdup (g_param_spec_get_name (spec)); - g_object_class_install_property (object_class, 2 * i + 2, spec); - } - - basesink_class->preroll = GST_DEBUG_FUNCPTR (gst_test_render_buffer); - basesink_class->render = GST_DEBUG_FUNCPTR (gst_test_render_buffer); - basesink_class->event = GST_DEBUG_FUNCPTR (gst_test_sink_event); - basesink_class->start = GST_DEBUG_FUNCPTR (gst_test_start); - basesink_class->stop = GST_DEBUG_FUNCPTR (gst_test_stop); -} - -static void -gst_test_init (GstTest * test, GstTestClass * g_class) -{ - GstTestClass *klass; - guint i; - - klass = GST_TEST_GET_CLASS (test); - for (i = 0; i < TESTS_COUNT; i++) { - GParamSpec *spec = g_object_class_find_property (G_OBJECT_CLASS (klass), - klass->param_names[2 * i + 1]); - - g_value_init (&test->values[i], G_PARAM_SPEC_VALUE_TYPE (spec)); - } -} - -static void -gst_test_finalize (GstTest * test) -{ - guint i; - - for (i = 0; i < TESTS_COUNT; i++) { - g_value_unset (&test->values[i]); - } - - G_OBJECT_CLASS (parent_class)->finalize ((GObject *) test); -} - -static void -tests_unset (GstTest * test) -{ - guint i; - - for (i = 0; i < TESTS_COUNT; i++) { - if (test->tests[i]) { - tests[i].free (test->tests[i]); - test->tests[i] = NULL; - } - } -} - -static void -tests_set (GstTest * test) -{ - guint i; - - for (i = 0; i < TESTS_COUNT; i++) { - g_assert (test->tests[i] == NULL); - test->tests[i] = tests[i].new (&tests[i]); - } -} - -static gboolean -gst_test_sink_event (GstBaseSink * basesink, GstEvent * event) -{ - GstTestClass *klass = GST_TEST_GET_CLASS (basesink); - GstTest *test = GST_TEST (basesink); - gboolean ret = FALSE; - - switch (GST_EVENT_TYPE (event)) { -/* - case GST_EVENT_NEWSEGMENT: - if (GST_EVENT_DISCONT_NEW_MEDIA (event)) { - tests_unset (test); - tests_set (test); - } - break; -*/ - case GST_EVENT_EOS:{ - gint i; - - g_object_freeze_notify (G_OBJECT (test)); - for (i = 0; i < TESTS_COUNT; i++) { - if (test->tests[i]) { - if (!tests[i].finish (test->tests[i], &test->values[i])) { - GValue v = { 0, }; - gchar *real, *expected; - - expected = gst_value_serialize (&test->values[i]); - g_value_init (&v, G_VALUE_TYPE (&test->values[i])); - g_object_get_property (G_OBJECT (test), klass->param_names[2 * i], - &v); - real = gst_value_serialize (&v); - g_value_unset (&v); - GST_ELEMENT_ERROR (test, STREAM, FORMAT, (NULL), - ("test %s returned value \"%s\" and not expected value \"%s\"", - klass->param_names[2 * i], real, expected)); - g_free (real); - g_free (expected); - } - g_object_notify (G_OBJECT (test), klass->param_names[2 * i]); - } - } - g_object_thaw_notify (G_OBJECT (test)); - ret = TRUE; - break; - } - default: - break; - } - - return ret; -} - -static GstFlowReturn -gst_test_render_buffer (GstBaseSink * basesink, GstBuffer * buf) -{ - GstTest *test = GST_TEST (basesink); - guint i; - - for (i = 0; i < TESTS_COUNT; i++) { - if (test->tests[i]) { - tests[i].add (test->tests[i], buf); - } - } - return GST_FLOW_OK; -} - -static gboolean -gst_test_start (GstBaseSink * sink) -{ - GstTest *test = GST_TEST (sink); - - tests_set (test); - return TRUE; -} - -static gboolean -gst_test_stop (GstBaseSink * sink) -{ - GstTest *test = GST_TEST (sink); - - tests_unset (test); - return TRUE; -} - -static void -gst_test_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstTest *test = GST_TEST (object); - - if (prop_id == 0 || prop_id > 2 * TESTS_COUNT) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - return; - } - - if (prop_id % 2) { - /* real values can't be set */ - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } else { - /* expected values */ - GST_OBJECT_LOCK (test); - g_value_copy (value, &test->values[prop_id / 2 - 1]); - GST_OBJECT_UNLOCK (test); - } -} - -static void -gst_test_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstTest *test = GST_TEST (object); - guint id = (prop_id - 1) / 2; - - if (prop_id == 0 || prop_id > 2 * TESTS_COUNT) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - return; - } - - GST_OBJECT_LOCK (test); - - if (prop_id % 2) { - /* real values */ - tests[id].get_value (test->tests[id], value); - } else { - /* expected values */ - g_value_copy (&test->values[id], value); - } - - GST_OBJECT_UNLOCK (test); -} diff --git a/gst/debug/tests.c b/gst/debug/tests.c deleted file mode 100644 index cd382782..00000000 --- a/gst/debug/tests.c +++ /dev/null @@ -1,568 +0,0 @@ -/* GStreamer - * Copyright (C) 2004 Benjamin Otte - * - * includes code based on glibc 2.2.3's crypt/md5.c, - * Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "tests.h" -#include -#include - - -/* - *** LENGTH *** - */ - -typedef struct -{ - gint64 value; -} -LengthTest; - -static GParamSpec * -length_get_spec (const GstTestInfo * info, gboolean compare_value) -{ - if (compare_value) { - return g_param_spec_int64 ("expected-length", "expected length", - "expected length of stream", -1, G_MAXINT64, -1, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT); - } else { - return g_param_spec_int64 ("length", "length", "length of stream", - -1, G_MAXINT64, -1, G_PARAM_READABLE); - } -} - -static gpointer -length_new (const GstTestInfo * info) -{ - return g_new0 (LengthTest, 1); -} - -static void -length_add (gpointer test, GstBuffer * buffer) -{ - LengthTest *t = test; - - t->value += GST_BUFFER_SIZE (buffer); -} - -static gboolean -length_finish (gpointer test, GValue * value) -{ - LengthTest *t = test; - - if (g_value_get_int64 (value) == -1) - return TRUE; - - return t->value == g_value_get_int64 (value); -} - -static void -length_get_value (gpointer test, GValue * value) -{ - LengthTest *t = test; - - g_value_set_int64 (value, t ? t->value : -1); -} - -/* - *** BUFFER COUNT *** - */ - -static GParamSpec * -buffer_count_get_spec (const GstTestInfo * info, gboolean compare_value) -{ - if (compare_value) { - return g_param_spec_int64 ("expected-buffer-count", "expected buffer count", - "expected number of buffers in stream", - -1, G_MAXINT64, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); - } else { - return g_param_spec_int64 ("buffer-count", "buffer count", - "number of buffers in stream", -1, G_MAXINT64, -1, G_PARAM_READABLE); - } -} - -static void -buffer_count_add (gpointer test, GstBuffer * buffer) -{ - LengthTest *t = test; - - t->value++; -} - -/* - *** TIMESTAMP / DURATION MATCHING *** - */ - -typedef struct -{ - guint64 diff; - guint count; - GstClockTime expected; -} -TimeDurTest; - -static GParamSpec * -timedur_get_spec (const GstTestInfo * info, gboolean compare_value) -{ - if (compare_value) { - return g_param_spec_int64 ("allowed-timestamp-deviation", - "allowed timestamp deviation", - "allowed average difference in usec between timestamp of next buffer " - "and expected timestamp from analyzing last buffer", - -1, G_MAXINT64, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); - } else { - return g_param_spec_int64 ("timestamp-deviation", - "timestamp deviation", - "average difference in usec between timestamp of next buffer " - "and expected timestamp from analyzing last buffer", - -1, G_MAXINT64, -1, G_PARAM_READABLE); - } -} - -static gpointer -timedur_new (const GstTestInfo * info) -{ - TimeDurTest *ret = g_new0 (TimeDurTest, 1); - - ret->expected = GST_CLOCK_TIME_NONE; - - return ret; -} - -static void -timedur_add (gpointer test, GstBuffer * buffer) -{ - TimeDurTest *t = test; - - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (t->expected)) { - t->diff += labs (GST_BUFFER_TIMESTAMP (buffer) - t->expected); - t->count++; - } - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_BUFFER_DURATION_IS_VALID (buffer)) { - t->expected = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); - } else { - t->expected = GST_CLOCK_TIME_NONE; - } -} - -static gboolean -timedur_finish (gpointer test, GValue * value) -{ - TimeDurTest *t = test; - - if (g_value_get_int64 (value) == -1) - return TRUE; - - return (t->diff / MAX (1, t->count)) <= g_value_get_int64 (value); -} - -static void -timedur_get_value (gpointer test, GValue * value) -{ - TimeDurTest *t = test; - - g_value_set_int64 (value, t ? (t->diff / MAX (1, t->count)) : -1); -} - -/* - *** MD5 *** - */ - -typedef struct -{ - /* md5 information */ - guint32 A; - guint32 B; - guint32 C; - guint32 D; - - guint32 total[2]; - guint32 buflen; - gchar buffer[128]; - - gchar result[33]; -} -MD5Test; - -static void md5_process_block (const void *buffer, size_t len, MD5Test * ctx); -static void md5_read_ctx (MD5Test * ctx, gchar * result); - -static GParamSpec * -md5_get_spec (const GstTestInfo * info, gboolean compare_value) -{ - if (compare_value) { - return g_param_spec_string ("expected-md5", "expected md5", - "expected md5 of processing the whole data", - "---", G_PARAM_READWRITE | G_PARAM_CONSTRUCT); - } else { - return g_param_spec_string ("md5", "md5", - "md5 of processing the whole data", "---", G_PARAM_READABLE); - } -} - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const guchar fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - -/* MD5 functions */ -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -static gpointer -md5_new (const GstTestInfo * info) -{ - MD5Test *ctx = g_new (MD5Test, 1); - - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; - - memset (ctx->result, 0, 33); - - return ctx; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -static gboolean -md5_finish (gpointer test, GValue * value) -{ - MD5Test *ctx = test; - const gchar *str_val = g_value_get_string (value); - - /* Take yet unprocessed bytes into account. */ - guint32 bytes = ctx->buflen; - size_t pad; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; - memcpy (&ctx->buffer[bytes], fillbuf, pad); - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - *(guint32 *) & ctx->buffer[bytes + pad] = GUINT32_TO_LE (ctx->total[0] << 3); - *(guint32 *) & ctx->buffer[bytes + pad + 4] = - GUINT32_TO_LE ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - - /* Process last bytes. */ - md5_process_block (ctx->buffer, bytes + pad + 8, ctx); - - md5_read_ctx (ctx, ctx->result); - if (g_str_equal (str_val, "---")) - return TRUE; - if (g_str_equal (str_val, ctx->result)) - return TRUE; - return FALSE; -} - -/* Put result from CTX in first 16 bytes following RESBUF. The result - must be in little endian byte order. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -static void -md5_read_ctx (MD5Test * ctx, gchar * result) -{ - guint32 resbuf[4]; - guint i; - - resbuf[0] = GUINT32_TO_LE (ctx->A); - resbuf[1] = GUINT32_TO_LE (ctx->B); - resbuf[2] = GUINT32_TO_LE (ctx->C); - resbuf[3] = GUINT32_TO_LE (ctx->D); - - for (i = 0; i < 16; i++) - sprintf (result + i * 2, "%02x", ((guchar *) resbuf)[i]); -} - -static void -md5_add (gpointer test, GstBuffer * gstbuffer) -{ - const void *buffer = GST_BUFFER_DATA (gstbuffer); - gsize len = GST_BUFFER_SIZE (gstbuffer); - MD5Test *ctx = test; - - /*const void aligned_buffer = buffer; */ - - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) { - gsize left_over = ctx->buflen; - gsize add = 128 - left_over > len ? len : 128 - left_over; - - /* Only put full words in the buffer. */ - /* Forcing alignment here appears to be only an optimization. - * The glibc source uses __alignof__, which seems to be a - * gratuitous usage of a GCC extension, when sizeof() will - * work fine. (And don't question the sanity of using - * sizeof(guint32) instead of 4. */ - /* add -= add % __alignof__ (guint32); */ - add -= add % sizeof (guint32); - - memcpy (&ctx->buffer[left_over], buffer, add); - ctx->buflen += add; - - if (ctx->buflen > 64) { - md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap. */ - memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ctx->buflen); - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len > 64) { - md5_process_block (buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) { - size_t left_over = ctx->buflen; - - memcpy (&ctx->buffer[left_over], buffer, len); - left_over += len; - if (left_over >= 64) { - md5_process_block (ctx->buffer, 64, ctx); - left_over -= 64; - memcpy (ctx->buffer, &ctx->buffer[64], left_over); - } - ctx->buflen = left_over; - } -} - - -/* These are the four functions used in the four steps of the MD5 algorithm - and defined in the RFC 1321. The first function is a little bit optimized - (as found in Colin Plumbs public domain implementation). */ -/* #define FF(b, c, d) ((b & c) | (~b & d)) */ -#define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF (d, b, c) -#define FH(b, c, d) (b ^ c ^ d) -#define FI(b, c, d) (c ^ (b | ~d)) - -static void -md5_process_block (const void *buffer, size_t len, MD5Test * ctx) -{ -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. */ - guint32 correct_words[16]; - const guint32 *words = buffer; - size_t nwords = len / sizeof (guint32); - const guint32 *endp = words + nwords; - guint32 A = ctx->A; - guint32 B = ctx->B; - guint32 C = ctx->C; - guint32 D = ctx->D; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += len; - if (ctx->total[0] < len) - ++ctx->total[1]; - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - while (words < endp) { - guint32 *cwp = correct_words; - guint32 A_save = A; - guint32 B_save = B; - guint32 C_save = C; - guint32 D_save = D; - - /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing - unit is a 32-bit word and it is determined to work on words in - little endian byte order we perhaps have to change the byte order - before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a += FF (b, c, d) + (*cwp++ = GUINT32_TO_LE (*words)) + T; \ - ++words; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* It is unfortunate that C does not provide an operator for - cyclic rotation. Hope the C compiler is smart enough. */ -#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) - - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - - T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 - */ - - /* Round 1. */ - OP (A, B, C, D, 7, 0xd76aa478); - OP (D, A, B, C, 12, 0xe8c7b756); - OP (C, D, A, B, 17, 0x242070db); - OP (B, C, D, A, 22, 0xc1bdceee); - OP (A, B, C, D, 7, 0xf57c0faf); - OP (D, A, B, C, 12, 0x4787c62a); - OP (C, D, A, B, 17, 0xa8304613); - OP (B, C, D, A, 22, 0xfd469501); - OP (A, B, C, D, 7, 0x698098d8); - OP (D, A, B, C, 12, 0x8b44f7af); - OP (C, D, A, B, 17, 0xffff5bb1); - OP (B, C, D, A, 22, 0x895cd7be); - OP (A, B, C, D, 7, 0x6b901122); - OP (D, A, B, C, 12, 0xfd987193); - OP (C, D, A, B, 17, 0xa679438e); - OP (B, C, D, A, 22, 0x49b40821); - - /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first - argument specifying the function to use. */ -#undef OP -#define OP(f, a, b, c, d, k, s, T) \ - do \ - { \ - a += f (b, c, d) + correct_words[k] + T; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* Round 2. */ - OP (FG, A, B, C, D, 1, 5, 0xf61e2562); - OP (FG, D, A, B, C, 6, 9, 0xc040b340); - OP (FG, C, D, A, B, 11, 14, 0x265e5a51); - OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP (FG, A, B, C, D, 5, 5, 0xd62f105d); - OP (FG, D, A, B, C, 10, 9, 0x02441453); - OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP (FG, D, A, B, C, 14, 9, 0xc33707d6); - OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP (FG, B, C, D, A, 8, 20, 0x455a14ed); - OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP (FG, C, D, A, B, 7, 14, 0x676f02d9); - OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); - - /* Round 3. */ - OP (FH, A, B, C, D, 5, 4, 0xfffa3942); - OP (FH, D, A, B, C, 8, 11, 0x8771f681); - OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP (FH, B, C, D, A, 14, 23, 0xfde5380c); - OP (FH, A, B, C, D, 1, 4, 0xa4beea44); - OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP (FH, B, C, D, A, 6, 23, 0x04881d05); - OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); - - /* Round 4. */ - OP (FI, A, B, C, D, 0, 6, 0xf4292244); - OP (FI, D, A, B, C, 7, 10, 0x432aff97); - OP (FI, C, D, A, B, 14, 15, 0xab9423a7); - OP (FI, B, C, D, A, 5, 21, 0xfc93a039); - OP (FI, A, B, C, D, 12, 6, 0x655b59c3); - OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP (FI, C, D, A, B, 10, 15, 0xffeff47d); - OP (FI, B, C, D, A, 1, 21, 0x85845dd1); - OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP (FI, C, D, A, B, 6, 15, 0xa3014314); - OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP (FI, A, B, C, D, 4, 6, 0xf7537e82); - OP (FI, D, A, B, C, 11, 10, 0xbd3af235); - OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP (FI, B, C, D, A, 9, 21, 0xeb86d391); - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - } - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; -} - -static void -md5_get_value (gpointer test, GValue * value) -{ - MD5Test *ctx = test; - - if (!ctx) { - g_value_set_string (value, "---"); - } else if (ctx->result[0] == 0) { - gchar *str = g_new (gchar, 33); - - str[32] = 0; - md5_read_ctx (ctx, str); - g_value_take_string (value, str); - } else { - g_value_set_string (value, ctx->result); - } -} - -/* - *** TESTINFO *** - */ - -const GstTestInfo tests[] = { - {length_get_spec, length_new, length_add, - length_finish, length_get_value, g_free}, - {buffer_count_get_spec, length_new, buffer_count_add, - length_finish, length_get_value, g_free}, - {timedur_get_spec, timedur_new, timedur_add, - timedur_finish, timedur_get_value, g_free}, - {md5_get_spec, md5_new, md5_add, - md5_finish, md5_get_value, g_free} -}; diff --git a/gst/debug/tests.h b/gst/debug/tests.h deleted file mode 100644 index 9926af62..00000000 --- a/gst/debug/tests.h +++ /dev/null @@ -1,43 +0,0 @@ -/* GStreamer - * Copyright (C) 2004 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#ifndef __GST_TESTS_H__ -#define __GST_TESTS_H__ - - -typedef struct _GstTestInfo GstTestInfo; - -struct _GstTestInfo -{ - GParamSpec *(*get_spec) (const GstTestInfo * info, gboolean compare_value); - gpointer (*new) (const GstTestInfo * info); - void (*add) (gpointer test, GstBuffer * buffer); - gboolean (*finish) (gpointer test, GValue * value); - void (*get_value) (gpointer test, GValue * value); - void (*free) (gpointer test); -}; - -extern const GstTestInfo tests[]; -/* keep up to date! */ -#define TESTS_COUNT (4) - - -#endif /* __GST_TESTS_H__ */ diff --git a/gst/debugutils/Makefile.am b/gst/debugutils/Makefile.am new file mode 100644 index 00000000..8c53cdf3 --- /dev/null +++ b/gst/debugutils/Makefile.am @@ -0,0 +1,49 @@ +if GST_HAVE_MMAP +EFENCE_PLUGIN=libgstefence.la +else +EFENCE_PLUGIN= +endif + +plugin_LTLIBRARIES = $(EFENCE_PLUGIN) libgstdebug.la libgstnavigationtest.la + +noinst_HEADERS = \ + efence.h \ + gstnavigationtest.h \ + gstnavseek.h \ + gstpushfilesrc.h \ + gsttaginject.h \ + progressreport.h \ + tests.h + +libgstefence_la_SOURCES = efence.c +libgstefence_la_CFLAGS = $(GST_CFLAGS) +libgstefence_la_LIBADD = $(GST_LIBS) +libgstefence_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstefence_la_LIBTOOLFLAGS = --tag=disable-static + +libgstnavigationtest_la_SOURCES = gstnavigationtest.c +libgstnavigationtest_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) +libgstnavigationtest_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ + $(GST_PLUGINS_BASE_LIBS) -lgstvideo-@GST_MAJORMINOR@ $(LIBM) +libgstnavigationtest_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstnavigationtest_la_LIBTOOLFLAGS = --tag=disable-static + +libgstdebug_la_SOURCES = \ + gstdebug.c \ + breakmydata.c \ + gstnavseek.c \ + gstpushfilesrc.c \ + gsttaginject.c \ + rndbuffersize.c \ + progressreport.c \ + tests.c \ + testplugin.c + +# negotiation.c + +libgstdebug_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) +libgstdebug_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) +libgstdebug_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstdebug_la_LIBTOOLFLAGS = --tag=disable-static + diff --git a/gst/debugutils/breakmydata.c b/gst/debugutils/breakmydata.c new file mode 100644 index 00000000..63e30b6c --- /dev/null +++ b/gst/debugutils/breakmydata.c @@ -0,0 +1,297 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-breakmydata + * + * This element modifies the contents of the buffer it is passed randomly + * according to the parameters set. + * It otherwise acts as an identity. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +GST_DEBUG_CATEGORY_STATIC (gst_break_my_data_debug); +#define GST_CAT_DEFAULT gst_break_my_data_debug + +#define GST_TYPE_BREAK_MY_DATA \ + (gst_break_my_data_get_type()) +#define GST_BREAK_MY_DATA(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BREAK_MY_DATA,GstBreakMyData)) +#define GST_BREAK_MY_DATA_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BREAK_MY_DATA,GstBreakMyDataClass)) +#define GST_IS_BREAK_MY_DATA(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BREAK_MY_DATA)) +#define GST_IS_BREAK_MY_DATA_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BREAK_MY_DATA)) + +enum +{ + ARG_0, + ARG_SEED, + ARG_SET_TO, + ARG_SKIP, + ARG_PROBABILITY +}; + +typedef struct _GstBreakMyData GstBreakMyData; +typedef struct _GstBreakMyDataClass GstBreakMyDataClass; + +struct _GstBreakMyData +{ + GstBaseTransform basetransform; + + GRand *rand; + guint skipped; + + guint32 seed; + gint set; + guint skip; + gdouble probability; +}; + +struct _GstBreakMyDataClass +{ + GstBaseTransformClass parent_class; +}; + +static void gst_break_my_data_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_break_my_data_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_break_my_data_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); +static gboolean gst_break_my_data_stop (GstBaseTransform * trans); +static gboolean gst_break_my_data_start (GstBaseTransform * trans); + +static const GstElementDetails details = GST_ELEMENT_DETAILS ("Break my data", + "Testing", + "randomly change data in the stream", + "Benjamin Otte "); + +GstStaticPadTemplate bmd_src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GstStaticPadTemplate bmd_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_break_my_data_debug, "breakmydata", 0, \ + "debugging category for breakmydata element"); + +GST_BOILERPLATE_FULL (GstBreakMyData, gst_break_my_data, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); + + +static void +gst_break_my_data_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&bmd_sink_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&bmd_src_template)); + + gst_element_class_set_details (gstelement_class, &details); +} + +static void +gst_break_my_data_class_init (GstBreakMyDataClass * klass) +{ + GstBaseTransformClass *gstbasetrans_class; + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_break_my_data_set_property); + gobject_class->get_property = + GST_DEBUG_FUNCPTR (gst_break_my_data_get_property); + + g_object_class_install_property (gobject_class, ARG_SEED, + g_param_spec_uint ("seed", "seed", + "seed for randomness (initialized when going from READY to PAUSED)", + 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, ARG_SET_TO, + g_param_spec_int ("set-to", "set-to", + "set changed bytes to this value (-1 means random value", + -1, G_MAXUINT8, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, ARG_SKIP, + g_param_spec_uint ("skip", "skip", + "amount of bytes skipped at the beginning of stream", + 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, ARG_PROBABILITY, + g_param_spec_double ("probability", "probability", + "probability for each byte in the buffer to be changed", 0.0, 1.0, + 0.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + gstbasetrans_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_break_my_data_transform_ip); + gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_break_my_data_start); + gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_break_my_data_stop); +} + +static void +gst_break_my_data_init (GstBreakMyData * bmd, GstBreakMyDataClass * g_class) +{ + gst_base_transform_set_in_place (GST_BASE_TRANSFORM (bmd), TRUE); + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (bmd), TRUE); +} + +static void +gst_break_my_data_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBreakMyData *bmd = GST_BREAK_MY_DATA (object); + + GST_OBJECT_LOCK (bmd); + + switch (prop_id) { + case ARG_SEED: + bmd->seed = g_value_get_uint (value); + break; + case ARG_SET_TO: + bmd->set = g_value_get_int (value); + break; + case ARG_SKIP: + bmd->skip = g_value_get_uint (value); + break; + case ARG_PROBABILITY: + bmd->probability = g_value_get_double (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (bmd); +} + +static void +gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstBreakMyData *bmd = GST_BREAK_MY_DATA (object); + + GST_OBJECT_LOCK (bmd); + + switch (prop_id) { + case ARG_SEED: + g_value_set_uint (value, bmd->seed); + break; + case ARG_SET_TO: + g_value_set_int (value, bmd->set); + break; + case ARG_SKIP: + g_value_set_uint (value, bmd->skip); + break; + case ARG_PROBABILITY: + g_value_set_double (value, bmd->probability); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (bmd); +} + +static GstFlowReturn +gst_break_my_data_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); + guint i, size; + + g_return_val_if_fail (gst_buffer_is_writable (buf), GST_FLOW_ERROR); + + GST_OBJECT_LOCK (bmd); + + if (bmd->skipped < bmd->skip) { + i = bmd->skip - bmd->skipped; + } else { + i = 0; + } + + size = GST_BUFFER_SIZE (buf); + + GST_LOG_OBJECT (bmd, + "got buffer %p (size %u, timestamp %" G_GUINT64_FORMAT ", offset %" + G_GUINT64_FORMAT "", buf, size, GST_BUFFER_TIMESTAMP (buf), + GST_BUFFER_OFFSET (buf)); + + for (; i < size; i++) { + if (g_rand_double_range (bmd->rand, 0, 1.0) <= bmd->probability) { + guint8 new; + + if (bmd->set < 0) { + new = g_rand_int_range (bmd->rand, 0, 256); + } else { + new = bmd->set; + } + GST_INFO_OBJECT (bmd, "changing byte %u from 0x%02X to 0x%02X", i, + (guint) GST_READ_UINT8 (GST_BUFFER_DATA (buf) + i), + (guint) ((guint8) new)); + GST_BUFFER_DATA (buf)[i] = new; + } + } + /* don't overflow */ + bmd->skipped += MIN (G_MAXUINT - bmd->skipped, GST_BUFFER_SIZE (buf)); + + GST_OBJECT_UNLOCK (bmd); + + return GST_FLOW_OK; +} + +static gboolean +gst_break_my_data_start (GstBaseTransform * trans) +{ + GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); + + GST_OBJECT_LOCK (bmd); + bmd->rand = g_rand_new_with_seed (bmd->seed); + bmd->skipped = 0; + GST_OBJECT_UNLOCK (bmd); + + return TRUE; +} + +static gboolean +gst_break_my_data_stop (GstBaseTransform * trans) +{ + GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); + + GST_OBJECT_LOCK (bmd); + g_rand_free (bmd->rand); + bmd->rand = NULL; + GST_OBJECT_UNLOCK (bmd); + + return TRUE; +} diff --git a/gst/debugutils/debug.vcproj b/gst/debugutils/debug.vcproj new file mode 100644 index 00000000..3093ae7b --- /dev/null +++ b/gst/debugutils/debug.vcproj @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst/debugutils/efence.c b/gst/debugutils/efence.c new file mode 100644 index 00000000..a46bf1ac --- /dev/null +++ b/gst/debugutils/efence.c @@ -0,0 +1,537 @@ +/* + * GStreamer + * Copyright (C) 1999-2001 Erik Walthinsen + * Copyright (C) 2002 David A. Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#include +#include +#include + +#include "efence.h" + +#ifndef MAP_ANONYMOUS +#ifdef MAP_ANON +#define MAP_ANONYMOUS MAP_ANON +#else +/* assume we don't need it */ +#define MAP_ANONYMOUS 0 +#endif +#endif + +GST_DEBUG_CATEGORY_STATIC (gst_efence_debug); +#define GST_CAT_DEFAULT gst_efence_debug + +static const GstElementDetails plugin_details = +GST_ELEMENT_DETAILS ("Electric Fence", + "Testing", + "This element converts a stream of normal GStreamer buffers into a " + "stream of buffers that are allocated in such a way that out-of-bounds " + "access to data in the buffer is more likely to cause segmentation " + "faults. This allocation method is very similar to the debugging tool " + "\"Electric Fence\".", + "David A. Schleef "); + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_FENCE_TOP +}; + +static GstStaticPadTemplate gst_efence_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_efence_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static void gst_efence_base_init (gpointer g_class); +static void gst_efence_class_init (GstEFenceClass * klass); +static void gst_efence_init (GstEFence * filter); + +static void gst_efence_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_efence_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_efence_chain (GstPad * pad, GstBuffer * buf); +static GstFlowReturn gst_efence_getrange (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buffer); +static gboolean gst_efence_checkgetrange (GstPad * pad); +static gboolean gst_efence_activate_src_pull (GstPad * pad, gboolean active); + +static GstElementClass *parent_class = NULL; + +typedef struct _GstFencedBuffer GstFencedBuffer; +struct _GstFencedBuffer +{ + GstBuffer buffer; + void *region; + unsigned int length; +}; + +GType gst_fenced_buffer_get_type (void); +static void gst_fenced_buffer_finalize (GstFencedBuffer * buf); +static GstFencedBuffer *gst_fenced_buffer_copy (const GstBuffer * buffer); +static void *gst_fenced_buffer_alloc (GstBuffer * buffer, unsigned int length, + gboolean fence_top); +static GstFlowReturn gst_efence_buffer_alloc (GstPad * pad, guint64 offset, + guint size, GstCaps * caps, GstBuffer ** buf); + +#define GST_TYPE_FENCED_BUFFER (gst_fenced_buffer_get_type()) + +#define GST_IS_FENCED_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_FENCED_BUFFER)) +#define GST_FENCED_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_FENCED_BUFFER, GstFencedBuffer)) + +GType +gst_gst_efence_get_type (void) +{ + static GType plugin_type = 0; + + if (!plugin_type) { + static const GTypeInfo plugin_info = { + sizeof (GstEFenceClass), + gst_efence_base_init, + NULL, + (GClassInitFunc) gst_efence_class_init, + NULL, + NULL, + sizeof (GstEFence), + 0, + (GInstanceInitFunc) gst_efence_init, + }; + + plugin_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstEFence", &plugin_info, 0); + } + return plugin_type; +} + +static void +gst_efence_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_efence_sink_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_efence_src_factory)); + gst_element_class_set_details (element_class, &plugin_details); +} + +/* initialize the plugin's class */ +static void +gst_efence_class_init (GstEFenceClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_efence_set_property; + gobject_class->get_property = gst_efence_get_property; + + g_object_class_install_property (gobject_class, ARG_FENCE_TOP, + g_param_spec_boolean ("fence_top", "Fence Top", + "Align buffers with top of fenced region", TRUE, G_PARAM_READWRITE)); +} + +/* initialize the new element + * instantiate pads and add them to element + * set functions + * initialize structure + */ +static void +gst_efence_init (GstEFence * filter) +{ + filter->sinkpad = + gst_pad_new_from_static_template (&gst_efence_sink_factory, "sink"); + gst_pad_set_getcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); + gst_pad_set_setcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps)); + gst_pad_set_chain_function (filter->sinkpad, + GST_DEBUG_FUNCPTR (gst_efence_chain)); + gst_pad_set_bufferalloc_function (filter->sinkpad, + GST_DEBUG_FUNCPTR (gst_efence_buffer_alloc)); + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); + + filter->srcpad = + gst_pad_new_from_static_template (&gst_efence_src_factory, "src"); + gst_pad_set_getcaps_function (filter->srcpad, + GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); + gst_pad_set_setcaps_function (filter->srcpad, + GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps)); + gst_pad_set_checkgetrange_function (filter->srcpad, + GST_DEBUG_FUNCPTR (gst_efence_checkgetrange)); + gst_pad_set_getrange_function (filter->srcpad, + GST_DEBUG_FUNCPTR (gst_efence_getrange)); + gst_pad_set_activatepull_function (filter->srcpad, + GST_DEBUG_FUNCPTR (gst_efence_activate_src_pull)); + + gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); + + filter->fence_top = TRUE; +} + +/* chain function + * this function does the actual processing + */ + +static GstFlowReturn +gst_efence_chain (GstPad * pad, GstBuffer * buffer) +{ + GstEFence *efence; + GstBuffer *copy; + + efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); + g_return_val_if_fail (GST_IS_EFENCE (efence), GST_FLOW_ERROR); + + if (GST_IS_FENCED_BUFFER (buffer)) { + GST_DEBUG_OBJECT (efence, "Passing on existing fenced buffer with caps %" + GST_PTR_FORMAT, GST_BUFFER_CAPS (buffer)); + return gst_pad_push (efence->srcpad, buffer); + } + + copy = (GstBuffer *) gst_fenced_buffer_copy (buffer); + + GST_DEBUG_OBJECT (efence, "Pushing newly fenced buffer with caps %" + GST_PTR_FORMAT ", data=%p, size=%u", GST_BUFFER_CAPS (copy), + GST_BUFFER_DATA (copy), GST_BUFFER_SIZE (copy)); + + gst_buffer_unref (buffer); + + return gst_pad_push (efence->srcpad, copy); +} + +static GstFlowReturn +gst_efence_getrange (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstEFence *efence; + GstFlowReturn ret; + GstBuffer *ownbuf; + GstPad *peer; + + efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); + + peer = gst_pad_get_peer (efence->sinkpad); + if (!peer) + return GST_FLOW_NOT_LINKED; + + if ((ret = gst_pad_get_range (peer, offset, length, buffer)) != GST_FLOW_OK) + goto beach; + + ownbuf = (GstBuffer *) gst_fenced_buffer_copy (*buffer); + gst_buffer_unref ((GstBuffer *) * buffer); + *buffer = ownbuf; + +beach: + gst_object_unref (peer); + return ret; +} + +static gboolean +gst_efence_checkgetrange (GstPad * pad) +{ + GstEFence *efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); + + return gst_pad_check_pull_range (efence->sinkpad); +} + +static gboolean +gst_efence_activate_src_pull (GstPad * pad, gboolean active) +{ + GstEFence *efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); + + return gst_pad_activate_pull (efence->sinkpad, active); +} + +static GstFlowReturn +gst_efence_buffer_alloc (GstPad * pad, guint64 offset, + guint size, GstCaps * caps, GstBuffer ** buf) +{ + GstBuffer *buffer; + GstEFence *efence; + + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + + efence = GST_EFENCE (GST_OBJECT_PARENT (pad)); + + buffer = (GstBuffer *) gst_mini_object_new (GST_TYPE_FENCED_BUFFER); + + GST_BUFFER_DATA (buffer) = gst_fenced_buffer_alloc (buffer, size, + efence->fence_top); + GST_BUFFER_SIZE (buffer) = size; + GST_BUFFER_OFFSET (buffer) = offset; + + if (caps) + gst_buffer_set_caps (buffer, caps); + + *buf = buffer; + + GST_DEBUG_OBJECT (efence, "Allocated buffer of size %u, caps: %" + GST_PTR_FORMAT, GST_BUFFER_SIZE (buffer), GST_BUFFER_CAPS (buffer)); + + return GST_FLOW_OK; +} + +static void +gst_efence_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstEFence *filter; + + g_return_if_fail (GST_IS_EFENCE (object)); + filter = GST_EFENCE (object); + + switch (prop_id) { + case ARG_FENCE_TOP: + filter->fence_top = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_efence_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstEFence *filter; + + g_return_if_fail (GST_IS_EFENCE (object)); + filter = GST_EFENCE (object); + + switch (prop_id) { + case ARG_FENCE_TOP: + g_value_set_boolean (value, filter->fence_top); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* entry point to initialize the plug-in + * initialize the plug-in itself + * register the element factories and pad templates + * register the features + */ +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "efence", GST_RANK_NONE, GST_TYPE_EFENCE)) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (gst_efence_debug, "efence", 0, + "Debug output from the efence element"); + + /* plugin initialisation succeeded */ + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "efence", + "This element converts a stream of normal GStreamer buffers into a " + "stream of buffers that are allocated in such a way that out-of-bounds " + "access to data in the buffer is more likely to cause segmentation " + "faults. This allocation method is very similar to the debugging tool " + "\"Electric Fence\".", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); + + +static GstBufferClass *fenced_buffer_parent_class = NULL; + +static void +gst_fenced_buffer_finalize (GstFencedBuffer * buffer) +{ + GstFencedBuffer *fenced_buffer; + + GST_DEBUG ("free buffer=%p", buffer); + + fenced_buffer = GST_FENCED_BUFFER (buffer); + + /* free our data */ + if (GST_BUFFER_DATA (buffer)) { + GST_DEBUG ("free region %p %d", fenced_buffer->region, + fenced_buffer->length); + munmap (fenced_buffer->region, fenced_buffer->length); + } + + GST_MINI_OBJECT_CLASS (fenced_buffer_parent_class)->finalize (GST_MINI_OBJECT + (buffer)); +} + +static GstFencedBuffer * +gst_fenced_buffer_copy (const GstBuffer * buffer) +{ + GstBuffer *copy; + void *ptr; + guint mask; + + g_return_val_if_fail (buffer != NULL, NULL); + + /* create a fresh new buffer */ + copy = (GstBuffer *) gst_mini_object_new (GST_TYPE_FENCED_BUFFER); + + /* we simply copy everything from our parent */ + ptr = gst_fenced_buffer_alloc (GST_BUFFER (copy), + GST_BUFFER_SIZE (buffer), TRUE); + memcpy (ptr, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); + + /* copy relevant flags */ + mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS | + GST_BUFFER_FLAG_DELTA_UNIT; + GST_MINI_OBJECT (copy)->flags |= GST_MINI_OBJECT (buffer)->flags & mask; + + GST_BUFFER_DATA (copy) = ptr; + GST_BUFFER_SIZE (copy) = GST_BUFFER_SIZE (buffer); + GST_BUFFER_TIMESTAMP (copy) = GST_BUFFER_TIMESTAMP (buffer); + GST_BUFFER_DURATION (copy) = GST_BUFFER_DURATION (buffer); + GST_BUFFER_OFFSET (copy) = GST_BUFFER_OFFSET (buffer); + GST_BUFFER_OFFSET_END (copy) = GST_BUFFER_OFFSET_END (buffer); + + if (GST_BUFFER_CAPS (buffer)) + GST_BUFFER_CAPS (copy) = gst_caps_ref (GST_BUFFER_CAPS (buffer)); + else + GST_BUFFER_CAPS (copy) = NULL; + + GST_DEBUG ("Copied buffer %p with ts %" GST_TIME_FORMAT + ", caps: %" GST_PTR_FORMAT, buffer, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (copy)), GST_BUFFER_CAPS (copy)); + + return GST_FENCED_BUFFER (copy); +} + +void * +gst_fenced_buffer_alloc (GstBuffer * buffer, unsigned int length, + gboolean fence_top) +{ + int alloc_size; + void *region; + GstFencedBuffer *fenced_buffer = (GstFencedBuffer *) buffer; + int page_size; + + GST_DEBUG ("buffer=%p length=%d fence_top=%d", buffer, length, fence_top); + + if (length == 0) + return NULL; + +#ifdef _SC_PAGESIZE + page_size = sysconf (_SC_PAGESIZE); +#else + page_size = getpagesize (); +#endif + + /* Allocate a complete page, and one on either side */ + alloc_size = ((length - 1) & ~(page_size - 1)) + page_size; + alloc_size += 2 * page_size; + + region = mmap (NULL, alloc_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (region == MAP_FAILED) { + g_warning ("mmap failed"); + return NULL; + } +#if 0 + munmap (region, page_size); + munmap (region + alloc_size - page_size, page_size); + + fenced_buffer->region = region + page_size; + fenced_buffer->length = alloc_size - page_size; +#else + mprotect (region, page_size, PROT_NONE); + mprotect ((char *) region + alloc_size - page_size, page_size, PROT_NONE); + + fenced_buffer->region = region; + fenced_buffer->length = alloc_size; +#endif + + GST_DEBUG ("new region %p %d", fenced_buffer->region, fenced_buffer->length); + + if (fence_top) { + int offset; + + /* Align to top of region, but force alignment to 4 bytes */ + offset = alloc_size - page_size - length; + offset &= ~0x3; + return (void *) ((char *) region + offset); + } else { + return (void *) ((char *) region + page_size); + } +} + +static void +gst_fenced_buffer_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + fenced_buffer_parent_class = g_type_class_peek_parent (g_class); + + mini_object_class->finalize = + (GstMiniObjectFinalizeFunction) gst_fenced_buffer_finalize; + mini_object_class->copy = (GstMiniObjectCopyFunction) gst_fenced_buffer_copy; +} + +GType +gst_fenced_buffer_get_type (void) +{ + static GType fenced_buf_type = 0; + + if (G_UNLIKELY (!fenced_buf_type)) { + static const GTypeInfo fenced_buf_info = { + sizeof (GstBufferClass), + NULL, + NULL, + (GClassInitFunc) gst_fenced_buffer_class_init, + NULL, + NULL, + sizeof (GstFencedBuffer), + 0, + NULL, + }; + + fenced_buf_type = g_type_register_static (GST_TYPE_BUFFER, + "GstFencedBuffer", &fenced_buf_info, 0); + } + return fenced_buf_type; +} diff --git a/gst/debugutils/efence.h b/gst/debugutils/efence.h new file mode 100644 index 00000000..7c4acb5d --- /dev/null +++ b/gst/debugutils/efence.h @@ -0,0 +1,50 @@ +/* + * efence.h + */ + +#ifndef __GST_EFENCE_H__ +#define __GST_EFENCE_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* #define's don't like whitespacey bits */ +#define GST_TYPE_EFENCE \ + (gst_gst_efence_get_type()) +#define GST_EFENCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EFENCE,GstEFence)) +#define GST_EFENCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EFENCE,GstEFenceClass)) +#define GST_IS_EFENCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EFENCE)) +#define GST_IS_EFENCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EFENCE)) + + typedef struct _GstEFence GstEFence; + typedef struct _GstEFenceClass GstEFenceClass; + + struct _GstEFence + { + GstElement element; + + GstPad *sinkpad, *srcpad; + + gboolean fence_top; + }; + + struct _GstEFenceClass + { + GstElementClass parent_class; + }; + + GType gst_gst_efence_get_type (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_EFENCE_H__ */ diff --git a/gst/debugutils/efence.vcproj b/gst/debugutils/efence.vcproj new file mode 100644 index 00000000..c01fcd28 --- /dev/null +++ b/gst/debugutils/efence.vcproj @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst/debugutils/gstdebug.c b/gst/debugutils/gstdebug.c new file mode 100644 index 00000000..53f24d50 --- /dev/null +++ b/gst/debugutils/gstdebug.c @@ -0,0 +1,63 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +GType gst_break_my_data_get_type (void); +GType gst_rnd_buffer_size_get_type (void); +GType gst_navseek_get_type (void); +GType gst_progress_report_get_type (void); +GType gst_tag_inject_get_type (void); +GType gst_test_get_type (void); +/* +GType gst_push_file_src_get_type (void); +GType gst_gst_negotiation_get_type (void); +*/ + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "breakmydata", GST_RANK_NONE, + gst_break_my_data_get_type ()) + || !gst_element_register (plugin, "rndbuffersize", GST_RANK_NONE, + gst_rnd_buffer_size_get_type ()) + || !gst_element_register (plugin, "navseek", GST_RANK_NONE, + gst_navseek_get_type ()) || +/* !gst_element_register (plugin, "pushfilesrc", GST_RANK_NONE, gst_push_file_src_get_type ()) || */ +/* !gst_element_register (plugin, "negotiation", GST_RANK_NONE, gst_gst_negotiation_get_type ()) || */ + !gst_element_register (plugin, "progressreport", GST_RANK_NONE, + gst_progress_report_get_type ()) + || !gst_element_register (plugin, "taginject", GST_RANK_NONE, + gst_tag_inject_get_type ()) + || !gst_element_register (plugin, "testsink", GST_RANK_NONE, + gst_test_get_type ())) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "debug", + "elements for testing and debugging", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/debugutils/gstnavigationtest.c b/gst/debugutils/gstnavigationtest.c new file mode 100644 index 00000000..5c339252 --- /dev/null +++ b/gst/debugutils/gstnavigationtest.c @@ -0,0 +1,357 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstnavigationtest.h" +#include +#include + +#include + +#ifdef _MSC_VER +#define rint(x) (floor((x)+0.5)) +#endif + +GST_DEBUG_CATEGORY_STATIC (navigationtest_debug); +#define GST_CAT_DEFAULT navigationtest_debug + +static const GstElementDetails navigationtest_details = +GST_ELEMENT_DETAILS ("Video navigation test", + "Filter/Effect/Video", + "Handle navigation events showing a black square following mouse pointer", + "David Schleef "); + +static GstStaticPadTemplate gst_navigationtest_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) + ); + +static GstStaticPadTemplate gst_navigationtest_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) + ); + +static GstVideoFilterClass *parent_class = NULL; + +static gboolean +gst_navigationtest_handle_src_event (GstPad * pad, GstEvent * event) +{ + GstNavigationtest *navtest; + const gchar *type; + + navtest = GST_NAVIGATIONTEST (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NAVIGATION: + { + const GstStructure *s = gst_event_get_structure (event); + gint fps_n, fps_d; + + fps_n = gst_value_get_fraction_numerator ((&navtest->framerate)); + fps_d = gst_value_get_fraction_denominator ((&navtest->framerate)); + + type = gst_structure_get_string (s, "event"); + if (g_str_equal (type, "mouse-move")) { + gst_structure_get_double (s, "pointer_x", &navtest->x); + gst_structure_get_double (s, "pointer_y", &navtest->y); + } else if (g_str_equal (type, "mouse-button-press")) { + ButtonClick *click = g_new (ButtonClick, 1); + + gst_structure_get_double (s, "pointer_x", &click->x); + gst_structure_get_double (s, "pointer_y", &click->y); + click->images_left = (fps_n + fps_d - 1) / fps_d; + /* green */ + click->cy = 150; + click->cu = 46; + click->cv = 21; + navtest->clicks = g_slist_prepend (navtest->clicks, click); + } else if (g_str_equal (type, "mouse-button-release")) { + ButtonClick *click = g_new (ButtonClick, 1); + + gst_structure_get_double (s, "pointer_x", &click->x); + gst_structure_get_double (s, "pointer_y", &click->y); + click->images_left = (fps_n + fps_d - 1) / fps_d; + /* red */ + click->cy = 76; + click->cu = 85; + click->cv = 255; + navtest->clicks = g_slist_prepend (navtest->clicks, click); + } + break; + } + default: + break; + } + return gst_pad_event_default (pad, event); +} + +/* Useful macros */ +#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) +#define GST_VIDEO_I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2) +#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2) + +#define GST_VIDEO_I420_Y_OFFSET(w,h) (0) +#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h))) +#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) + +#define GST_VIDEO_I420_SIZE(w,h) (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) + +static gboolean +gst_navigationtest_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, + guint * size) +{ + GstNavigationtest *navtest; + GstStructure *structure; + gboolean ret = FALSE; + gint width, height; + + navtest = GST_NAVIGATIONTEST (btrans); + + structure = gst_caps_get_structure (caps, 0); + + if (gst_structure_get_int (structure, "width", &width) && + gst_structure_get_int (structure, "height", &height)) { + *size = GST_VIDEO_I420_SIZE (width, height); + ret = TRUE; + GST_DEBUG_OBJECT (navtest, "our frame size is %d bytes (%dx%d)", *size, + width, height); + } + + return ret; +} + +static gboolean +gst_navigationtest_set_caps (GstBaseTransform * btrans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstNavigationtest *navtest = GST_NAVIGATIONTEST (btrans); + gboolean ret = FALSE; + GstStructure *structure; + + structure = gst_caps_get_structure (incaps, 0); + + if (gst_structure_get_int (structure, "width", &navtest->width) && + gst_structure_get_int (structure, "height", &navtest->height)) { + const GValue *framerate; + + framerate = gst_structure_get_value (structure, "framerate"); + if (framerate && GST_VALUE_HOLDS_FRACTION (framerate)) { + g_value_copy (framerate, &navtest->framerate); + ret = TRUE; + } + } + + return ret; +} + +static void +draw_box_planar411 (guint8 * dest, int width, int height, int x, int y, + guint8 colory, guint8 coloru, guint8 colorv) +{ + int x1, x2, y1, y2; + guint8 *d = dest; + + if (x < 0 || y < 0 || x >= width || y >= height) + return; + + x1 = MAX (x - 5, 0); + x2 = MIN (x + 5, width); + y1 = MAX (y - 5, 0); + y2 = MIN (y + 5, height); + + for (y = y1; y < y2; y++) { + for (x = x1; x < x2; x++) { + ((guint8 *) d)[y * GST_VIDEO_I420_Y_ROWSTRIDE (width) + x] = colory; + } + } + + d = dest + GST_VIDEO_I420_U_OFFSET (width, height); + x1 /= 2; + x2 /= 2; + y1 /= 2; + y2 /= 2; + for (y = y1; y < y2; y++) { + for (x = x1; x < x2; x++) { + ((guint8 *) d)[y * GST_VIDEO_I420_U_ROWSTRIDE (width) + x] = coloru; + } + } + + d = dest + GST_VIDEO_I420_V_OFFSET (width, height); + for (y = y1; y < y2; y++) { + for (x = x1; x < x2; x++) { + ((guint8 *) d)[y * GST_VIDEO_I420_V_ROWSTRIDE (width) + x] = colorv; + } + } +} + +static GstFlowReturn +gst_navigationtest_transform (GstBaseTransform * trans, GstBuffer * in, + GstBuffer * out) +{ + GstNavigationtest *navtest = GST_NAVIGATIONTEST (trans); + GSList *walk; + GstFlowReturn ret = GST_FLOW_OK; + + /* do something interesting here. This simply copies the source + * to the destination. */ + gst_buffer_copy_metadata (out, in, GST_BUFFER_COPY_TIMESTAMPS); + + memcpy (GST_BUFFER_DATA (out), GST_BUFFER_DATA (in), + MIN (GST_BUFFER_SIZE (in), GST_BUFFER_SIZE (out))); + + walk = navtest->clicks; + while (walk) { + ButtonClick *click = walk->data; + + walk = g_slist_next (walk); + draw_box_planar411 (GST_BUFFER_DATA (out), navtest->width, navtest->height, + rint (click->x), rint (click->y), click->cy, click->cu, click->cv); + if (--click->images_left < 1) { + navtest->clicks = g_slist_remove (navtest->clicks, click); + g_free (click); + } + } + draw_box_planar411 (GST_BUFFER_DATA (out), navtest->width, navtest->height, + rint (navtest->x), rint (navtest->y), 0, 128, 128); + + return ret; +} + +static GstStateChangeReturn +gst_navigationtest_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstNavigationtest *navtest = GST_NAVIGATIONTEST (element); + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + /* downwards state changes */ + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + { + g_slist_foreach (navtest->clicks, (GFunc) g_free, NULL); + g_slist_free (navtest->clicks); + navtest->clicks = NULL; + break; + } + default: + break; + } + + return ret; +} + +static void +gst_navigationtest_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details (element_class, &navigationtest_details); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_navigationtest_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_navigationtest_src_template)); +} + +static void +gst_navigationtest_class_init (gpointer klass, gpointer class_data) +{ + GObjectClass *gobject_class; + GstElementClass *element_class; + GstBaseTransformClass *trans_class; + + gobject_class = (GObjectClass *) klass; + element_class = (GstElementClass *) klass; + trans_class = (GstBaseTransformClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_navigationtest_change_state); + + trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_navigationtest_set_caps); + trans_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_navigationtest_get_unit_size); + trans_class->transform = GST_DEBUG_FUNCPTR (gst_navigationtest_transform); +} + +static void +gst_navigationtest_init (GTypeInstance * instance, gpointer g_class) +{ + GstNavigationtest *navtest = GST_NAVIGATIONTEST (instance); + GstBaseTransform *btrans = GST_BASE_TRANSFORM (instance); + + gst_pad_set_event_function (btrans->srcpad, + GST_DEBUG_FUNCPTR (gst_navigationtest_handle_src_event)); + + navtest->x = -1; + navtest->y = -1; + g_value_init (&navtest->framerate, GST_TYPE_FRACTION); +} + +GType +gst_navigationtest_get_type (void) +{ + static GType navigationtest_type = 0; + + if (!navigationtest_type) { + static const GTypeInfo navigationtest_info = { + sizeof (GstNavigationtestClass), + gst_navigationtest_base_init, + NULL, + gst_navigationtest_class_init, + NULL, + NULL, + sizeof (GstNavigationtest), + 0, + gst_navigationtest_init, + }; + + navigationtest_type = g_type_register_static (GST_TYPE_VIDEO_FILTER, + "GstNavigationtest", &navigationtest_info, 0); + } + return navigationtest_type; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (navigationtest_debug, "navigationtest", 0, + "navigationtest"); + + return gst_element_register (plugin, "navigationtest", GST_RANK_NONE, + GST_TYPE_NAVIGATIONTEST); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "navigationtest", + "Template for a video filter", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/debugutils/gstnavigationtest.h b/gst/debugutils/gstnavigationtest.h new file mode 100644 index 00000000..efdbb228 --- /dev/null +++ b/gst/debugutils/gstnavigationtest.h @@ -0,0 +1,68 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_NAVIGATIONTEST_H__ +#define __GST_NAVIGATIONTEST_H__ + +#include + +G_BEGIN_DECLS +#define GST_TYPE_NAVIGATIONTEST \ + (gst_navigationtest_get_type()) +#define GST_NAVIGATIONTEST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NAVIGATIONTEST,GstNavigationtest)) +#define GST_NAVIGATIONTEST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NAVIGATIONTEST,GstNavigationtestClass)) +#define GST_IS_NAVIGATIONTEST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NAVIGATIONTEST)) +#define GST_IS_NAVIGATIONTEST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NAVIGATIONTEST)) +typedef struct _GstNavigationtest GstNavigationtest; +typedef struct _GstNavigationtestClass GstNavigationtestClass; + +typedef struct +{ + gdouble x; + gdouble y; + gint images_left; + guint8 cy, cu, cv; +} ButtonClick; + +struct _GstNavigationtest +{ + GstVideoFilter videofilter; + + gint width, height; + + GValue framerate; + gdouble x, y; + + GSList *clicks; +}; + +struct _GstNavigationtestClass +{ + GstVideoFilterClass parent_class; +}; + +GType gst_navigationtest_get_type (void); + +G_END_DECLS +#endif /* __GST_NAVIGATIONTEST_H__ */ diff --git a/gst/debugutils/gstnavseek.c b/gst/debugutils/gstnavseek.c new file mode 100644 index 00000000..c47bf42f --- /dev/null +++ b/gst/debugutils/gstnavseek.c @@ -0,0 +1,340 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This file was (probably) generated from gstnavseek.c, + * gstnavseek.c,v 1.7 2003/11/08 02:48:59 dschleef Exp + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstnavseek.h" +#include +#include + +enum +{ + ARG_0, + ARG_SEEKOFFSET +}; + +GstStaticPadTemplate navseek_src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GstStaticPadTemplate navseek_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static const GstElementDetails navseek_details = +GST_ELEMENT_DETAILS ("Seek based on left-right arrows", + "Filter/Video", + "Seek based on navigation keys left-right", + "Jan Schmidt "); + +static gboolean gst_navseek_event (GstBaseTransform * trans, GstEvent * event); +static GstFlowReturn gst_navseek_transform_ip (GstBaseTransform * basetrans, + GstBuffer * buf); +static gboolean gst_navseek_handle_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_navseek_stop (GstBaseTransform * trans); +static gboolean gst_navseek_start (GstBaseTransform * trans); + +static void gst_navseek_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_navseek_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GST_BOILERPLATE (GstNavSeek, gst_navseek, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); + +static void +gst_navseek_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&navseek_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&navseek_src_template)); + + gst_element_class_set_details (element_class, &navseek_details); +} + +static void +gst_navseek_class_init (GstNavSeekClass * klass) +{ + GstBaseTransformClass *gstbasetrans_class; + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->set_property = gst_navseek_set_property; + gobject_class->get_property = gst_navseek_get_property; + + g_object_class_install_property (gobject_class, + ARG_SEEKOFFSET, g_param_spec_double ("seek-offset", "Seek Offset", + "Time in seconds to seek by", 0.0, G_MAXDOUBLE, 5.0, + G_PARAM_READWRITE)); + + gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_navseek_event); + gstbasetrans_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_navseek_transform_ip); + gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_navseek_start); + gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_navseek_stop); +} + +static void +gst_navseek_init (GstNavSeek * navseek, GstNavSeekClass * g_class) +{ + gst_pad_set_event_function (GST_BASE_TRANSFORM (navseek)->srcpad, + GST_DEBUG_FUNCPTR (gst_navseek_handle_src_event)); + + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (navseek), TRUE); + + navseek->seek_offset = 5.0; + navseek->loop = FALSE; + navseek->grab_seg_start = FALSE; + navseek->grab_seg_end = FALSE; + navseek->segment_start = GST_CLOCK_TIME_NONE; + navseek->segment_end = GST_CLOCK_TIME_NONE; +} + +static void +gst_navseek_seek (GstNavSeek * navseek, gint64 offset) +{ + GstFormat peer_format = GST_FORMAT_TIME; + gboolean ret; + GstPad *peer_pad; + gint64 peer_value; + + /* Query for the current time then attempt to set to time + offset */ + peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); + ret = gst_pad_query_position (peer_pad, &peer_format, &peer_value); + + if (ret && peer_format == GST_FORMAT_TIME) { + GstEvent *event; + + peer_value += offset; + if (peer_value < 0) + peer_value = 0; + + event = gst_event_new_seek (1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, peer_value, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + + gst_pad_send_event (peer_pad, event); + } + + gst_object_unref (peer_pad); +} + +static void +gst_navseek_segseek (GstNavSeek * navseek) +{ + GstEvent *event; + GstPad *peer_pad; + + if ((navseek->segment_start == GST_CLOCK_TIME_NONE) || + (navseek->segment_end == GST_CLOCK_TIME_NONE) || + (!GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad))) { + return; + } + + if (navseek->loop) { + event = + gst_event_new_seek (1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT, + GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET, + navseek->segment_end); + } else { + event = + gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE, + GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET, + navseek->segment_end); + } + + peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); + gst_pad_send_event (peer_pad, event); + gst_object_unref (peer_pad); +} + +static gboolean +gst_navseek_handle_src_event (GstPad * pad, GstEvent * event) +{ + GstNavSeek *navseek; + gboolean ret = TRUE; + + navseek = GST_NAVSEEK (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NAVIGATION: + /* Check for a keyup and convert left/right to a seek event */ + { + const GstStructure *structure; + const gchar *event_type; + + structure = gst_event_get_structure (event); + g_return_val_if_fail (structure != NULL, FALSE); + + event_type = gst_structure_get_string (structure, "event"); + g_return_val_if_fail (event_type != NULL, FALSE); + + if (strcmp (event_type, "key-press") == 0) { + const gchar *key; + + key = gst_structure_get_string (structure, "key"); + g_return_val_if_fail (key != NULL, FALSE); + + if (strcmp (key, "Left") == 0) { + /* Seek backward by 5 secs */ + gst_navseek_seek (navseek, -1.0 * navseek->seek_offset * GST_SECOND); + } else if (strcmp (key, "Right") == 0) { + /* Seek forward */ + gst_navseek_seek (navseek, navseek->seek_offset * GST_SECOND); + } else if (strcmp (key, "s") == 0) { + /* Grab the next frame as the start frame of a segment */ + navseek->grab_seg_start = TRUE; + } else if (strcmp (key, "e") == 0) { + /* Grab the next frame as the end frame of a segment */ + navseek->grab_seg_end = TRUE; + } else if (strcmp (key, "l") == 0) { + /* Toggle the loop flag. If we have both start and end segment times send a seek */ + navseek->loop = !navseek->loop; + gst_navseek_segseek (navseek); + } + } else { + break; + } + gst_event_unref (event); + event = NULL; + } + break; + default: + break; + } + + if (event && GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad)) { + GstPad *peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); + + ret = gst_pad_send_event (peer_pad, event); + gst_object_unref (peer_pad); + } + + return ret; +} + +static void +gst_navseek_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstNavSeek *navseek = GST_NAVSEEK (object); + + switch (prop_id) { + case ARG_SEEKOFFSET: + GST_OBJECT_LOCK (navseek); + navseek->seek_offset = g_value_get_double (value); + GST_OBJECT_UNLOCK (navseek); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_navseek_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstNavSeek *navseek = GST_NAVSEEK (object); + + switch (prop_id) { + case ARG_SEEKOFFSET: + GST_OBJECT_LOCK (navseek); + g_value_set_double (value, navseek->seek_offset); + GST_OBJECT_UNLOCK (navseek); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_navseek_event (GstBaseTransform * trans, GstEvent * event) +{ + GstNavSeek *navseek = GST_NAVSEEK (trans); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + GST_OBJECT_LOCK (navseek); + if (navseek->loop) + gst_navseek_segseek (navseek); + GST_OBJECT_UNLOCK (navseek); + break; + default: + break; + } + return GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event); +} + +static GstFlowReturn +gst_navseek_transform_ip (GstBaseTransform * basetrans, GstBuffer * buf) +{ + GstNavSeek *navseek = GST_NAVSEEK (basetrans); + + GST_OBJECT_LOCK (navseek); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + if (navseek->grab_seg_start) { + navseek->segment_start = GST_BUFFER_TIMESTAMP (buf); + navseek->segment_end = GST_CLOCK_TIME_NONE; + navseek->grab_seg_start = FALSE; + } + + if (navseek->grab_seg_end) { + navseek->segment_end = GST_BUFFER_TIMESTAMP (buf); + navseek->grab_seg_end = FALSE; + gst_navseek_segseek (navseek); + } + } + + GST_OBJECT_UNLOCK (navseek); + + return GST_FLOW_OK; +} + +static gboolean +gst_navseek_start (GstBaseTransform * trans) +{ + /* anything we should be doing here? */ + return TRUE; +} + +static gboolean +gst_navseek_stop (GstBaseTransform * trans) +{ + /* anything we should be doing here? */ + return TRUE; +} diff --git a/gst/debugutils/gstnavseek.h b/gst/debugutils/gstnavseek.h new file mode 100644 index 00000000..af7e9d21 --- /dev/null +++ b/gst/debugutils/gstnavseek.h @@ -0,0 +1,60 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_NAVSEEK_H__ +#define __GST_NAVSEEK_H__ + + +#include +#include + +G_BEGIN_DECLS +#define GST_TYPE_NAVSEEK \ + (gst_navseek_get_type()) +#define GST_NAVSEEK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NAVSEEK,GstNavSeek)) +#define GST_NAVSEEK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NAVSEEK,GstNavSeekClass)) +#define GST_IS_NAVSEEK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NAVSEEK)) +#define GST_IS_NAVSEEK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NAVSEEK)) +typedef struct _GstNavSeek GstNavSeek; +typedef struct _GstNavSeekClass GstNavSeekClass; + +struct _GstNavSeek +{ + GstBaseTransform basetransform; + + gdouble seek_offset; + gboolean loop; + gboolean grab_seg_start; + gboolean grab_seg_end; + GstClockTime segment_start; + GstClockTime segment_end; +}; + +struct _GstNavSeekClass +{ + GstBaseTransformClass parent_class; +}; + +G_END_DECLS +#endif /* __GST_NAVSEEK_H__ */ diff --git a/gst/debugutils/gstpushfilesrc.c b/gst/debugutils/gstpushfilesrc.c new file mode 100644 index 00000000..47daa83e --- /dev/null +++ b/gst/debugutils/gstpushfilesrc.c @@ -0,0 +1,195 @@ +/* GStreamer Push File Source + * Copyright (C) <2007> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-pushfilesrc + * @see_also: filesrc + * + * This element is only useful for debugging purposes. It implements an URI + * protocol handler for the 'pushfile' protocol and behaves like a file source + * element that cannot be activated in pull-mode. This makes it very easy to + * debug demuxers or decoders that can operate both pull and push-based in + * connection with the playbin element (which creates a source based on the + * URI passed). + * + * + * Example launch line + * |[ + * gst-launch -m playbin uri=pushfile:///home/you/some/file.ogg + * ]| This plays back the given file using playbin, with the demuxer operating + * push-based. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstpushfilesrc.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (pushfilesrc_debug); +#define GST_CAT_DEFAULT pushfilesrc_debug + +static const GstElementDetails pushfilesrc_details = +GST_ELEMENT_DETAILS ("Push File Source", + "Testing", + "Implements pushfile:// URI-handler for push-based file access", + "Tim-Philipp Müller "); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static void gst_push_file_src_uri_handler_init (gpointer g_iface, + gpointer iface_data); +static void gst_file_push_src_add_uri_handler (GType type); + +GST_BOILERPLATE_FULL (GstPushFileSrc, gst_push_file_src, GstBin, GST_TYPE_BIN, + gst_file_push_src_add_uri_handler); + +static void +gst_file_push_src_add_uri_handler (GType type) +{ + static const GInterfaceInfo info = { + gst_push_file_src_uri_handler_init, + NULL, + NULL + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &info); + GST_DEBUG_CATEGORY_INIT (pushfilesrc_debug, "pushfilesrc", 0, + "pushfilesrc element"); +} + +static void +gst_push_file_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&srctemplate)); + + gst_element_class_set_details (element_class, &pushfilesrc_details); +} + +static void +gst_push_file_src_dispose (GObject * obj) +{ + GstPushFileSrc *src = GST_PUSH_FILE_SRC (obj); + + if (src->srcpad) { + gst_element_remove_pad (GST_ELEMENT (src), src->srcpad); + src->srcpad = NULL; + } + if (src->filesrc) { + gst_bin_remove (GST_BIN (src), src->filesrc); + src->filesrc = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + +static void +gst_push_file_src_class_init (GstPushFileSrcClass * g_class) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (g_class); + + gobject_class->dispose = gst_push_file_src_dispose; +} + +static gboolean +gst_push_file_src_ghostpad_checkgetrange (GstPad * pad) +{ + return FALSE; +} + +static void +gst_push_file_src_init (GstPushFileSrc * src, GstPushFileSrcClass * g_class) +{ + src->filesrc = gst_element_factory_make ("filesrc", "real-filesrc"); + if (src->filesrc) { + GstPad *pad; + + gst_bin_add (GST_BIN (src), src->filesrc); + pad = gst_element_get_static_pad (src->filesrc, "src"); + g_assert (pad != NULL); + src->srcpad = gst_ghost_pad_new ("src", pad); + /* FIXME^H^HCORE: try pushfile:///foo/bar.ext ! typefind ! fakesink without + * this and watch core bugginess (some pad stays in flushing state) */ + gst_pad_set_checkgetrange_function (src->srcpad, + GST_DEBUG_FUNCPTR (gst_push_file_src_ghostpad_checkgetrange)); + gst_element_add_pad (GST_ELEMENT (src), src->srcpad); + gst_object_unref (pad); + } +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_push_file_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_push_file_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { "pushfile", NULL }; + + return protocols; +} + +static const gchar * +gst_push_file_src_uri_get_uri (GstURIHandler * handler) +{ + GstPushFileSrc *src = GST_PUSH_FILE_SRC (handler); + + if (src->filesrc == NULL) + return NULL; + + return gst_uri_handler_get_uri (GST_URI_HANDLER (src->filesrc)); +} + +static gboolean +gst_push_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + GstPushFileSrc *src = GST_PUSH_FILE_SRC (handler); + + if (src->filesrc == NULL || !g_str_has_prefix (uri, "pushfile://")) + return FALSE; + + /* skip 'push' bit */ + return gst_uri_handler_set_uri (GST_URI_HANDLER (src->filesrc), uri + 4); +} + +static void +gst_push_file_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_push_file_src_uri_get_type; + iface->get_protocols = gst_push_file_src_uri_get_protocols; + iface->get_uri = gst_push_file_src_uri_get_uri; + iface->set_uri = gst_push_file_src_uri_set_uri; +} diff --git a/gst/debugutils/gstpushfilesrc.h b/gst/debugutils/gstpushfilesrc.h new file mode 100644 index 00000000..d9333444 --- /dev/null +++ b/gst/debugutils/gstpushfilesrc.h @@ -0,0 +1,56 @@ +/* GStreamer Push File Source + * Copyright (C) <2007> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_PUSH_FILE_SRC_H__ +#define __GST_PUSH_FILE_SRC_H__ + +#include + +G_BEGIN_DECLS +#define GST_TYPE_PUSH_FILE_SRC \ + (gst_push_file_src_get_type()) +#define GST_PUSH_FILE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PUSH_FILE_SRC,GstPushFileSrc)) +#define GST_PUSH_FILE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PUSH_FILE_SRC,GstPushFileSrcClass)) +#define GST_IS_PUSH_FILE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PUSH_FILE_SRC)) +#define GST_IS_PUSH_FILE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PUSH_FILE_SRC)) +typedef struct _GstPushFileSrc GstPushFileSrc; +typedef struct _GstPushFileSrcClass GstPushFileSrcClass; + +struct _GstPushFileSrc +{ + GstBin parent; + + /*< private > */ + GstElement *filesrc; + GstPad *srcpad; +}; + +struct _GstPushFileSrcClass +{ + GstBinClass parent_class; +}; + +GType gst_push_file_src_get_type (void); + +G_END_DECLS +#endif /* __GST_PUSH_FILE_SRC_H__ */ diff --git a/gst/debugutils/gsttaginject.c b/gst/debugutils/gsttaginject.c new file mode 100644 index 00000000..3429fb14 --- /dev/null +++ b/gst/debugutils/gsttaginject.c @@ -0,0 +1,204 @@ +/* GStreamer + * Copyright (C) 2008 Stefan Kost + * + * gsttaginject.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-taginject + * + * Element that injects new metadata tags, but passes incomming data through + * unmodified. + * + * + * Example launch lines + * |[ + * gst-launch audiotestsrc num-buffers=100 ! taginject tags="title=testsrc,artist=gstreamer" ! vorbisenc ! oggmux ! filesink location=test.ogg + * ]| set title and artist + * |[ + * gst-launch audiotestsrc num-buffers=100 ! taginject tags="keywords=\"testone,audio\",title=\"audio testtone\"" ! vorbisenc ! oggmux ! filesink location=test.ogg + * ]| set keywords and title demonstrating quoting of special chars + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "gsttaginject.h" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_tag_inject_debug); +#define GST_CAT_DEFAULT gst_tag_inject_debug + +enum +{ + PROP_TAGS = 1 +}; + + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_tag_inject_debug, "taginject", 0, "tag inject element"); + +GST_BOILERPLATE_FULL (GstTagInject, gst_tag_inject, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); + +static void gst_tag_inject_finalize (GObject * object); +static void gst_tag_inject_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tag_inject_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_tag_inject_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); +static gboolean gst_tag_inject_start (GstBaseTransform * trans); + + +static void +gst_tag_inject_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (gstelement_class, + "TagInject", + "Generic", "inject metadata tags", "Stefan Kost "); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); +} + +static void +gst_tag_inject_finalize (GObject * object) +{ + GstTagInject *self = GST_TAG_INJECT (object); + + if (self->tags) { + gst_tag_list_free (self->tags); + self->tags = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_tag_inject_class_init (GstTagInjectClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseTransformClass *gstbasetrans_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_tag_inject_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_tag_inject_get_property); + + g_object_class_install_property (gobject_class, PROP_TAGS, + g_param_spec_string ("tags", "taglist", + "List of tags to inject into the target file", + NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_tag_inject_finalize); + + gstbasetrans_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_tag_inject_transform_ip); + + gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_tag_inject_start); +} + +static void +gst_tag_inject_init (GstTagInject * self, GstTagInjectClass * g_class) +{ + self->tags = NULL; +} + +static GstFlowReturn +gst_tag_inject_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstTagInject *self = GST_TAG_INJECT (trans); + + if (G_UNLIKELY (!self->tags_sent)) { + self->tags_sent = TRUE; + /* send tags */ + if (self->tags && !gst_tag_list_is_empty (self->tags)) { + GST_DEBUG ("tag event :%" GST_PTR_FORMAT, self->tags); + gst_element_found_tags (GST_ELEMENT (trans), + gst_tag_list_copy (self->tags)); + } + } + + return GST_FLOW_OK; +} + +static void +gst_tag_inject_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTagInject *self = GST_TAG_INJECT (object); + + switch (prop_id) { + case PROP_TAGS:{ + gchar *structure = + g_strdup_printf ("taglist,%s", g_value_get_string (value)); + if (!(self->tags = gst_structure_from_string (structure, NULL))) { + GST_WARNING ("unparsable taglist = '%s'", structure); + } + g_free (structure); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_tag_inject_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + /*GstTagInject *self = GST_TAG_INJECT (object); */ + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_tag_inject_start (GstBaseTransform * trans) +{ + GstTagInject *self = GST_TAG_INJECT (trans); + + /* we need to sent tags _transform_ip() once */ + self->tags_sent = FALSE; + + return TRUE; +} diff --git a/gst/debugutils/gsttaginject.h b/gst/debugutils/gsttaginject.h new file mode 100644 index 00000000..8e8de1ee --- /dev/null +++ b/gst/debugutils/gsttaginject.h @@ -0,0 +1,66 @@ +/* GStreamer + * Copyright (C) 2008 Stefan Kost + * + * gsttaginject.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_TAG_INJECT_H__ +#define __GST_TAG_INJECT_H__ + + +#include +#include + +G_BEGIN_DECLS +#define GST_TYPE_TAG_INJECT \ + (gst_tag_inject_get_type()) +#define GST_TAG_INJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TAG_INJECT,GstTagInject)) +#define GST_TAG_INJECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TAG_INJECT,GstTagInjectClass)) +#define GST_IS_TAG_INJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TAG_INJECT)) +#define GST_IS_TAG_INJECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TAG_INJECT)) +typedef struct _GstTagInject GstTagInject; +typedef struct _GstTagInjectClass GstTagInjectClass; + +/** + * GstTagInject: + * + * Opaque #GstTagInject data structure + */ +struct _GstTagInject +{ + GstBaseTransform element; + + /*< private > */ + GstTagList *tags; + gboolean tags_sent; +}; + +struct _GstTagInjectClass +{ + GstBaseTransformClass parent_class; +}; + +GType gst_tag_inject_get_type (void); + +G_END_DECLS +#endif /* __GST_TAG_INJECT_H__ */ diff --git a/gst/debugutils/navigationtest.vcproj b/gst/debugutils/navigationtest.vcproj new file mode 100644 index 00000000..0bcc0ff7 --- /dev/null +++ b/gst/debugutils/navigationtest.vcproj @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst/debugutils/negotiation.c b/gst/debugutils/negotiation.c new file mode 100644 index 00000000..12082273 --- /dev/null +++ b/gst/debugutils/negotiation.c @@ -0,0 +1,287 @@ +/* + * GStreamer + * Copyright (C) 1999-2001 Erik Walthinsen + * Copyright (C) 2002 David A. Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#include +#include +#include + + +#define GST_TYPE_NEGOTIATION \ + (gst_gst_negotiation_get_type()) +#define GST_NEGOTIATION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NEGOTIATION,GstNegotiation)) +#define GST_NEGOTIATION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NEGOTIATION,GstNegotiation)) +#define GST_IS_NEGOTIATION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NEGOTIATION)) +#define GST_IS_NEGOTIATION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NEGOTIATION)) + +typedef struct _GstNegotiation GstNegotiation; +typedef struct _GstNegotiationClass GstNegotiationClass; + +struct _GstNegotiation +{ + GstElement element; + + GstPad *sinkpad, *srcpad; + + GstCaps *caps; +}; + +struct _GstNegotiationClass +{ + GstElementClass parent_class; +}; + +GType gst_gst_negotiation_get_type (void); + + +static const GstElementDetails plugin_details = +GST_ELEMENT_DETAILS ("Negotiation", + "Testing", + "This element acts like identity, except that one can control how " + "negotiation works", + "David A. Schleef "); + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_ALLOWED_CAPS +}; + +static GstStaticPadTemplate gst_negotiation_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_negotiation_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static void gst_negotiation_base_init (gpointer g_class); +static void gst_negotiation_class_init (GstNegotiationClass * klass); +static void gst_negotiation_init (GstNegotiation * filter); + +static GstCaps *gst_negotiation_getcaps (GstPad * pad); +static GstPadLinkReturn gst_negotiation_pad_link (GstPad * pad, + const GstCaps * caps); + +static void gst_negotiation_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_negotiation_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void gst_negotiation_update_caps (GstNegotiation * negotiation); +static void gst_negotiation_chain (GstPad * pad, GstData * _data); + +static GstElementClass *parent_class = NULL; + +GType +gst_gst_negotiation_get_type (void) +{ + static GType plugin_type = 0; + + if (!plugin_type) { + static const GTypeInfo plugin_info = { + sizeof (GstNegotiationClass), + gst_negotiation_base_init, + NULL, + (GClassInitFunc) gst_negotiation_class_init, + NULL, + NULL, + sizeof (GstNegotiation), + 0, + (GInstanceInitFunc) gst_negotiation_init, + }; + + plugin_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstNegotiation", &plugin_info, 0); + } + return plugin_type; +} + +static void +gst_negotiation_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_negotiation_sink_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_negotiation_src_factory)); + gst_element_class_set_details (element_class, &plugin_details); +} + +static void +gst_negotiation_class_init (GstNegotiationClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_negotiation_set_property; + gobject_class->get_property = gst_negotiation_get_property; + + g_object_class_install_property (gobject_class, ARG_ALLOWED_CAPS, + g_param_spec_boxed ("allowed-caps", "Caps", + "The range of formats allowed by " "this element's peers", + GST_TYPE_CAPS, G_PARAM_READABLE)); +} + +static void +gst_negotiation_init (GstNegotiation * filter) +{ + filter->sinkpad = + gst_pad_new_from_static_template (&gst_negotiation_sink_factory, "sink"); + gst_pad_set_getcaps_function (filter->sinkpad, gst_negotiation_getcaps); + gst_pad_set_link_function (filter->sinkpad, gst_negotiation_pad_link); + filter->srcpad = + gst_pad_new_from_static_template (&gst_negotiation_src_factory, "src"); + gst_pad_set_getcaps_function (filter->srcpad, gst_negotiation_getcaps); + gst_pad_set_link_function (filter->srcpad, gst_negotiation_pad_link); + + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); + gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); + gst_pad_set_chain_function (filter->sinkpad, gst_negotiation_chain); +} + +static GstCaps * +gst_negotiation_getcaps (GstPad * pad) +{ + GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad)); + GstPad *otherpad; + GstCaps *caps; + + otherpad = (pad == negotiation->sinkpad) ? negotiation->srcpad : + negotiation->sinkpad; + + caps = gst_pad_get_allowed_caps (otherpad); + + GST_ERROR ("getcaps called on %" GST_PTR_FORMAT ", returning %" + GST_PTR_FORMAT, pad, caps); + + gst_negotiation_update_caps (negotiation); + gst_object_unref (negotiation); + + return caps; +} + +static GstPadLinkReturn +gst_negotiation_pad_link (GstPad * pad, const GstCaps * caps) +{ + GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad)); + GstPad *otherpad; + GstPadLinkReturn ret; + + otherpad = (pad == negotiation->sinkpad) ? negotiation->srcpad : + negotiation->sinkpad; + + ret = gst_pad_try_set_caps (otherpad, caps); + + GST_ERROR ("pad_link called on %" GST_PTR_FORMAT " with caps %" + GST_PTR_FORMAT ", returning %d", pad, caps, ret); + gst_object_unref (negotiation); + + return ret; +} + +static void +gst_negotiation_update_caps (GstNegotiation * negotiation) +{ + GstCaps *srccaps; + GstCaps *sinkcaps; + GstCaps *icaps; + + srccaps = gst_pad_get_allowed_caps (negotiation->srcpad); + sinkcaps = gst_pad_get_allowed_caps (negotiation->sinkpad); + + icaps = gst_caps_intersect (srccaps, sinkcaps); + gst_caps_free (srccaps); + gst_caps_free (sinkcaps); + + gst_caps_replace (&negotiation->caps, icaps); + g_object_notify (G_OBJECT (negotiation), "allowed-caps"); + GST_DEBUG ("notify %" GST_PTR_FORMAT, icaps); +} + +static void +gst_negotiation_chain (GstPad * pad, GstData * _data) +{ + GstNegotiation *negotiation = GST_NEGOTIATION (gst_pad_get_parent (pad)); + + gst_pad_push (negotiation->srcpad, _data); + gst_object_unref (negotiation); +} + +static void +gst_negotiation_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstNegotiation *filter; + + g_return_if_fail (GST_IS_NEGOTIATION (object)); + filter = GST_NEGOTIATION (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_negotiation_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstNegotiation *filter; + + g_return_if_fail (GST_IS_NEGOTIATION (object)); + filter = GST_NEGOTIATION (object); + + switch (prop_id) { + case ARG_ALLOWED_CAPS: + g_value_set_boxed (value, filter->caps); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst/debugutils/progressreport.c b/gst/debugutils/progressreport.c new file mode 100644 index 00000000..8f2547b3 --- /dev/null +++ b/gst/debugutils/progressreport.c @@ -0,0 +1,478 @@ +/* GStreamer Progress Report Element + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * Copyright (C) <2004> Jan Schmidt + * Copyright (C) <2006> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-progressreport + * + * The progressreport element can be put into a pipeline to report progress, + * which is done by doing upstream duration and position queries in regular + * (real-time) intervals. Both the interval and the prefered query format + * can be specified via the #GstProgressReport:update-freq and the + * #GstProgressReport:format property. + * + * Element messages containing a "progress" structure are posted on the bus + * whenever progress has been queried (since gst-plugins-good 0.10.6 only). + * + * Since the element was originally designed for debugging purposes, it will + * by default also print information about the current progress to the + * terminal. This can be prevented by setting the #GstProgressReport:silent + * property to %TRUE. + * + * This element is most useful in transcoding pipelines or other situations + * where just querying the pipeline might not lead to the wanted result. For + * progress in TIME format, the element is best placed in a 'raw stream' + * section of the pipeline (or after any demuxers/decoders/parsers). + * + * Three more things should be pointed out: firstly, the element will only + * query progress when data flow happens. If data flow is stalled for some + * reason, no progress messages will be posted. Secondly, there are other + * elements (like qtdemux, for example) that may also post "progress" element + * messages on the bus. Applications should check the source of any element + * messages they receive, if needed. Finally, applications should not take + * action on receiving notification of progress being 100%, they should only + * take action when they receive an EOS message (since the progress reported + * is in reference to an internal point of a pipeline and not the pipeline as + * a whole). + * + * + * Example launch line + * |[ + * gst-launch -m filesrc location=foo.ogg ! decodebin ! progressreport update-freq=1 ! audioconvert ! audioresample ! autoaudiosink + * ]| This shows a progress query where a duration is available. + * |[ + * gst-launch -m audiotestsrc ! progressreport update-freq=1 ! audioconvert ! autoaudiosink + * ]| This shows a progress query where no duration is available. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "progressreport.h" + + +enum +{ + ARG_0, + ARG_UPDATE_FREQ, + ARG_SILENT, + ARG_FORMAT +}; + +GstStaticPadTemplate progress_report_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GstStaticPadTemplate progress_report_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static const GstElementDetails progress_report_details = +GST_ELEMENT_DETAILS ("Progress report", + "Testing", + "Periodically query and report on processing progress", + "Jan Schmidt "); + +#define DEFAULT_UPDATE_FREQ 5 +#define DEFAULT_SILENT FALSE +#define DEFAULT_FORMAT "auto" + +static void gst_progress_report_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_progress_report_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_progress_report_event (GstBaseTransform * trans, + GstEvent * event); +static GstFlowReturn gst_progress_report_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); + +static gboolean gst_progress_report_start (GstBaseTransform * trans); +static gboolean gst_progress_report_stop (GstBaseTransform * trans); + +GST_BOILERPLATE (GstProgressReport, gst_progress_report, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); + +static void +gst_progress_report_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&progress_report_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&progress_report_src_template)); + + gst_element_class_set_details (element_class, &progress_report_details); +} + +static void +gst_progress_report_finalize (GObject * obj) +{ + GstProgressReport *filter = GST_PROGRESS_REPORT (obj); + + g_free (filter->format); + filter->format = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_progress_report_class_init (GstProgressReportClass * g_class) +{ + GstBaseTransformClass *gstbasetrans_class; + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (g_class); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (g_class); + + gobject_class->finalize = gst_progress_report_finalize; + gobject_class->set_property = gst_progress_report_set_property; + gobject_class->get_property = gst_progress_report_get_property; + + g_object_class_install_property (gobject_class, + ARG_UPDATE_FREQ, g_param_spec_int ("update-freq", "Update Frequency", + "Number of seconds between reports when data is flowing", 1, G_MAXINT, + DEFAULT_UPDATE_FREQ, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + ARG_SILENT, g_param_spec_boolean ("silent", + "Do not print output to stdout", "Do not print output to stdout", + DEFAULT_SILENT, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + ARG_FORMAT, g_param_spec_string ("format", "format", + "Format to use for the querying", DEFAULT_FORMAT, G_PARAM_READWRITE)); + + gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_progress_report_event); + gstbasetrans_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_progress_report_transform_ip); + gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_progress_report_start); + gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_progress_report_stop); +} + +static void +gst_progress_report_init (GstProgressReport * report, + GstProgressReportClass * g_class) +{ + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (report), TRUE); + + report->update_freq = DEFAULT_UPDATE_FREQ; + report->silent = DEFAULT_SILENT; + report->format = g_strdup (DEFAULT_FORMAT); +} + +static void +gst_progress_report_post_progress (GstProgressReport * filter, + GstFormat format, gint64 current, gint64 total) +{ + GstStructure *s = NULL; + + if (current >= 0 && total > 0) { + gdouble perc; + + perc = gst_util_guint64_to_gdouble (current) * 100.0 / + gst_util_guint64_to_gdouble (total); + perc = CLAMP (perc, 0.0, 100.0); + + /* we provide a "percent" field of integer type to stay compatible + * with qtdemux, but add a second "percent-double" field for those who + * want more precision and are too lazy to calculate it themselves */ + s = gst_structure_new ("progress", "percent", G_TYPE_INT, (gint) perc, + "percent-double", G_TYPE_DOUBLE, perc, "current", G_TYPE_INT64, current, + "total", G_TYPE_INT64, total, NULL); + } else if (current >= 0) { + s = gst_structure_new ("progress", "current", G_TYPE_INT64, current, NULL); + } + + if (s) { + GST_LOG_OBJECT (filter, "posting progress message: %" GST_PTR_FORMAT, s); + gst_structure_set (s, "format", GST_TYPE_FORMAT, format, NULL); + /* can't post it right here because we're holding the object lock */ + filter->pending_msg = gst_message_new_element (GST_OBJECT_CAST (filter), s); + } +} + +static gboolean +gst_progress_report_do_query (GstProgressReport * filter, GstFormat format, + gint hh, gint mm, gint ss) +{ + const gchar *format_name = NULL; + GstPad *sink_pad; + gint64 cur, total; + + sink_pad = GST_BASE_TRANSFORM (filter)->sinkpad; + + GST_LOG_OBJECT (filter, "querying using format %d (%s)", format, + gst_format_get_name (format)); + + if (!gst_pad_query_peer_position (sink_pad, &format, &cur) || + !gst_pad_query_peer_duration (sink_pad, &format, &total)) { + return FALSE; + } + + switch (format) { + case GST_FORMAT_BYTES: + format_name = "bytes"; + break; + case GST_FORMAT_BUFFERS: + format_name = "buffers"; + break; + case GST_FORMAT_PERCENT: + format_name = "percent"; + break; + case GST_FORMAT_TIME: + format_name = "seconds"; + cur /= GST_SECOND; + total /= GST_SECOND; + break; + case GST_FORMAT_DEFAULT:{ + GstCaps *caps; + + format_name = "bogounits"; + caps = GST_PAD_CAPS (GST_BASE_TRANSFORM (filter)->sinkpad); + if (caps && gst_caps_is_fixed (caps) && !gst_caps_is_any (caps)) { + GstStructure *s = gst_caps_get_structure (caps, 0); + const gchar *mime_type = gst_structure_get_name (s); + + if (g_str_has_prefix (mime_type, "video/") || + g_str_has_prefix (mime_type, "image/")) { + format_name = "frames"; + } else if (g_str_has_prefix (mime_type, "audio/")) { + format_name = "samples"; + } + } + break; + } + default:{ + const GstFormatDefinition *details; + + details = gst_format_get_details (format); + if (details) { + format_name = details->nick; + } else { + format_name = "unknown"; + } + break; + } + } + + if (!filter->silent) { + if (total > 0) { + g_print ("%s (%02d:%02d:%02d): %" G_GINT64_FORMAT " / %" + G_GINT64_FORMAT " %s (%4.1f %%)\n", GST_OBJECT_NAME (filter), hh, + mm, ss, cur, total, format_name, (gdouble) cur / total * 100.0); + } else { + g_print ("%s (%02d:%02d:%02d): %" G_GINT64_FORMAT " %s\n", + GST_OBJECT_NAME (filter), hh, mm, ss, cur, format_name); + } + } + + gst_progress_report_post_progress (filter, format, cur, total); + return TRUE; +} + +static void +gst_progress_report_report (GstProgressReport * filter, GTimeVal cur_time) +{ + GstFormat try_formats[] = { GST_FORMAT_TIME, GST_FORMAT_BYTES, + GST_FORMAT_PERCENT, GST_FORMAT_BUFFERS, + GST_FORMAT_DEFAULT + }; + GstMessage *msg; + GstFormat format = GST_FORMAT_UNDEFINED; + gboolean done = FALSE; + glong run_time; + gint hh, mm, ss; + + run_time = cur_time.tv_sec - filter->start_time.tv_sec; + + hh = (run_time / 3600) % 100; + mm = (run_time / 60) % 60; + ss = (run_time % 60); + + GST_OBJECT_LOCK (filter); + + if (filter->format != NULL && strcmp (filter->format, "auto") != 0) { + format = gst_format_get_by_nick (filter->format); + } + + if (format != GST_FORMAT_UNDEFINED) { + done = gst_progress_report_do_query (filter, format, hh, mm, ss); + } else { + gint i; + + for (i = 0; i < G_N_ELEMENTS (try_formats); ++i) { + done = gst_progress_report_do_query (filter, try_formats[i], hh, mm, ss); + if (done) + break; + } + } + + if (!done && !filter->silent) { + g_print ("%s (%2d:%2d:%2d): Could not query position and/or duration\n", + GST_OBJECT_NAME (filter), hh, mm, ss); + } + + msg = filter->pending_msg; + filter->pending_msg = NULL; + GST_OBJECT_UNLOCK (filter); + + if (msg) { + gst_element_post_message (GST_ELEMENT_CAST (filter), msg); + } +} + +static gboolean +gst_progress_report_event (GstBaseTransform * trans, GstEvent * event) +{ + GstProgressReport *filter; + + filter = GST_PROGRESS_REPORT (trans); + + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + GTimeVal cur_time; + + g_get_current_time (&cur_time); + gst_progress_report_report (filter, cur_time); + } + return GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event); +} + +static GstFlowReturn +gst_progress_report_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstProgressReport *filter; + gboolean need_update; + GTimeVal cur_time; + + g_get_current_time (&cur_time); + + filter = GST_PROGRESS_REPORT (trans); + + /* Check if update_freq seconds have passed since the last update */ + GST_OBJECT_LOCK (filter); + need_update = + ((cur_time.tv_sec - filter->last_report.tv_sec) >= filter->update_freq); + GST_OBJECT_UNLOCK (filter); + + if (need_update) { + gst_progress_report_report (filter, cur_time); + GST_OBJECT_LOCK (filter); + filter->last_report = cur_time; + GST_OBJECT_UNLOCK (filter); + } + + return GST_FLOW_OK; +} + +static gboolean +gst_progress_report_start (GstBaseTransform * trans) +{ + GstProgressReport *filter; + + filter = GST_PROGRESS_REPORT (trans); + + g_get_current_time (&filter->last_report); + filter->start_time = filter->last_report; + + return TRUE; +} + +static gboolean +gst_progress_report_stop (GstBaseTransform * trans) +{ + /* anything we should be doing here? */ + return TRUE; +} + +static void +gst_progress_report_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstProgressReport *filter; + + filter = GST_PROGRESS_REPORT (object); + + switch (prop_id) { + case ARG_UPDATE_FREQ: + GST_OBJECT_LOCK (filter); + filter->update_freq = g_value_get_int (value); + GST_OBJECT_UNLOCK (filter); + break; + case ARG_SILENT: + GST_OBJECT_LOCK (filter); + filter->silent = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (filter); + break; + case ARG_FORMAT: + GST_OBJECT_LOCK (filter); + g_free (filter->format); + filter->format = g_value_dup_string (value); + if (filter->format == NULL) + filter->format = g_strdup ("auto"); + GST_OBJECT_UNLOCK (filter); + break; + default: + break; + } +} + +static void +gst_progress_report_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstProgressReport *filter; + + filter = GST_PROGRESS_REPORT (object); + + switch (prop_id) { + case ARG_UPDATE_FREQ: + GST_OBJECT_LOCK (filter); + g_value_set_int (value, filter->update_freq); + GST_OBJECT_UNLOCK (filter); + break; + case ARG_SILENT: + GST_OBJECT_LOCK (filter); + g_value_set_boolean (value, filter->silent); + GST_OBJECT_UNLOCK (filter); + break; + case ARG_FORMAT: + GST_OBJECT_LOCK (filter); + g_value_set_string (value, filter->format); + GST_OBJECT_UNLOCK (filter); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst/debugutils/progressreport.h b/gst/debugutils/progressreport.h new file mode 100644 index 00000000..92886b29 --- /dev/null +++ b/gst/debugutils/progressreport.h @@ -0,0 +1,66 @@ +/* GStreamer Progress Report Element + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * Copyright (C) <2004> Jan Schmidt + * Copyright (C) <2006> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_PROGRESS_REPORT_H__ +#define __GST_PROGRESS_REPORT_H__ + +#include + +G_BEGIN_DECLS +#define GST_TYPE_PROGRESS_REPORT \ + (gst_progress_report_get_type()) +#define GST_PROGRESS_REPORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PROGRESS_REPORT,GstProgressReport)) +#define GST_PROGRESS_REPORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PROGRESS_REPORT,GstProgressReportClass)) +#define GST_IS_PROGRESS_REPORT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PROGRESS_REPORT)) +#define GST_IS_PROGRESS_REPORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROGRESS_REPORT)) +typedef struct _GstProgressReport GstProgressReport; +typedef struct _GstProgressReportClass GstProgressReportClass; + +struct _GstProgressReport +{ + GstBaseTransform basetransform; + + GstMessage *pending_msg; + + gint update_freq; + gboolean silent; + GTimeVal start_time; + GTimeVal last_report; + + /* Format used for querying. Using a string here because the + * format might not be registered yet when the property is set */ + gchar *format; +}; + +struct _GstProgressReportClass +{ + GstBaseTransformClass parent_class; +}; + +GType gst_progress_report_get_type (void); + +G_END_DECLS +#endif /* __GST_PROGRESS_REPORT_H__ */ diff --git a/gst/debugutils/rndbuffersize.c b/gst/debugutils/rndbuffersize.c new file mode 100644 index 00000000..7a8abd6b --- /dev/null +++ b/gst/debugutils/rndbuffersize.c @@ -0,0 +1,371 @@ +/* GStreamer + * Copyright (C) 2007 Nokia Corporation (contact ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-rndbuffersize + * + * This element pulls buffers with random sizes from the source. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_rnd_buffer_size_debug); +#define GST_CAT_DEFAULT gst_rnd_buffer_size_debug + +#define GST_TYPE_RND_BUFFER_SIZE (gst_rnd_buffer_size_get_type()) +#define GST_RND_BUFFER_SIZE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RND_BUFFER_SIZE,GstRndBufferSize)) +#define GST_RND_BUFFER_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RND_BUFFER_SIZE,GstRndBufferSizeClass)) +#define GST_IS_RND_BUFFER_SIZE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RND_BUFFER_SIZE)) +#define GST_IS_RND_BUFFER_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RND_BUFFER_SIZE)) + +typedef struct _GstRndBufferSize GstRndBufferSize; +typedef struct _GstRndBufferSizeClass GstRndBufferSizeClass; + +struct _GstRndBufferSize +{ + GstElement parent; + + /*< private > */ + GRand *rand; + gulong seed; + glong min, max; + + GstPad *sinkpad, *srcpad; + guint64 offset; +}; + +struct _GstRndBufferSizeClass +{ + GstElementClass parent_class; +}; + +enum +{ + ARG_SEED = 1, + ARG_MINIMUM, + ARG_MAXIMUM +}; + +#define DEFAULT_SEED 0 +#define DEFAULT_MIN 1 +#define DEFAULT_MAX (8*1024) + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static void gst_rnd_buffer_size_finalize (GObject * object); +static void gst_rnd_buffer_size_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rnd_buffer_size_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_rnd_buffer_size_activate (GstPad * pad); +static gboolean gst_rnd_buffer_size_activate_pull (GstPad * pad, + gboolean active); +static void gst_rnd_buffer_size_loop (GstRndBufferSize * self); +static GstStateChangeReturn gst_rnd_buffer_size_change_state (GstElement * + element, GstStateChange transition); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_rnd_buffer_size_debug, "rndbuffersize", 0, \ + "rndbuffersize element"); + +GST_BOILERPLATE_FULL (GstRndBufferSize, gst_rnd_buffer_size, GstElement, + GST_TYPE_ELEMENT, DEBUG_INIT); + + +static void +gst_rnd_buffer_size_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_template)); + + gst_element_class_set_details_simple (gstelement_class, "Random buffer size", + "Testing", "pull random sized buffers", + "Stefan Kost )"); +} + + +static void +gst_rnd_buffer_size_class_init (GstRndBufferSizeClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_set_property); + gobject_class->get_property = + GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_get_property); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_finalize); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_change_state); + + /* FIXME 0.11: these should all be int instead of long, to avoid bugs + * when passing these as varargs with g_object_set(), and there was no + * reason to use long in the first place here */ + g_object_class_install_property (gobject_class, ARG_SEED, + g_param_spec_ulong ("seed", "random number seed", + "seed for randomness (initialized when going from READY to PAUSED)", + 0, G_MAXUINT32, DEFAULT_SEED, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, ARG_MINIMUM, + g_param_spec_long ("min", "mininum", "mininum buffer size", + 0, G_MAXINT32, DEFAULT_MIN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, ARG_MAXIMUM, + g_param_spec_long ("max", "maximum", "maximum buffer size", + 1, G_MAXINT32, DEFAULT_MAX, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +gst_rnd_buffer_size_init (GstRndBufferSize * self, + GstRndBufferSizeClass * g_class) +{ + self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_activate_function (self->sinkpad, + GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_activate)); + gst_pad_set_activatepull_function (self->sinkpad, + GST_DEBUG_FUNCPTR (gst_rnd_buffer_size_activate_pull)); + gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); + + self->srcpad = gst_pad_new_from_static_template (&src_template, "src"); + gst_element_add_pad (GST_ELEMENT (self), self->srcpad); +} + + +static void +gst_rnd_buffer_size_finalize (GObject * object) +{ + GstRndBufferSize *self = GST_RND_BUFFER_SIZE (object); + + if (self->rand) { + g_rand_free (self->rand); + self->rand = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +static void +gst_rnd_buffer_size_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRndBufferSize *self = GST_RND_BUFFER_SIZE (object); + + switch (prop_id) { + case ARG_SEED: + self->seed = g_value_get_ulong (value); + break; + case ARG_MINIMUM: + self->min = g_value_get_long (value); + break; + case ARG_MAXIMUM: + self->max = g_value_get_long (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_rnd_buffer_size_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstRndBufferSize *self = GST_RND_BUFFER_SIZE (object); + + switch (prop_id) { + case ARG_SEED: + g_value_set_ulong (value, self->seed); + break; + case ARG_MINIMUM: + g_value_set_long (value, self->min); + break; + case ARG_MAXIMUM: + g_value_set_long (value, self->max); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static gboolean +gst_rnd_buffer_size_activate (GstPad * pad) +{ + if (gst_pad_check_pull_range (pad)) { + return gst_pad_activate_pull (pad, TRUE); + } else { + GST_INFO_OBJECT (pad, "push mode not supported"); + return FALSE; + } +} + + +static gboolean +gst_rnd_buffer_size_activate_pull (GstPad * pad, gboolean active) +{ + GstRndBufferSize *self = GST_RND_BUFFER_SIZE (GST_OBJECT_PARENT (pad)); + + if (active) { + GST_INFO_OBJECT (self, "starting pull"); + return gst_pad_start_task (pad, (GstTaskFunction) gst_rnd_buffer_size_loop, + self); + } else { + GST_INFO_OBJECT (self, "stopping pull"); + return gst_pad_stop_task (pad); + } +} + + +static void +gst_rnd_buffer_size_loop (GstRndBufferSize * self) +{ + GstBuffer *buf = NULL; + GstFlowReturn ret; + guint num_bytes; + + if (G_UNLIKELY (self->min > self->max)) + goto bogus_minmax; + + if (G_UNLIKELY (self->min != self->max)) { + num_bytes = g_rand_int_range (self->rand, self->min, self->max); + } else { + num_bytes = self->min; + } + + GST_LOG_OBJECT (self, "pulling %u bytes at offset %" G_GUINT64_FORMAT, + num_bytes, self->offset); + + ret = gst_pad_pull_range (self->sinkpad, self->offset, num_bytes, &buf); + + if (ret != GST_FLOW_OK) + goto pull_failed; + + if (GST_BUFFER_SIZE (buf) < num_bytes) { + GST_WARNING_OBJECT (self, "short buffer: %u bytes", GST_BUFFER_SIZE (buf)); + } + + self->offset += GST_BUFFER_SIZE (buf); + + ret = gst_pad_push (self->srcpad, buf); + + if (ret != GST_FLOW_OK) + goto push_failed; + + return; + +pause_task: + { + GST_DEBUG_OBJECT (self, "pausing task"); + gst_pad_pause_task (self->sinkpad); + return; + } + +pull_failed: + { + if (ret == GST_FLOW_UNEXPECTED) { + GST_DEBUG_OBJECT (self, "eos"); + gst_pad_push_event (self->srcpad, gst_event_new_eos ()); + } else { + GST_WARNING_OBJECT (self, "pull_range flow: %s", gst_flow_get_name (ret)); + } + goto pause_task; + } + +push_failed: + { + GST_DEBUG_OBJECT (self, "push flow: %s", gst_flow_get_name (ret)); + if (ret == GST_FLOW_UNEXPECTED) { + GST_DEBUG_OBJECT (self, "eos"); + gst_pad_push_event (self->srcpad, gst_event_new_eos ()); + } else if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { + GST_ELEMENT_ERROR (self, STREAM, FAILED, + ("Internal data stream error."), + ("streaming stopped, reason: %s", gst_flow_get_name (ret))); + } + goto pause_task; + } + +bogus_minmax: + { + GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, + ("The minimum buffer size is smaller than the maximum buffer size."), + ("buffer sizes: max=%ld, min=%ld", self->min, self->max)); + goto pause_task; + } +} + +static GstStateChangeReturn +gst_rnd_buffer_size_change_state (GstElement * element, + GstStateChange transition) +{ + GstRndBufferSize *self = GST_RND_BUFFER_SIZE (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + self->offset = 0; + if (!self->rand) { + self->rand = g_rand_new_with_seed (self->seed); + } + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (self->rand) { + g_rand_free (self->rand); + self->rand = NULL; + } + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} diff --git a/gst/debugutils/testplugin.c b/gst/debugutils/testplugin.c new file mode 100644 index 00000000..dbb1e618 --- /dev/null +++ b/gst/debugutils/testplugin.c @@ -0,0 +1,318 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "tests.h" + +GST_DEBUG_CATEGORY_STATIC (gst_test_debug); +#define GST_CAT_DEFAULT gst_test_debug + +/* This plugin does all the tests registered in the tests.h file + */ + +#define GST_TYPE_TEST \ + (gst_test_get_type()) +#define GST_TEST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST,GstTest)) +#define GST_TEST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST,GstTestClass)) +#define GST_TEST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_TEST,GstTestClass)) +#define GST_IS_TEST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST)) +#define GST_IS_TEST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST)) + +typedef struct _GstTest GstTest; +typedef struct _GstTestClass GstTestClass; + +struct _GstTest +{ + GstBaseSink basesink; + + gpointer tests[TESTS_COUNT]; + GValue values[TESTS_COUNT]; +}; + +struct _GstTestClass +{ + GstBaseSinkClass parent_class; + + gchar *param_names[2 * TESTS_COUNT]; +}; + +static void gst_test_finalize (GstTest * test); + +static gboolean gst_test_start (GstBaseSink * trans); +static gboolean gst_test_stop (GstBaseSink * trans); +static gboolean gst_test_sink_event (GstBaseSink * basesink, GstEvent * event); +static GstFlowReturn gst_test_render_buffer (GstBaseSink * basesink, + GstBuffer * buf); + +static void gst_test_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_test_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +static const GstElementDetails details = GST_ELEMENT_DETAILS ("Test plugin", + "Testing", + "perform a number of tests", + "Benjamin Otte "); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_test_debug, "testsink", 0, \ + "debugging category for testsink element"); + +GST_BOILERPLATE_FULL (GstTest, gst_test, GstBaseSink, GST_TYPE_BASE_SINK, + DEBUG_INIT); + + +static void +gst_test_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details (gstelement_class, &details); +} + +static void +gst_test_class_init (GstTestClass * klass) +{ + GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + guint i; + + object_class->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property); + object_class->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property); + + object_class->finalize = (GObjectFinalizeFunc) gst_test_finalize; + + for (i = 0; i < TESTS_COUNT; i++) { + GParamSpec *spec; + + spec = tests[i].get_spec (&tests[i], FALSE); + klass->param_names[2 * i] = g_strdup (g_param_spec_get_name (spec)); + g_object_class_install_property (object_class, 2 * i + 1, spec); + spec = tests[i].get_spec (&tests[i], TRUE); + klass->param_names[2 * i + 1] = g_strdup (g_param_spec_get_name (spec)); + g_object_class_install_property (object_class, 2 * i + 2, spec); + } + + basesink_class->preroll = GST_DEBUG_FUNCPTR (gst_test_render_buffer); + basesink_class->render = GST_DEBUG_FUNCPTR (gst_test_render_buffer); + basesink_class->event = GST_DEBUG_FUNCPTR (gst_test_sink_event); + basesink_class->start = GST_DEBUG_FUNCPTR (gst_test_start); + basesink_class->stop = GST_DEBUG_FUNCPTR (gst_test_stop); +} + +static void +gst_test_init (GstTest * test, GstTestClass * g_class) +{ + GstTestClass *klass; + guint i; + + klass = GST_TEST_GET_CLASS (test); + for (i = 0; i < TESTS_COUNT; i++) { + GParamSpec *spec = g_object_class_find_property (G_OBJECT_CLASS (klass), + klass->param_names[2 * i + 1]); + + g_value_init (&test->values[i], G_PARAM_SPEC_VALUE_TYPE (spec)); + } +} + +static void +gst_test_finalize (GstTest * test) +{ + guint i; + + for (i = 0; i < TESTS_COUNT; i++) { + g_value_unset (&test->values[i]); + } + + G_OBJECT_CLASS (parent_class)->finalize ((GObject *) test); +} + +static void +tests_unset (GstTest * test) +{ + guint i; + + for (i = 0; i < TESTS_COUNT; i++) { + if (test->tests[i]) { + tests[i].free (test->tests[i]); + test->tests[i] = NULL; + } + } +} + +static void +tests_set (GstTest * test) +{ + guint i; + + for (i = 0; i < TESTS_COUNT; i++) { + g_assert (test->tests[i] == NULL); + test->tests[i] = tests[i].new (&tests[i]); + } +} + +static gboolean +gst_test_sink_event (GstBaseSink * basesink, GstEvent * event) +{ + GstTestClass *klass = GST_TEST_GET_CLASS (basesink); + GstTest *test = GST_TEST (basesink); + gboolean ret = FALSE; + + switch (GST_EVENT_TYPE (event)) { +/* + case GST_EVENT_NEWSEGMENT: + if (GST_EVENT_DISCONT_NEW_MEDIA (event)) { + tests_unset (test); + tests_set (test); + } + break; +*/ + case GST_EVENT_EOS:{ + gint i; + + g_object_freeze_notify (G_OBJECT (test)); + for (i = 0; i < TESTS_COUNT; i++) { + if (test->tests[i]) { + if (!tests[i].finish (test->tests[i], &test->values[i])) { + GValue v = { 0, }; + gchar *real, *expected; + + expected = gst_value_serialize (&test->values[i]); + g_value_init (&v, G_VALUE_TYPE (&test->values[i])); + g_object_get_property (G_OBJECT (test), klass->param_names[2 * i], + &v); + real = gst_value_serialize (&v); + g_value_unset (&v); + GST_ELEMENT_ERROR (test, STREAM, FORMAT, (NULL), + ("test %s returned value \"%s\" and not expected value \"%s\"", + klass->param_names[2 * i], real, expected)); + g_free (real); + g_free (expected); + } + g_object_notify (G_OBJECT (test), klass->param_names[2 * i]); + } + } + g_object_thaw_notify (G_OBJECT (test)); + ret = TRUE; + break; + } + default: + break; + } + + return ret; +} + +static GstFlowReturn +gst_test_render_buffer (GstBaseSink * basesink, GstBuffer * buf) +{ + GstTest *test = GST_TEST (basesink); + guint i; + + for (i = 0; i < TESTS_COUNT; i++) { + if (test->tests[i]) { + tests[i].add (test->tests[i], buf); + } + } + return GST_FLOW_OK; +} + +static gboolean +gst_test_start (GstBaseSink * sink) +{ + GstTest *test = GST_TEST (sink); + + tests_set (test); + return TRUE; +} + +static gboolean +gst_test_stop (GstBaseSink * sink) +{ + GstTest *test = GST_TEST (sink); + + tests_unset (test); + return TRUE; +} + +static void +gst_test_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTest *test = GST_TEST (object); + + if (prop_id == 0 || prop_id > 2 * TESTS_COUNT) { + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + return; + } + + if (prop_id % 2) { + /* real values can't be set */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } else { + /* expected values */ + GST_OBJECT_LOCK (test); + g_value_copy (value, &test->values[prop_id / 2 - 1]); + GST_OBJECT_UNLOCK (test); + } +} + +static void +gst_test_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstTest *test = GST_TEST (object); + guint id = (prop_id - 1) / 2; + + if (prop_id == 0 || prop_id > 2 * TESTS_COUNT) { + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + return; + } + + GST_OBJECT_LOCK (test); + + if (prop_id % 2) { + /* real values */ + tests[id].get_value (test->tests[id], value); + } else { + /* expected values */ + g_value_copy (&test->values[id], value); + } + + GST_OBJECT_UNLOCK (test); +} diff --git a/gst/debugutils/tests.c b/gst/debugutils/tests.c new file mode 100644 index 00000000..cd382782 --- /dev/null +++ b/gst/debugutils/tests.c @@ -0,0 +1,568 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * includes code based on glibc 2.2.3's crypt/md5.c, + * Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tests.h" +#include +#include + + +/* + *** LENGTH *** + */ + +typedef struct +{ + gint64 value; +} +LengthTest; + +static GParamSpec * +length_get_spec (const GstTestInfo * info, gboolean compare_value) +{ + if (compare_value) { + return g_param_spec_int64 ("expected-length", "expected length", + "expected length of stream", -1, G_MAXINT64, -1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + } else { + return g_param_spec_int64 ("length", "length", "length of stream", + -1, G_MAXINT64, -1, G_PARAM_READABLE); + } +} + +static gpointer +length_new (const GstTestInfo * info) +{ + return g_new0 (LengthTest, 1); +} + +static void +length_add (gpointer test, GstBuffer * buffer) +{ + LengthTest *t = test; + + t->value += GST_BUFFER_SIZE (buffer); +} + +static gboolean +length_finish (gpointer test, GValue * value) +{ + LengthTest *t = test; + + if (g_value_get_int64 (value) == -1) + return TRUE; + + return t->value == g_value_get_int64 (value); +} + +static void +length_get_value (gpointer test, GValue * value) +{ + LengthTest *t = test; + + g_value_set_int64 (value, t ? t->value : -1); +} + +/* + *** BUFFER COUNT *** + */ + +static GParamSpec * +buffer_count_get_spec (const GstTestInfo * info, gboolean compare_value) +{ + if (compare_value) { + return g_param_spec_int64 ("expected-buffer-count", "expected buffer count", + "expected number of buffers in stream", + -1, G_MAXINT64, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + } else { + return g_param_spec_int64 ("buffer-count", "buffer count", + "number of buffers in stream", -1, G_MAXINT64, -1, G_PARAM_READABLE); + } +} + +static void +buffer_count_add (gpointer test, GstBuffer * buffer) +{ + LengthTest *t = test; + + t->value++; +} + +/* + *** TIMESTAMP / DURATION MATCHING *** + */ + +typedef struct +{ + guint64 diff; + guint count; + GstClockTime expected; +} +TimeDurTest; + +static GParamSpec * +timedur_get_spec (const GstTestInfo * info, gboolean compare_value) +{ + if (compare_value) { + return g_param_spec_int64 ("allowed-timestamp-deviation", + "allowed timestamp deviation", + "allowed average difference in usec between timestamp of next buffer " + "and expected timestamp from analyzing last buffer", + -1, G_MAXINT64, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + } else { + return g_param_spec_int64 ("timestamp-deviation", + "timestamp deviation", + "average difference in usec between timestamp of next buffer " + "and expected timestamp from analyzing last buffer", + -1, G_MAXINT64, -1, G_PARAM_READABLE); + } +} + +static gpointer +timedur_new (const GstTestInfo * info) +{ + TimeDurTest *ret = g_new0 (TimeDurTest, 1); + + ret->expected = GST_CLOCK_TIME_NONE; + + return ret; +} + +static void +timedur_add (gpointer test, GstBuffer * buffer) +{ + TimeDurTest *t = test; + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (t->expected)) { + t->diff += labs (GST_BUFFER_TIMESTAMP (buffer) - t->expected); + t->count++; + } + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BUFFER_DURATION_IS_VALID (buffer)) { + t->expected = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + } else { + t->expected = GST_CLOCK_TIME_NONE; + } +} + +static gboolean +timedur_finish (gpointer test, GValue * value) +{ + TimeDurTest *t = test; + + if (g_value_get_int64 (value) == -1) + return TRUE; + + return (t->diff / MAX (1, t->count)) <= g_value_get_int64 (value); +} + +static void +timedur_get_value (gpointer test, GValue * value) +{ + TimeDurTest *t = test; + + g_value_set_int64 (value, t ? (t->diff / MAX (1, t->count)) : -1); +} + +/* + *** MD5 *** + */ + +typedef struct +{ + /* md5 information */ + guint32 A; + guint32 B; + guint32 C; + guint32 D; + + guint32 total[2]; + guint32 buflen; + gchar buffer[128]; + + gchar result[33]; +} +MD5Test; + +static void md5_process_block (const void *buffer, size_t len, MD5Test * ctx); +static void md5_read_ctx (MD5Test * ctx, gchar * result); + +static GParamSpec * +md5_get_spec (const GstTestInfo * info, gboolean compare_value) +{ + if (compare_value) { + return g_param_spec_string ("expected-md5", "expected md5", + "expected md5 of processing the whole data", + "---", G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + } else { + return g_param_spec_string ("md5", "md5", + "md5 of processing the whole data", "---", G_PARAM_READABLE); + } +} + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const guchar fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + +/* MD5 functions */ +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +static gpointer +md5_new (const GstTestInfo * info) +{ + MD5Test *ctx = g_new (MD5Test, 1); + + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; + + memset (ctx->result, 0, 33); + + return ctx; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +static gboolean +md5_finish (gpointer test, GValue * value) +{ + MD5Test *ctx = test; + const gchar *str_val = g_value_get_string (value); + + /* Take yet unprocessed bytes into account. */ + guint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(guint32 *) & ctx->buffer[bytes + pad] = GUINT32_TO_LE (ctx->total[0] << 3); + *(guint32 *) & ctx->buffer[bytes + pad + 4] = + GUINT32_TO_LE ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + md5_read_ctx (ctx, ctx->result); + if (g_str_equal (str_val, "---")) + return TRUE; + if (g_str_equal (str_val, ctx->result)) + return TRUE; + return FALSE; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +static void +md5_read_ctx (MD5Test * ctx, gchar * result) +{ + guint32 resbuf[4]; + guint i; + + resbuf[0] = GUINT32_TO_LE (ctx->A); + resbuf[1] = GUINT32_TO_LE (ctx->B); + resbuf[2] = GUINT32_TO_LE (ctx->C); + resbuf[3] = GUINT32_TO_LE (ctx->D); + + for (i = 0; i < 16; i++) + sprintf (result + i * 2, "%02x", ((guchar *) resbuf)[i]); +} + +static void +md5_add (gpointer test, GstBuffer * gstbuffer) +{ + const void *buffer = GST_BUFFER_DATA (gstbuffer); + gsize len = GST_BUFFER_SIZE (gstbuffer); + MD5Test *ctx = test; + + /*const void aligned_buffer = buffer; */ + + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) { + gsize left_over = ctx->buflen; + gsize add = 128 - left_over > len ? len : 128 - left_over; + + /* Only put full words in the buffer. */ + /* Forcing alignment here appears to be only an optimization. + * The glibc source uses __alignof__, which seems to be a + * gratuitous usage of a GCC extension, when sizeof() will + * work fine. (And don't question the sanity of using + * sizeof(guint32) instead of 4. */ + /* add -= add % __alignof__ (guint32); */ + add -= add % sizeof (guint32); + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len > 64) { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +static void +md5_process_block (const void *buffer, size_t len, MD5Test * ctx) +{ +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + guint32 correct_words[16]; + const guint32 *words = buffer; + size_t nwords = len / sizeof (guint32); + const guint32 *endp = words + nwords; + guint32 A = ctx->A; + guint32 B = ctx->B; + guint32 C = ctx->C; + guint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) { + guint32 *cwp = correct_words; + guint32 A_save = A; + guint32 B_save = B; + guint32 C_save = C; + guint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = GUINT32_TO_LE (*words)) + T; \ + ++words; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} + +static void +md5_get_value (gpointer test, GValue * value) +{ + MD5Test *ctx = test; + + if (!ctx) { + g_value_set_string (value, "---"); + } else if (ctx->result[0] == 0) { + gchar *str = g_new (gchar, 33); + + str[32] = 0; + md5_read_ctx (ctx, str); + g_value_take_string (value, str); + } else { + g_value_set_string (value, ctx->result); + } +} + +/* + *** TESTINFO *** + */ + +const GstTestInfo tests[] = { + {length_get_spec, length_new, length_add, + length_finish, length_get_value, g_free}, + {buffer_count_get_spec, length_new, buffer_count_add, + length_finish, length_get_value, g_free}, + {timedur_get_spec, timedur_new, timedur_add, + timedur_finish, timedur_get_value, g_free}, + {md5_get_spec, md5_new, md5_add, + md5_finish, md5_get_value, g_free} +}; diff --git a/gst/debugutils/tests.h b/gst/debugutils/tests.h new file mode 100644 index 00000000..9926af62 --- /dev/null +++ b/gst/debugutils/tests.h @@ -0,0 +1,43 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#ifndef __GST_TESTS_H__ +#define __GST_TESTS_H__ + + +typedef struct _GstTestInfo GstTestInfo; + +struct _GstTestInfo +{ + GParamSpec *(*get_spec) (const GstTestInfo * info, gboolean compare_value); + gpointer (*new) (const GstTestInfo * info); + void (*add) (gpointer test, GstBuffer * buffer); + gboolean (*finish) (gpointer test, GValue * value); + void (*get_value) (gpointer test, GValue * value); + void (*free) (gpointer test); +}; + +extern const GstTestInfo tests[]; +/* keep up to date! */ +#define TESTS_COUNT (4) + + +#endif /* __GST_TESTS_H__ */ -- cgit