diff options
author | Tim-Philipp Müller <tim@centricular.net> | 2005-10-05 11:38:29 +0000 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.net> | 2005-10-05 11:38:29 +0000 |
commit | 2fa12d1a6de6b985723e271585ea8dfb50a2d04a (patch) | |
tree | 5a6530c5c0c9bff3af328a9e21ad98616f43b662 | |
parent | 76620459d5eff33e3408f61b8cecfa365f1e45bf (diff) |
gst/debug/: Port progressreport, navseek, navigationtest, testsink and breakmydata.
Original commit message from CVS:
* gst/debug/Makefile.am:
* gst/debug/breakmydata.c:
* gst/debug/gstdebug.c:
* gst/debug/gstnavigationtest.c:
* gst/debug/gstnavseek.c:
* gst/debug/gstnavseek.h:
* gst/debug/progressreport.c:
* gst/debug/testplugin.c:
Port progressreport, navseek, navigationtest, testsink and
breakmydata.
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | gst/debug/Makefile.am | 34 | ||||
-rw-r--r-- | gst/debug/breakmydata.c | 225 | ||||
-rw-r--r-- | gst/debug/gstdebug.c | 12 | ||||
-rw-r--r-- | gst/debug/gstnavigationtest.c | 194 | ||||
-rw-r--r-- | gst/debug/gstnavseek.c | 247 | ||||
-rw-r--r-- | gst/debug/gstnavseek.h | 21 | ||||
-rw-r--r-- | gst/debug/progressreport.c | 384 | ||||
-rw-r--r-- | gst/debug/testplugin.c | 188 |
9 files changed, 729 insertions, 589 deletions
@@ -1,3 +1,16 @@ +2005-10-05 Tim-Philipp Müller <tim at centricular dot net> + + * gst/debug/Makefile.am: + * gst/debug/breakmydata.c: + * gst/debug/gstdebug.c: + * gst/debug/gstnavigationtest.c: + * gst/debug/gstnavseek.c: + * gst/debug/gstnavseek.h: + * gst/debug/progressreport.c: + * gst/debug/testplugin.c: + Port progressreport, navseek, navigationtest, testsink and + breakmydata. + 2005-10-05 Edward Hervey <edward@fluendo.com> * ext/dv/gstdvdemux.c: (gst_dvdemux_src_convert), diff --git a/gst/debug/Makefile.am b/gst/debug/Makefile.am index f9013530..b3b2911f 100644 --- a/gst/debug/Makefile.am +++ b/gst/debug/Makefile.am @@ -1,4 +1,4 @@ -plugin_LTLIBRARIES = libgstefence.la # libgstnavigationtest.la libgstdebug.la +plugin_LTLIBRARIES = libgstefence.la libgstdebug.la libgstnavigationtest.la noinst_HEADERS = efence.h gstnavigationtest.h gstnavseek.h tests.h @@ -7,18 +7,20 @@ libgstefence_la_CFLAGS = $(GST_CFLAGS) libgstefence_la_LIBADD = $(GST_LIBS) libgstefence_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -# libgstnavigationtest_la_SOURCES = gstnavigationtest.c -# libgstnavigationtest_la_CFLAGS = $(GST_CFLAGS) -I$(top_srcdir)/gst/videofilter -# libgstnavigationtest_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -# -# libgstdebug_la_SOURCES = \ -# gstdebug.c \ -# breakmydata.c \ -# negotiation.c \ -# gstnavseek.c \ -# progressreport.c \ -# tests.c \ -# testplugin.c -# -# libgstdebug_la_CFLAGS = $(GST_CFLAGS) -# libgstdebug_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstnavigationtest_la_SOURCES = gstnavigationtest.c +libgstnavigationtest_la_CFLAGS = $(GST_CFLAGS) -I$(top_srcdir)/gst/videofilter +libgstnavigationtest_la_LIBADD = $(GST_LIBS) $(top_builddir)/gst/videofilter/libgstvideofilter-@GST_MAJORMINOR@.la +libgstnavigationtest_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +libgstdebug_la_SOURCES = \ + gstdebug.c \ + breakmydata.c \ + progressreport.c \ + gstnavseek.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) diff --git a/gst/debug/breakmydata.c b/gst/debug/breakmydata.c index b35b908c..f9e3be2a 100644 --- a/gst/debug/breakmydata.c +++ b/gst/debug/breakmydata.c @@ -22,6 +22,7 @@ #endif #include <gst/gst.h> +#include <gst/base/gstbasetransform.h> GST_DEBUG_CATEGORY_STATIC (gst_break_my_data_debug); #define GST_CAT_DEFAULT gst_break_my_data_debug @@ -56,10 +57,7 @@ typedef struct _GstBreakMyDataClass GstBreakMyDataClass; struct _GstBreakMyData { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; + GstBaseTransform basetransform; GRand *rand; guint skipped; @@ -72,113 +70,91 @@ struct _GstBreakMyData struct _GstBreakMyDataClass { - GstElementClass parent_class; + GstBaseTransformClass parent_class; }; -GST_BOILERPLATE (GstBreakMyData, gst_break_my_data, GstElement, - GST_TYPE_ELEMENT) - - static void gst_break_my_data_set_property (GObject * object, +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, +static void gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); - static void gst_break_my_data_chain (GstPad * pad, GstData * _data); - static GstStateChangeReturn gst_break_my_data_change_state (GstElement * - element); +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 GstElementDetails details = GST_ELEMENT_DETAILS ("breakmydata", + "Testing", + "randomly change data in the stream", + "Benjamin Otte <otte@gnome>"); + +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); + +GST_BOILERPLATE (GstBreakMyData, gst_break_my_data, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM) static void gst_break_my_data_base_init (gpointer g_class) { - static GstElementDetails details = GST_ELEMENT_DETAILS ("breakmydata", - "Testing", - "randomly change data in the stream", - "Benjamin Otte <otte@gnome>"); 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) { - GObjectClass *object = G_OBJECT_CLASS (klass); - GstElementClass *element = GST_ELEMENT_CLASS (klass); + GstBaseTransformClass *gstbasetrans_class; + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); - object->set_property = GST_DEBUG_FUNCPTR (gst_break_my_data_set_property); - object->get_property = GST_DEBUG_FUNCPTR (gst_break_my_data_get_property); + 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 (object, ARG_SEED, + g_object_class_install_property (gobject_class, ARG_SEED, g_param_spec_uint ("seed", "seed", - "seed for randomness (initialized when goint from READY to PAUSED)", + "seed for randomness (initialized when going from READY to PAUSED)", 0, 0xFFFFFFFF, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object, ARG_SET_TO, + 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, 255, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object, ARG_SKIP, + 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 (object, ARG_PROBABILITY, + g_object_class_install_property (gobject_class, ARG_PROBABILITY, g_param_spec_double ("probability", "probability", - "probability that a buffer is changed", 0.0, 1.0, 0.0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - element->change_state = gst_break_my_data_change_state; + "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); + gstbasetrans_class->passthrough_on_same_caps = TRUE; } static void -gst_break_my_data_init (GstBreakMyData * break_my_data) +gst_break_my_data_init (GstBreakMyData * bmd, GstBreakMyDataClass * g_class) { - break_my_data->sinkpad = gst_pad_new ("sink", GST_PAD_SINK); - gst_element_add_pad (GST_ELEMENT (break_my_data), break_my_data->sinkpad); - gst_pad_set_chain_function (break_my_data->sinkpad, - GST_DEBUG_FUNCPTR (gst_break_my_data_chain)); - gst_pad_set_link_function (break_my_data->sinkpad, gst_pad_proxy_pad_link); - gst_pad_set_getcaps_function (break_my_data->sinkpad, gst_pad_proxy_getcaps); - - break_my_data->srcpad = gst_pad_new ("src", GST_PAD_SRC); - gst_element_add_pad (GST_ELEMENT (break_my_data), break_my_data->srcpad); - gst_pad_set_link_function (break_my_data->srcpad, gst_pad_proxy_pad_link); - gst_pad_set_getcaps_function (break_my_data->srcpad, gst_pad_proxy_getcaps); -} - -static void -gst_break_my_data_chain (GstPad * pad, GstData * data) -{ - GstBuffer *copy = NULL, *buf = GST_BUFFER (data); - GstBreakMyData *bmd = GST_BREAK_MY_DATA (gst_pad_get_parent (pad)); - guint i, size; - - 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) < bmd->probability) { - guint8 new; - - if (!copy) - copy = gst_buffer_copy_on_write (buf); - 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%2X to 0x%2X", i, - (gint) GST_BUFFER_DATA (copy)[i], (gint) new); - GST_BUFFER_DATA (copy)[i] = new; - } - } - /* don't overflow */ - bmd->skipped += MIN (G_MAXUINT - bmd->skipped, GST_BUFFER_SIZE (buf)); - gst_pad_push (bmd->srcpad, GST_DATA (copy ? copy : buf)); + gst_base_transform_set_in_place (GST_BASE_TRANSFORM (bmd), TRUE); } static void @@ -187,6 +163,8 @@ gst_break_my_data_set_property (GObject * object, guint prop_id, { GstBreakMyData *bmd = GST_BREAK_MY_DATA (object); + GST_LOCK (bmd); + switch (prop_id) { case ARG_SEED: bmd->seed = g_value_get_uint (value); @@ -204,6 +182,8 @@ gst_break_my_data_set_property (GObject * object, guint prop_id, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + GST_UNLOCK (bmd); } static void @@ -212,6 +192,8 @@ gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value, { GstBreakMyData *bmd = GST_BREAK_MY_DATA (object); + GST_LOCK (bmd); + switch (prop_id) { case ARG_SEED: g_value_set_uint (value, bmd->seed); @@ -229,27 +211,80 @@ gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + GST_UNLOCK (bmd); } -static GstStateChangeReturn -gst_break_my_data_change_state (GstElement * element, GstStateChange transition) +static GstFlowReturn +gst_break_my_data_transform_ip (GstBaseTransform * trans, GstBuffer * buf) { - GstBreakMyData *bmd = GST_BREAK_MY_DATA (element); + GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); + guint i, size; - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - bmd->rand = g_rand_new_with_seed (bmd->seed); - bmd->skipped = 0; - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - g_rand_free (bmd->rand); - break; - default: - break; + g_return_val_if_fail (gst_buffer_is_writable (buf), GST_FLOW_ERROR); + + GST_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_UNLOCK (bmd); + + return GST_FLOW_OK; +} - return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state, - (element), GST_STATE_CHANGE_SUCCESS); +static gboolean +gst_break_my_data_start (GstBaseTransform * trans) +{ + GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); + + GST_LOCK (bmd); + bmd->rand = g_rand_new_with_seed (bmd->seed); + bmd->skipped = 0; + GST_UNLOCK (bmd); + + return TRUE; +} + +static gboolean +gst_break_my_data_stop (GstBaseTransform * trans) +{ + GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans); + + GST_LOCK (bmd); + g_rand_free (bmd->rand); + bmd->rand = NULL; + GST_UNLOCK (bmd); + + return TRUE; } gboolean diff --git a/gst/debug/gstdebug.c b/gst/debug/gstdebug.c index 0c5e8fa3..8c64588e 100644 --- a/gst/debug/gstdebug.c +++ b/gst/debug/gstdebug.c @@ -23,20 +23,20 @@ #include <gst/gst.h> - -gboolean gst_break_my_data_plugin_init (GstPlugin * plugin); -gboolean gst_negotiation_plugin_init (GstPlugin * plugin); +gboolean gst_progress_report_plugin_init (GstPlugin * plugin); gboolean gst_navseek_plugin_init (GstPlugin * plugin); -gboolean gst_progressreport_plugin_init (GstPlugin * plugin); gboolean gst_test_plugin_init (GstPlugin * plugin); +gboolean gst_break_my_data_plugin_init (GstPlugin * plugin); + +/* gboolean gst_negotiation_plugin_init (GstPlugin * plugin); */ static gboolean plugin_init (GstPlugin * plugin) { if (!gst_break_my_data_plugin_init (plugin) || - !gst_negotiation_plugin_init (plugin) || !gst_navseek_plugin_init (plugin) || - !gst_progressreport_plugin_init (plugin) || +/* !gst_negotiation_plugin_init (plugin) || */ + !gst_progress_report_plugin_init (plugin) || !gst_test_plugin_init (plugin)) return FALSE; diff --git a/gst/debug/gstnavigationtest.c b/gst/debug/gstnavigationtest.c index 372c3463..de7d5e96 100644 --- a/gst/debug/gstnavigationtest.c +++ b/gst/debug/gstnavigationtest.c @@ -27,24 +27,10 @@ #include "config.h" #endif -/*#define DEBUG_ENABLED */ #include <gstnavigationtest.h> #include <string.h> #include <math.h> -/* GstNavigationtest signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0 - /* FILL ME */ -}; - typedef struct { double x; @@ -61,10 +47,6 @@ static void gst_navigationtest_init (GTypeInstance * instance, static gboolean gst_navigationtest_handle_src_event (GstPad * pad, GstEvent * event); -static void gst_navigationtest_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_navigationtest_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); static GstStateChangeReturn gst_navigationtest_change_state (GstElement * element, @@ -74,7 +56,7 @@ static void gst_navigationtest_planar411 (GstVideofilter * videofilter, void *dest, void *src); static void gst_navigationtest_setup (GstVideofilter * videofilter); -static GstVideofilterClass *parent_class = NULL; +static GstVideofilterClass *parent_class; /* NULL */ GType gst_navigationtest_get_type (void) @@ -130,15 +112,11 @@ gst_navigationtest_base_init (gpointer g_class) static void gst_navigationtest_class_init (gpointer g_class, gpointer class_data) { - GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class); parent_class = g_type_class_peek_parent (g_class); - gobject_class->set_property = gst_navigationtest_set_property; - gobject_class->get_property = gst_navigationtest_get_property; - element_class->change_state = gst_navigationtest_change_state; videofilter_class->setup = gst_navigationtest_setup; @@ -147,67 +125,58 @@ gst_navigationtest_class_init (gpointer g_class, gpointer class_data) static void gst_navigationtest_init (GTypeInstance * instance, gpointer g_class) { - GstNavigationtest *navigationtest = GST_NAVIGATIONTEST (instance); - GstVideofilter *videofilter; - - GST_DEBUG ("gst_navigationtest_init"); - - videofilter = GST_VIDEOFILTER (navigationtest); + GstNavigationtest *navtest = GST_NAVIGATIONTEST (instance); + GstVideofilter *videofilter = GST_VIDEOFILTER (navtest); gst_pad_set_event_function (videofilter->srcpad, - gst_navigationtest_handle_src_event); + GST_DEBUG_FUNCPTR (gst_navigationtest_handle_src_event)); - navigationtest->x = -1; - navigationtest->y = -1; + navtest->x = -1; + navtest->y = -1; } static gboolean gst_navigationtest_handle_src_event (GstPad * pad, GstEvent * event) { - GstNavigationtest *navigationtest; + GstNavigationtest *navtest; const gchar *type; - navigationtest = GST_NAVIGATIONTEST (gst_pad_get_parent (pad)); + navtest = GST_NAVIGATIONTEST (GST_PAD_PARENT (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NAVIGATION: - type = gst_structure_get_string (event->event_data.structure.structure, - "event"); + { + const GstStructure *s = gst_event_get_structure (event); + + type = gst_structure_get_string (s, "event"); if (g_str_equal (type, "mouse-move")) { - gst_structure_get_double (event->event_data.structure.structure, - "pointer_x", &navigationtest->x); - gst_structure_get_double (event->event_data.structure.structure, - "pointer_y", &navigationtest->y); + 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 (event->event_data.structure.structure, - "pointer_x", &click->x); - gst_structure_get_double (event->event_data.structure.structure, - "pointer_y", &click->y); - click->images_left = ceil (GST_VIDEOFILTER (navigationtest)->framerate); + gst_structure_get_double (s, "pointer_x", &click->x); + gst_structure_get_double (s, "pointer_y", &click->y); + click->images_left = ceil (GST_VIDEOFILTER (navtest)->framerate); /* green */ click->cy = 150; click->cu = 46; click->cv = 21; - navigationtest->clicks = - g_slist_prepend (navigationtest->clicks, click); + 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 (event->event_data.structure.structure, - "pointer_x", &click->x); - gst_structure_get_double (event->event_data.structure.structure, - "pointer_y", &click->y); - click->images_left = ceil (GST_VIDEOFILTER (navigationtest)->framerate); + gst_structure_get_double (s, "pointer_x", &click->x); + gst_structure_get_double (s, "pointer_y", &click->y); + click->images_left = ceil (GST_VIDEOFILTER (navtest)->framerate); /* red */ click->cy = 76; click->cu = 85; click->cv = 255; - navigationtest->clicks = - g_slist_prepend (navigationtest->clicks, click); + navtest->clicks = g_slist_prepend (navtest->clicks, click); } break; + } default: break; } @@ -215,64 +184,7 @@ gst_navigationtest_handle_src_event (GstPad * pad, GstEvent * event) } static void -gst_navigationtest_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstNavigationtest *src; - - g_return_if_fail (GST_IS_NAVIGATIONTEST (object)); - src = GST_NAVIGATIONTEST (object); - - GST_DEBUG ("gst_navigationtest_set_property"); - switch (prop_id) { -#if 0 - case ARG_METHOD: - src->method = g_value_get_enum (value); - break; -#endif - default: - break; - } -} - -static void -gst_navigationtest_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstNavigationtest *src; - - g_return_if_fail (GST_IS_NAVIGATIONTEST (object)); - src = GST_NAVIGATIONTEST (object); - - switch (prop_id) { -#if 0 - case ARG_METHOD: - g_value_set_enum (value, src->method); - break; -#endif - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_library_load ("gstvideofilter")) - return FALSE; - - 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, GST_ORIGIN) - - static void gst_navigationtest_setup (GstVideofilter * videofilter) +gst_navigationtest_setup (GstVideofilter * videofilter) { GstNavigationtest *navigationtest; @@ -328,19 +240,20 @@ static void gst_navigationtest_planar411 (GstVideofilter * videofilter, void *dest, void *src) { - GstNavigationtest *navigationtest; - int width = gst_videofilter_get_input_width (videofilter); - int height = gst_videofilter_get_input_height (videofilter); + GstNavigationtest *navtest = (GstNavigationtest *) videofilter; + gint width, height; GSList *walk; g_return_if_fail (GST_IS_NAVIGATIONTEST (videofilter)); - navigationtest = GST_NAVIGATIONTEST (videofilter); + + width = gst_videofilter_get_input_width (videofilter); + height = gst_videofilter_get_input_height (videofilter); /* do something interesting here. This simply copies the source * to the destination. */ memcpy (dest, src, width * height + (width / 2) * (height / 2) * 2); - walk = navigationtest->clicks; + walk = navtest->clicks; while (walk) { ButtonClick *click = walk->data; @@ -348,32 +261,55 @@ gst_navigationtest_planar411 (GstVideofilter * videofilter, draw_box_planar411 (dest, width, height, rint (click->x), rint (click->y), click->cy, click->cu, click->cv); if (--click->images_left < 1) { - navigationtest->clicks = g_slist_remove (navigationtest->clicks, click); + navtest->clicks = g_slist_remove (navtest->clicks, click); g_free (click); } } - draw_box_planar411 (dest, width, height, rint (navigationtest->x), - rint (navigationtest->y), 0, 128, 128); + draw_box_planar411 (dest, width, height, rint (navtest->x), + rint (navtest->y), 0, 128, 128); } static GstStateChangeReturn gst_navigationtest_change_state (GstElement * element, GstStateChange transition) { - GstNavigationtest *navigation = GST_NAVIGATIONTEST (element); + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstNavigationtest *navtest = GST_NAVIGATIONTEST (element); + /* upwards state changes */ switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - while (navigation->clicks) { - g_free (navigation->clicks->data); - navigation->clicks = - g_slist_remove (navigation->clicks, navigation->clicks->data); - } + default: break; } if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - return GST_STATE_CHANGE_SUCCESS; + /* 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 gboolean +plugin_init (GstPlugin * plugin) +{ + 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, GST_ORIGIN) diff --git a/gst/debug/gstnavseek.c b/gst/debug/gstnavseek.c index 6e758347..7fe801b9 100644 --- a/gst/debug/gstnavseek.c +++ b/gst/debug/gstnavseek.c @@ -27,22 +27,14 @@ #include "config.h" #endif -#include <gstnavseek.h> +#include "gstnavseek.h" #include <string.h> #include <math.h> -/* GstNavSeek signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - enum { ARG_0, ARG_SEEKOFFSET - /* FILL ME */ }; GstStaticPadTemplate navseek_src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -55,49 +47,30 @@ GstStaticPadTemplate navseek_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); -static void gst_navseek_base_init (gpointer g_class); -static void gst_navseek_class_init (gpointer g_class, gpointer class_data); -static void gst_navseek_init (GTypeInstance * instance, gpointer g_class); +static GstElementDetails navseek_details = +GST_ELEMENT_DETAILS ("Seek based on left-right arrows", + "Filter/Video", + "Seek based on navigation keys left-right", + "Jan Schmidt <thaytan@mad.scientist.com>"); +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); -static void gst_navseek_chain (GstPad * pad, GstData * _data); -static GType -gst_navseek_get_type (void) -{ - static GType navseek_type = 0; - - if (!navseek_type) { - static const GTypeInfo navseek_info = { - sizeof (GstNavSeekClass), - gst_navseek_base_init, - NULL, - gst_navseek_class_init, - NULL, - NULL, - sizeof (GstNavSeek), - 0, - gst_navseek_init, - }; - - navseek_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstNavSeek", &navseek_info, 0); - } - return navseek_type; -} +GST_BOILERPLATE (GstNavSeek, gst_navseek, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); static void gst_navseek_base_init (gpointer g_class) { - static GstElementDetails navseek_details = - GST_ELEMENT_DETAILS ("Seek based on left-right arrows", - "Filter/Video", - "Seek based on navigation keys left-right", - "Jan Schmidt <thaytan@mad.scientist.com>"); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); gst_element_class_add_pad_template (element_class, @@ -109,43 +82,36 @@ gst_navseek_base_init (gpointer g_class) } static void -gst_navseek_class_init (gpointer g_class, gpointer class_data) +gst_navseek_class_init (GstNavSeekClass * klass) { + GstBaseTransformClass *gstbasetrans_class; GObjectClass *gobject_class; - gobject_class = G_OBJECT_CLASS (g_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 (G_OBJECT_CLASS (g_class), + 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)); - gobject_class->set_property = gst_navseek_set_property; - gobject_class->get_property = gst_navseek_get_property; + 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 (GTypeInstance * instance, gpointer g_class) +gst_navseek_init (GstNavSeek * navseek, GstNavSeekClass * g_class) { - GstNavSeek *navseek = GST_NAVSEEK (instance); - - navseek->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&navseek_sink_template), "sink"); - gst_element_add_pad (GST_ELEMENT (navseek), navseek->sinkpad); - gst_pad_set_chain_function (navseek->sinkpad, gst_navseek_chain); - gst_pad_set_link_function (navseek->sinkpad, gst_pad_proxy_pad_link); - gst_pad_set_getcaps_function (navseek->sinkpad, gst_pad_proxy_getcaps); - - navseek->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&navseek_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (navseek), navseek->srcpad); - gst_pad_set_link_function (navseek->srcpad, gst_pad_proxy_pad_link); - gst_pad_set_getcaps_function (navseek->srcpad, gst_pad_proxy_getcaps); - gst_pad_set_event_function (navseek->srcpad, gst_navseek_handle_src_event); - - GST_FLAG_SET (GST_ELEMENT (navseek), GST_ELEMENT_EVENT_AWARE); + 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; @@ -158,74 +124,90 @@ gst_navseek_init (GTypeInstance * instance, gpointer g_class) static void gst_navseek_seek (GstNavSeek * navseek, gint64 offset) { - /* Query for the current time then attempt to set to time + offset */ - gint64 peer_value; GstFormat peer_format = GST_FORMAT_TIME; + gboolean ret; + GstPad *peer_pad; + gint64 peer_value; - if (gst_pad_query (gst_pad_get_peer (navseek->sinkpad), - GST_QUERY_POSITION, &peer_format, &peer_value)) { - if (peer_format != GST_FORMAT_TIME) - return; + + /* 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, NULL); + + if (ret && peer_format == GST_FORMAT_TIME) { + GstEvent *event; peer_value += offset; if (peer_value < 0) peer_value = 0; - gst_element_seek (GST_ELEMENT (navseek), - GST_SEEK_METHOD_SET | GST_FORMAT_TIME | GST_SEEK_FLAG_ACCURATE | - GST_SEEK_FLAG_FLUSH, peer_value); + 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 (navseek->sinkpad))) { + (!GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad))) { return; } if (navseek->loop) { event = - gst_event_new_segment_seek (GST_SEEK_METHOD_SET | GST_FORMAT_TIME | - GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT_LOOP, - navseek->segment_start, navseek->segment_end); + 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_segment_seek (GST_SEEK_METHOD_SET | GST_FORMAT_TIME | - GST_SEEK_FLAG_ACCURATE, navseek->segment_start, navseek->segment_end); + 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); } - g_return_if_fail (event != NULL); - gst_pad_send_event (gst_pad_get_peer (navseek->sinkpad), event); + 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_get_parent (pad)); + 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 */ { - GstStructure *structure; + const GstStructure *structure; const gchar *event_type; - structure = event->event_data.structure.structure; - event_type = gst_structure_get_string (structure, "event"); + structure = gst_event_get_structure (event); + g_return_val_if_fail (structure != NULL, FALSE); - g_return_val_if_fail (event != 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 char *key = gst_structure_get_string (structure, "key"); + const gchar *key; + + key = gst_structure_get_string (structure, "key"); + g_return_val_if_fail (key != NULL, FALSE); - g_assert (key != NULL); if (strcmp (key, "Left") == 0) { /* Seek backward by 5 secs */ gst_navseek_seek (navseek, -1.0 * navseek->seek_offset * GST_SECOND); @@ -253,26 +235,31 @@ gst_navseek_handle_src_event (GstPad * pad, GstEvent * event) default: break; } - if ((event) && GST_PAD_IS_LINKED (navseek->sinkpad)) { - return gst_pad_send_event (gst_pad_get_peer (navseek->sinkpad), event); + + 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 TRUE; + + return ret; } static void gst_navseek_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstNavSeek *src; - - g_return_if_fail (GST_IS_NAVSEEK (object)); - src = GST_NAVSEEK (object); + GstNavSeek *navseek = GST_NAVSEEK (object); switch (prop_id) { case ARG_SEEKOFFSET: - src->seek_offset = g_value_get_double (value); + GST_LOCK (navseek); + navseek->seek_offset = g_value_get_double (value); + GST_UNLOCK (navseek); break; default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } @@ -281,14 +268,13 @@ static void gst_navseek_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstNavSeek *src; - - g_return_if_fail (GST_IS_NAVSEEK (object)); - src = GST_NAVSEEK (object); + GstNavSeek *navseek = GST_NAVSEEK (object); switch (prop_id) { case ARG_SEEKOFFSET: - g_value_set_double (value, src->seek_offset); + GST_LOCK (navseek); + g_value_set_double (value, navseek->seek_offset); + GST_UNLOCK (navseek); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -296,35 +282,62 @@ gst_navseek_get_property (GObject * object, guint prop_id, } } -static void -gst_navseek_chain (GstPad * pad, GstData * _data) +static gboolean +gst_navseek_event (GstBaseTransform * trans, GstEvent * event) { - GstNavSeek *navseek; + GstNavSeek *navseek = GST_NAVSEEK (trans); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + GST_LOCK (navseek); + if (navseek->loop) + gst_navseek_segseek (navseek); + GST_UNLOCK (navseek); + break; + default: + break; + } + return TRUE; +} + +static GstFlowReturn +gst_navseek_transform_ip (GstBaseTransform * basetrans, GstBuffer * buf) +{ + GstNavSeek *navseek = GST_NAVSEEK (basetrans); - navseek = GST_NAVSEEK (gst_pad_get_parent (pad)); + GST_LOCK (navseek); - if (GST_IS_BUFFER (_data) && - GST_BUFFER_TIMESTAMP_IS_VALID (GST_BUFFER (_data))) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { if (navseek->grab_seg_start) { - navseek->segment_start = GST_BUFFER_TIMESTAMP (GST_BUFFER (_data)); + 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 (GST_BUFFER (_data)); + navseek->segment_end = GST_BUFFER_TIMESTAMP (buf); navseek->grab_seg_end = FALSE; gst_navseek_segseek (navseek); } } - if (GST_IS_EVENT (_data) && - (GST_EVENT_TYPE (GST_EVENT (_data)) == GST_EVENT_SEGMENT_DONE) && - navseek->loop) { - gst_navseek_segseek (navseek); - } + GST_UNLOCK (navseek); + + return GST_FLOW_OK; +} + +static gboolean +gst_navseek_start (GstBaseTransform * trans) +{ + /* anything we should be doing here? */ + return TRUE; +} - gst_pad_push (navseek->srcpad, _data); +static gboolean +gst_navseek_stop (GstBaseTransform * trans) +{ + /* anything we should be doing here? */ + return TRUE; } gboolean diff --git a/gst/debug/gstnavseek.h b/gst/debug/gstnavseek.h index c4eb1bd1..4d124549 100644 --- a/gst/debug/gstnavseek.h +++ b/gst/debug/gstnavseek.h @@ -23,6 +23,7 @@ #include <gst/gst.h> +#include <gst/base/gstbasetransform.h> G_BEGIN_DECLS @@ -41,20 +42,18 @@ typedef struct _GstNavSeek GstNavSeek; typedef struct _GstNavSeekClass GstNavSeekClass; struct _GstNavSeek { - GstElement element; - GstPad *sinkpad; - GstPad *srcpad; - - gdouble seek_offset; - gboolean loop; - gboolean grab_seg_start; - gboolean grab_seg_end; - GstClockTime segment_start; - GstClockTime segment_end; + GstBaseTransform basetransform; + + gdouble seek_offset; + gboolean loop; + gboolean grab_seg_start; + gboolean grab_seg_end; + GstClockTime segment_start; + GstClockTime segment_end; }; struct _GstNavSeekClass { - GstElementClass parent_class; + GstBaseTransformClass parent_class; }; G_END_DECLS diff --git a/gst/debug/progressreport.c b/gst/debug/progressreport.c index 023991cd..82bdb3c1 100644 --- a/gst/debug/progressreport.c +++ b/gst/debug/progressreport.c @@ -24,211 +24,320 @@ #endif #include <gst/gst.h> +#include <gst/base/gstbasetransform.h> #include <string.h> #include <math.h> #include <time.h> -#define GST_TYPE_PROGRESSREPORT \ - (gst_progressreport_get_type()) -#define GST_PROGRESSREPORT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PROGRESSREPORT,GstProgressReport)) -#define GST_PROGRESSREPORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PROGRESSREPORT,GstProgressReportClass)) -#define GST_IS_PROGRESSREPORT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PROGRESSREPORT)) -#define GST_IS_PROGRESSREPORT_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROGRESSREPORT)) +#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(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROGRESS_REPORT)) typedef struct _GstProgressReport GstProgressReport; typedef struct _GstProgressReportClass GstProgressReportClass; struct _GstProgressReport { - GstElement element; - GstPad *sinkpad; - GstPad *srcpad; + GstBaseTransform basetransform; gint update_freq; + gboolean silent; GTimeVal start_time; GTimeVal last_report; }; struct _GstProgressReportClass { - GstElementClass parent_class; -}; - -/* GstProgressReport signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL + GstBaseTransformClass parent_class; }; enum { ARG_0, - ARG_UPDATE_FREQ - /* FILL ME */ + ARG_UPDATE_FREQ, + ARG_SILENT }; -GstStaticPadTemplate progressreport_src_template = +GstStaticPadTemplate progress_report_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); -GstStaticPadTemplate progressreport_sink_template = +GstStaticPadTemplate progress_report_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); -static void gst_progressreport_set_property (GObject * object, guint prop_id, +static GstElementDetails progress_report_details = +GST_ELEMENT_DETAILS ("Progress Report", + "Testing", + "Periodically query and report on processing progress", + "Jan Schmidt <thaytan@mad.scientist.com>"); + +#define DEFAULT_UPDATE_FREQ 5 +#define DEFAULT_SILENT FALSE + +static void gst_progress_report_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_progressreport_get_property (GObject * object, guint prop_id, +static void gst_progress_report_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_progressreport_chain (GstPad * pad, GstData * _data); -GST_BOILERPLATE (GstProgressReport, gst_progressreport, GstElement, - GST_TYPE_ELEMENT); +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_progressreport_base_init (gpointer g_class) +gst_progress_report_base_init (gpointer g_class) { - static GstElementDetails progressreport_details = - GST_ELEMENT_DETAILS ("Progress Report", - "Testing", - "Periodically query and report on processing progress", - "Jan Schmidt <thaytan@mad.scientist.com>"); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&progressreport_sink_template)); + gst_static_pad_template_get (&progress_report_sink_template)); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&progressreport_src_template)); + gst_static_pad_template_get (&progress_report_src_template)); - gst_element_class_set_details (element_class, &progressreport_details); + gst_element_class_set_details (element_class, &progress_report_details); } static void -gst_progressreport_class_init (GstProgressReportClass * g_class) +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->set_property = gst_progress_report_set_property; + gobject_class->get_property = gst_progress_report_get_property; g_object_class_install_property (G_OBJECT_CLASS (g_class), ARG_UPDATE_FREQ, g_param_spec_int ("update-freq", "Update Frequency", "Number of seconds between reports when data is flowing", 1, G_MAXINT, - 5, G_PARAM_READWRITE)); + DEFAULT_UPDATE_FREQ, G_PARAM_READWRITE)); - gobject_class->set_property = gst_progressreport_set_property; - gobject_class->get_property = gst_progressreport_get_property; + g_object_class_install_property (G_OBJECT_CLASS (g_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)); + + 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_progressreport_init (GstProgressReport * instance, +gst_progress_report_init (GstProgressReport * report, GstProgressReportClass * g_class) { - GstProgressReport *progressreport = GST_PROGRESSREPORT (instance); - - progressreport->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&progressreport_sink_template), "sink"); - gst_element_add_pad (GST_ELEMENT (progressreport), progressreport->sinkpad); - gst_pad_set_chain_function (progressreport->sinkpad, - gst_progressreport_chain); - gst_pad_set_link_function (progressreport->sinkpad, gst_pad_proxy_pad_link); - gst_pad_set_getcaps_function (progressreport->sinkpad, gst_pad_proxy_getcaps); - - progressreport->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&progressreport_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (progressreport), progressreport->srcpad); - gst_pad_set_link_function (progressreport->srcpad, gst_pad_proxy_pad_link); - gst_pad_set_getcaps_function (progressreport->srcpad, gst_pad_proxy_getcaps); - - g_get_current_time (&(progressreport->last_report)); - progressreport->start_time = progressreport->last_report; - progressreport->update_freq = 5; + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (report), TRUE); + + report->update_freq = DEFAULT_UPDATE_FREQ; + report->silent = DEFAULT_SILENT; } static void -gst_progressreport_report (GstProgressReport * progressreport, - GTimeVal cur_time) +gst_progress_report_report (GstProgressReport * filter, GTimeVal cur_time) { - /* Query for the current time then attempt to set to time + offset */ + GstFormat try_formats[] = { GST_FORMAT_TIME, GST_FORMAT_BYTES, + GST_FORMAT_PERCENT, GST_FORMAT_BUFFERS, + GST_FORMAT_DEFAULT + }; + GstPad *peer_pad; gint64 cur_progress; gint64 total_progress; - GstFormat peer_format = GST_FORMAT_DEFAULT; - gint hh, mm, ss; - glong run_time = cur_time.tv_sec - progressreport->start_time.tv_sec; + gint hh, mm, ss, i; + glong run_time; + + GST_LOCK (filter); + 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); - if (gst_pad_query (gst_pad_get_peer (progressreport->sinkpad), - GST_QUERY_POSITION, &peer_format, &cur_progress)) { - GstFormat peer_format2 = peer_format; - gchar *format_name = NULL; - gboolean got_total = FALSE; - - if ((gst_pad_query (gst_pad_get_peer (progressreport->sinkpad), - GST_QUERY_TOTAL, &peer_format2, &total_progress)) && - (peer_format == peer_format2)) - got_total = TRUE; - - switch (peer_format) { - case GST_FORMAT_BYTES: - format_name = "bytes"; - break; - case GST_FORMAT_TIME: - format_name = "seconds"; - cur_progress /= GST_SECOND; - total_progress /= GST_SECOND; - break; - case GST_FORMAT_BUFFERS: - format_name = "buffers"; - break; - case GST_FORMAT_PERCENT: - format_name = "percent"; - break; - default: - format_name = "unknown"; - break; + peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (filter)->sinkpad); + /* Query for the current time then attempt to set to time + offset */ + for (i = 0; i < G_N_ELEMENTS (try_formats); ++i) { + const gchar *format_name = NULL; + GstFormat format; + + format = try_formats[i]; + + if (gst_pad_query_position (peer_pad, &format, &cur_progress, + &total_progress)) { + 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_progress /= GST_SECOND; + total_progress /= 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_progress > 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_progress, total_progress, format_name, + (gdouble) cur_progress / total_progress * 100.0); + } else { + g_print ("%s (%02d:%02d:%02d): %" G_GINT64_FORMAT " %s\n", + GST_OBJECT_NAME (filter), hh, mm, ss, cur_progress, format_name); + } + } + break; } + } - if (got_total == TRUE) { - g_print ("%s (%2d:%2d:%2d): %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT - " %s (%3.2g %%)\n", - gst_object_get_name (GST_OBJECT (progressreport)), hh, mm, ss, - cur_progress, total_progress, format_name, - ((gdouble) (cur_progress)) / total_progress * 100); - } else { - g_print ("%s (%2d:%2d:%2d): %" G_GINT64_FORMAT " %s\n", - gst_object_get_name (GST_OBJECT (progressreport)), hh, mm, ss, - cur_progress, format_name); - } - } else { + if (i == G_N_ELEMENTS (try_formats)) { g_print ("%s (%2d:%2d:%2d): Could not query current position.\n", - gst_object_get_name (GST_OBJECT (progressreport)), hh, mm, ss); + GST_OBJECT_NAME (filter), hh, mm, ss); } + + GST_UNLOCK (filter); + + gst_object_unref (peer_pad); +} + +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 TRUE; +} + +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_LOCK (filter); + need_update = + ((cur_time.tv_sec - filter->last_report.tv_sec) >= filter->update_freq); + GST_UNLOCK (filter); + + if (need_update) { + gst_progress_report_report (filter, cur_time); + GST_LOCK (filter); + filter->last_report = cur_time; + GST_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_progressreport_set_property (GObject * object, guint prop_id, +gst_progress_report_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstProgressReport *src; + GstProgressReport *filter; - g_return_if_fail (GST_IS_PROGRESSREPORT (object)); - src = GST_PROGRESSREPORT (object); + filter = GST_PROGRESS_REPORT (object); switch (prop_id) { case ARG_UPDATE_FREQ: - src->update_freq = g_value_get_int (value); + GST_LOCK (filter); + filter->update_freq = g_value_get_int (value); + GST_UNLOCK (filter); + break; + case ARG_SILENT: + GST_LOCK (filter); + filter->silent = g_value_get_boolean (value); + GST_UNLOCK (filter); break; default: break; @@ -236,17 +345,23 @@ gst_progressreport_set_property (GObject * object, guint prop_id, } static void -gst_progressreport_get_property (GObject * object, guint prop_id, +gst_progress_report_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstProgressReport *src; + GstProgressReport *filter; - g_return_if_fail (GST_IS_PROGRESSREPORT (object)); - src = GST_PROGRESSREPORT (object); + filter = GST_PROGRESS_REPORT (object); switch (prop_id) { case ARG_UPDATE_FREQ: - g_value_set_int (value, src->update_freq); + GST_LOCK (filter); + g_value_set_int (value, filter->update_freq); + GST_UNLOCK (filter); + break; + case ARG_SILENT: + GST_LOCK (filter); + g_value_set_boolean (value, filter->silent); + GST_UNLOCK (filter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -254,29 +369,10 @@ gst_progressreport_get_property (GObject * object, guint prop_id, } } -static void -gst_progressreport_chain (GstPad * pad, GstData * _data) -{ - GstProgressReport *progressreport; - GTimeVal cur_time; - - g_get_current_time (&cur_time); - - progressreport = GST_PROGRESSREPORT (gst_pad_get_parent (pad)); - - /* Check if update_freq seconds have passed since the last update */ - if ((cur_time.tv_sec - progressreport->last_report.tv_sec) >= - progressreport->update_freq) { - gst_progressreport_report (progressreport, cur_time); - progressreport->last_report = cur_time; - } - - gst_pad_push (progressreport->srcpad, _data); -} gboolean -gst_progressreport_plugin_init (GstPlugin * plugin, GstPluginClass * g_class) +gst_progress_report_plugin_init (GstPlugin * plugin, GstPluginClass * g_class) { return gst_element_register (plugin, "progressreport", GST_RANK_NONE, - GST_TYPE_PROGRESSREPORT); + GST_TYPE_PROGRESS_REPORT); } diff --git a/gst/debug/testplugin.c b/gst/debug/testplugin.c index 2936a5e4..e5ad0db1 100644 --- a/gst/debug/testplugin.c +++ b/gst/debug/testplugin.c @@ -22,6 +22,7 @@ #endif #include <gst/gst.h> +#include <gst/base/gstbasesink.h> #include "tests.h" GST_DEBUG_CATEGORY_STATIC (gst_test_debug); @@ -48,9 +49,7 @@ typedef struct _GstTestClass GstTestClass; struct _GstTest { - GstElement element; - - GstPad *sinkpad; + GstBaseSink basesink; gpointer tests[TESTS_COUNT]; GValue values[TESTS_COUNT]; @@ -58,50 +57,71 @@ struct _GstTest struct _GstTestClass { - GstElementClass parent_class; + GstBaseSinkClass parent_class; gchar *param_names[2 * TESTS_COUNT]; }; -GST_BOILERPLATE (GstTest, gst_test, GstElement, GST_TYPE_ELEMENT) +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 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 GstElementDetails details = GST_ELEMENT_DETAILS ("gsttestsink", + "Testing", + "perform a number of tests", + "Benjamin Otte <otte@gnome>"); - static void gst_test_chain (GstPad * pad, GstData * _data); +GST_BOILERPLATE (GstTest, gst_test, GstBaseSink, GST_TYPE_BASE_SINK) static void gst_test_base_init (gpointer g_class) { - static GstElementDetails details = GST_ELEMENT_DETAILS ("gsttestsink", - "Testing", - "perform a number of tests", - "Benjamin Otte <otte@gnome>"); 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) { - GObjectClass *object = G_OBJECT_CLASS (klass); + GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); guint i; - object->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property); - object->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property); + object_class->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property); + object_class->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property); 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, 2 * i + 1, 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, 2 * i + 2, 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 @@ -110,13 +130,6 @@ gst_test_init (GstTest * test, GstTestClass * g_class) GstTestClass *klass; guint i; - GST_FLAG_SET (test, GST_ELEMENT_EVENT_AWARE); - - test->sinkpad = gst_pad_new ("sink", GST_PAD_SINK); - gst_element_add_pad (GST_ELEMENT (test), test->sinkpad); - gst_pad_set_chain_function (test->sinkpad, - GST_DEBUG_FUNCPTR (gst_test_chain)); - klass = GST_TEST_GET_CLASS (test); for (i = 0; i < TESTS_COUNT; i++) { GParamSpec *spec = g_object_class_find_property (G_OBJECT_CLASS (klass), @@ -150,61 +163,88 @@ tests_set (GstTest * test) } } -static void -gst_test_chain (GstPad * pad, GstData * data) +static gboolean +gst_test_sink_event (GstBaseSink * basesink, GstEvent * event) { - guint i; - GstTest *test = GST_TEST (gst_pad_get_parent (pad)); - GstTestClass *klass = GST_TEST_GET_CLASS (test); - - if (GST_IS_EVENT (data)) { - GstEvent *event = GST_EVENT (data); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_DISCONTINUOUS: - if (GST_EVENT_DISCONT_NEW_MEDIA (event)) { - tests_unset (test); - tests_set (test); - } - break; - case GST_EVENT_EOS: - 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]); + 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)); - break; - default: - break; + } + g_object_thaw_notify (G_OBJECT (test)); + ret = TRUE; + break; } - gst_pad_event_default (pad, event); - return; + 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], GST_BUFFER (data)); + tests[i].add (test->tests[i], buf); } } - gst_data_unref (data); + 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 @@ -223,7 +263,9 @@ gst_test_set_property (GObject * object, guint prop_id, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } else { /* expected values */ + GST_LOCK (test); g_value_copy (value, &test->values[prop_id / 2 - 1]); + GST_UNLOCK (test); } } @@ -239,6 +281,8 @@ gst_test_get_property (GObject * object, guint prop_id, GValue * value, return; } + GST_LOCK (test); + if (prop_id % 2) { /* real values */ tests[id].get_value (test->tests[id], value); @@ -246,6 +290,8 @@ gst_test_get_property (GObject * object, guint prop_id, GValue * value, /* expected values */ g_value_copy (&test->values[id], value); } + + GST_UNLOCK (test); } gboolean |