From bb1be5f5090e1143296a76a3e012ccbcd38a214f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 29 Mar 2005 16:18:12 +0000 Subject: [PATCH] gst/: Simplify pad activation. Original commit message from CVS: * gst/base/Makefile.am: * gst/base/README: * gst/base/gstbasesink.c: (gst_basesink_get_type), (gst_basesink_base_init), (gst_basesink_class_init), (gst_basesink_pad_getcaps), (gst_basesink_init), (gst_basesink_activate), (gst_basesink_change_state): * gst/base/gstbasesink.h: * gst/base/gstbasetransform.c: (gst_base_transform_get_type), (gst_base_transform_base_init), (gst_base_transform_finalize), (gst_base_transform_class_init), (gst_base_transform_init), (gst_base_transform_proxy_getcaps), (gst_base_transform_setcaps), (gst_base_transform_event), (gst_base_transform_getrange), (gst_base_transform_chain), (gst_base_transform_handle_buffer), (gst_base_transform_set_property), (gst_base_transform_get_property), (gst_base_transform_sink_activate), (gst_base_transform_src_activate), (gst_base_transform_change_state): * gst/base/gstbasetransform.h: * gst/elements/gstidentity.c: (gst_identity_finalize), (gst_identity_class_init), (gst_identity_init), (gst_identity_event), (gst_identity_check_perfect), (gst_identity_transform), (gst_identity_set_property), (gst_identity_get_property), (gst_identity_change_state): * gst/elements/gstidentity.h: * gst/gstelement.c: (gst_element_get_state_func), (gst_element_lost_state), (gst_element_pads_activate): * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), (gst_pad_check_pull_range), (gst_pad_pull_range): * gst/gstpad.h: Simplify pad activation. Added function to check if pull_range can be performed. Error out when pulling inactive or flushing pads. Removed const from refcounted types as it does not make sense. Simplify pad templates in basesink Added base class for simple 1-to-1 transforms. Make identity subclass the base transform. --- ChangeLog | 40 ++++ gst/base/Makefile.am | 6 +- gst/base/README | 11 + gst/base/gstbasesink.c | 100 +++++---- gst/base/gstbasesink.h | 2 - gst/base/gstbasetransform.c | 404 +++++++++++++++++++++++++++++++++++ gst/base/gstbasetransform.h | 67 ++++++ gst/elements/gstidentity.c | 446 +++++++-------------------------------- gst/elements/gstidentity.h | 26 +-- gst/gstelement.c | 34 +-- gst/gstpad.c | 176 +++++++++++++-- gst/gstpad.h | 13 +- libs/gst/base/Makefile.am | 6 +- libs/gst/base/README | 11 + libs/gst/base/gstbasesink.c | 100 +++++---- libs/gst/base/gstbasesink.h | 2 - libs/gst/base/gstbasetransform.c | 404 +++++++++++++++++++++++++++++++++++ libs/gst/base/gstbasetransform.h | 67 ++++++ plugins/elements/gstidentity.c | 446 +++++++-------------------------------- plugins/elements/gstidentity.h | 26 +-- 20 files changed, 1441 insertions(+), 946 deletions(-) create mode 100644 gst/base/gstbasetransform.c create mode 100644 gst/base/gstbasetransform.h create mode 100644 libs/gst/base/gstbasetransform.c create mode 100644 libs/gst/base/gstbasetransform.h diff --git a/ChangeLog b/ChangeLog index 3a0a2ae..040875e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2005-03-29 Wim Taymans + + * gst/base/Makefile.am: + * gst/base/README: + * gst/base/gstbasesink.c: (gst_basesink_get_type), + (gst_basesink_base_init), (gst_basesink_class_init), + (gst_basesink_pad_getcaps), (gst_basesink_init), + (gst_basesink_activate), (gst_basesink_change_state): + * gst/base/gstbasesink.h: + * gst/base/gstbasetransform.c: (gst_base_transform_get_type), + (gst_base_transform_base_init), (gst_base_transform_finalize), + (gst_base_transform_class_init), (gst_base_transform_init), + (gst_base_transform_proxy_getcaps), (gst_base_transform_setcaps), + (gst_base_transform_event), (gst_base_transform_getrange), + (gst_base_transform_chain), (gst_base_transform_handle_buffer), + (gst_base_transform_set_property), + (gst_base_transform_get_property), + (gst_base_transform_sink_activate), + (gst_base_transform_src_activate), + (gst_base_transform_change_state): + * gst/base/gstbasetransform.h: + * gst/elements/gstidentity.c: (gst_identity_finalize), + (gst_identity_class_init), (gst_identity_init), + (gst_identity_event), (gst_identity_check_perfect), + (gst_identity_transform), (gst_identity_set_property), + (gst_identity_get_property), (gst_identity_change_state): + * gst/elements/gstidentity.h: + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_lost_state), (gst_element_pads_activate): + * gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active), + (gst_pad_check_pull_range), (gst_pad_pull_range): + * gst/gstpad.h: + Simplify pad activation. + Added function to check if pull_range can be performed. + Error out when pulling inactive or flushing pads. + Removed const from refcounted types as it does not make sense. + Simplify pad templates in basesink + Added base class for simple 1-to-1 transforms. + Make identity subclass the base transform. + 2005-03-29 Andy Wingo * docs/libs/gstreamer-libs-overrides.txt: diff --git a/gst/base/Makefile.am b/gst/base/Makefile.am index 8ba1b85..dda7031 100644 --- a/gst/base/Makefile.am +++ b/gst/base/Makefile.am @@ -6,7 +6,8 @@ noinst_DATA = $(as_libtool_noinst_DATA_files) libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = ../libgstreamer-@GST_MAJORMINOR@.la libgstbase_@GST_MAJORMINOR@_la_SOURCES = \ - gstbasesink.c + gstbasesink.c \ + gstbasetransform.c libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstbase_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) @@ -16,7 +17,8 @@ libgstbase_@GST_MAJORMINOR@includedir = \ $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/base libgstbase_@GST_MAJORMINOR@include_HEADERS = \ - gstbasesink.h + gstbasesink.h \ + gstbasetransform.h install-data-local: as-libtool-install-data-local diff --git a/gst/base/README b/gst/base/README index efd6e57..f9c1583 100644 --- a/gst/base/README +++ b/gst/base/README @@ -14,3 +14,14 @@ GstBaseSink FIXME: not much point making it operate in pull mode as a generic base class I guess... + +GstBaseTransform + + Base class for simple tranform filters + + - one sinkpad and one srcpad + - formats the same on sink and source pad. + - handles state changes + - does flushing + - push mode + - pull mode if transform can operate on arbitrary data diff --git a/gst/base/gstbasesink.c b/gst/base/gstbasesink.c index a476071..88d7d97 100644 --- a/gst/base/gstbasesink.c +++ b/gst/base/gstbasesink.c @@ -26,11 +26,6 @@ #include "gstbasesink.h" #include -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - GST_DEBUG_CATEGORY_STATIC (gst_basesink_debug); #define GST_CAT_DEFAULT gst_basesink_debug @@ -61,11 +56,35 @@ enum PROP_PREROLL_QUEUE_LEN }; -#define _do_init(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_basesink_debug, "basesink", 0, "basesink element"); +static GstElementClass *parent_class = NULL; + +static void gst_basesink_base_init (gpointer g_class); +static void gst_basesink_class_init (GstBaseSinkClass * klass); +static void gst_basesink_init (GstBaseSink * trans, gpointer g_class); + +GType +gst_basesink_get_type (void) +{ + static GType basesink_type = 0; + + if (!basesink_type) { + static const GTypeInfo basesink_info = { + sizeof (GstBaseSinkClass), + (GBaseInitFunc) gst_basesink_base_init, + NULL, + (GClassInitFunc) gst_basesink_class_init, + NULL, + NULL, + sizeof (GstBaseSink), + 0, + (GInstanceInitFunc) gst_basesink_init, + }; -GST_BOILERPLATE_FULL (GstBaseSink, gst_basesink, GstElement, GST_TYPE_ELEMENT, - _do_init); + basesink_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseSink", &basesink_info, G_TYPE_FLAG_ABSTRACT); + } + return basesink_type; +} static void gst_basesink_set_clock (GstElement * element, GstClock * clock); @@ -74,7 +93,6 @@ static void gst_basesink_set_property (GObject * object, guint prop_id, static void gst_basesink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstStaticPadTemplate *gst_base_sink_get_template (GstBaseSink * sink); static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink); static gboolean gst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps); static GstBuffer *gst_base_sink_buffer_alloc (GstBaseSink * sink, @@ -93,32 +111,11 @@ static gboolean gst_basesink_event (GstPad * pad, GstEvent * event); static inline void gst_basesink_handle_buffer (GstBaseSink * basesink, GstBuffer * buf); -static GstStaticPadTemplate * -gst_basesink_get_template (GstBaseSink * bsink) -{ - GstStaticPadTemplate *template = NULL; - GstBaseSinkClass *bclass; - - bclass = GST_BASESINK_GET_CLASS (bsink); - - if (bclass->get_template) - template = bclass->get_template (bsink); - - if (template == NULL) { - template = &sinktemplate; - } - return template; -} - static void gst_basesink_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_DEBUG_CATEGORY_INIT (gst_basesink_debug, "basesink", 0, + "basesink element"); } static void @@ -130,6 +127,8 @@ gst_basesink_class_init (GstBaseSinkClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_basesink_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_basesink_get_property); @@ -153,7 +152,6 @@ gst_basesink_class_init (GstBaseSinkClass * klass) klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_sink_get_caps); klass->set_caps = GST_DEBUG_FUNCPTR (gst_base_sink_set_caps); - klass->get_template = GST_DEBUG_FUNCPTR (gst_base_sink_get_template); klass->buffer_alloc = GST_DEBUG_FUNCPTR (gst_base_sink_buffer_alloc); klass->get_times = GST_DEBUG_FUNCPTR (gst_basesink_get_times); } @@ -171,13 +169,15 @@ gst_basesink_pad_getcaps (GstPad * pad) caps = bclass->get_caps (bsink); if (caps == NULL) { - GstStaticPadTemplate *stemplate; - GstPadTemplate *template; + GstPadTemplate *pad_template; - stemplate = gst_basesink_get_template (bsink); - template = gst_static_pad_template_get (stemplate); - caps = gst_caps_copy (gst_pad_template_get_caps (template)); + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink"); + if (pad_template != NULL) { + caps = gst_caps_ref (gst_pad_template_get_caps (pad_template)); + } } + return caps; } @@ -213,15 +213,16 @@ gst_basesink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size, } static void -gst_basesink_init (GstBaseSink * basesink) +gst_basesink_init (GstBaseSink * basesink, gpointer g_class) { - GstStaticPadTemplate *template; + GstPadTemplate *pad_template; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); + g_return_if_fail (pad_template != NULL); - template = gst_basesink_get_template (basesink); + basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink"); - basesink->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get (template), - "sink"); gst_pad_set_getcaps_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_basesink_pad_getcaps)); gst_pad_set_setcaps_function (basesink->sinkpad, @@ -328,12 +329,6 @@ gst_basesink_get_property (GObject * object, guint prop_id, GValue * value, GST_UNLOCK (sink); } -static GstStaticPadTemplate * -gst_base_sink_get_template (GstBaseSink * sink) -{ - return &sinktemplate; -} - static GstCaps * gst_base_sink_get_caps (GstBaseSink * sink) { @@ -735,6 +730,7 @@ gst_basesink_activate (GstPad * pad, GstActivateMode mode) case GST_ACTIVATE_PULL: /* if we have a scheduler we can start the task */ g_return_val_if_fail (basesink->has_loop, FALSE); + gst_pad_peer_set_active (pad, mode); if (GST_ELEMENT_SCHEDULER (basesink)) { GST_STREAM_LOCK (pad); GST_RPAD_TASK (pad) = @@ -791,7 +787,7 @@ gst_basesink_change_state (GstElement * element) break; case GST_STATE_READY_TO_PAUSED: /* need to complete preroll before this state change completes, there - * is no data flow in READY so we cqn safely assume we need to preroll. */ + * is no data flow in READY so we can safely assume we need to preroll. */ basesink->offset = 0; GST_PREROLL_LOCK (basesink->sinkpad); basesink->preroll_queue = g_queue_new (); diff --git a/gst/base/gstbasesink.h b/gst/base/gstbasesink.h index 3c64f78..b3eafad 100644 --- a/gst/base/gstbasesink.h +++ b/gst/base/gstbasesink.h @@ -66,8 +66,6 @@ struct _GstBaseSink { struct _GstBaseSinkClass { GstElementClass parent_class; - GstStaticPadTemplate* (*get_template) (GstBaseSink *sink); - GstCaps* (*get_caps) (GstBaseSink *sink); gboolean (*set_caps) (GstBaseSink *sink, GstCaps *caps); diff --git a/gst/base/gstbasetransform.c b/gst/base/gstbasetransform.c new file mode 100644 index 0000000..c6032d6 --- /dev/null +++ b/gst/base/gstbasetransform.c @@ -0,0 +1,404 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstbasetransform.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. + */ + + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "../gst-i18n-lib.h" +#include "gstbasetransform.h" +#include + +GST_DEBUG_CATEGORY_STATIC (gst_base_transform_debug); +#define GST_CAT_DEFAULT gst_base_transform_debug + +/* BaseTransform signals and args */ +enum +{ + SIGNAL_HANDOFF, + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, +}; + +static GstElementClass *parent_class = NULL; + +static void gst_base_transform_base_init (gpointer g_class); +static void gst_base_transform_class_init (GstBaseTransformClass * klass); +static void gst_base_transform_init (GstBaseTransform * trans, + gpointer g_class); + +GType +gst_base_transform_get_type (void) +{ + static GType base_transform_type = 0; + + if (!base_transform_type) { + static const GTypeInfo base_transform_info = { + sizeof (GstBaseTransformClass), + (GBaseInitFunc) gst_base_transform_base_init, + NULL, + (GClassInitFunc) gst_base_transform_class_init, + NULL, + NULL, + sizeof (GstBaseTransform), + 0, + (GInstanceInitFunc) gst_base_transform_init, + }; + + base_transform_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT); + } + return base_transform_type; +} + +static void gst_base_transform_finalize (GObject * object); +static void gst_base_transform_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_transform_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static gboolean gst_base_transform_src_activate (GstPad * pad, + GstActivateMode mode); +static gboolean gst_base_transform_sink_activate (GstPad * pad, + GstActivateMode mode); +static GstElementStateReturn gst_base_transform_change_state (GstElement * + element); + +static gboolean gst_base_transform_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buffer); +static GstFlowReturn gst_base_transform_chain (GstPad * pad, + GstBuffer * buffer); +static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer ** outbuf); +static GstCaps *gst_base_transform_proxy_getcaps (GstPad * pad); +static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps); + +/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */ + +static void +gst_base_transform_base_init (gpointer g_class) +{ + GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0, + "basetransform element"); +} + +static void +gst_base_transform_finalize (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_base_transform_class_init (GstBaseTransformClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_base_transform_set_property); + gobject_class->get_property = + GST_DEBUG_FUNCPTR (gst_base_transform_get_property); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_transform_finalize); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_transform_change_state); +} + +static void +gst_base_transform_init (GstBaseTransform * trans, gpointer g_class) +{ + GstPadTemplate *pad_template; + + GST_DEBUG ("gst_base_transform_init"); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); + g_return_if_fail (pad_template != NULL); + trans->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + gst_pad_set_getcaps_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps)); + gst_pad_set_setcaps_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_setcaps)); + gst_pad_set_event_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_event)); + gst_pad_set_chain_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_chain)); + gst_pad_set_activate_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate)); + gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + g_return_if_fail (pad_template != NULL); + trans->srcpad = gst_pad_new_from_template (pad_template, "src"); + gst_pad_set_getcaps_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps)); + gst_pad_set_getrange_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_getrange)); + gst_pad_set_activate_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_src_activate)); + gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad); +} + +static GstCaps * +gst_base_transform_proxy_getcaps (GstPad * pad) +{ + GstPad *otherpad; + GstBaseTransform *trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad)); + + otherpad = pad == trans->srcpad ? trans->sinkpad : trans->srcpad; + + return gst_pad_peer_get_caps (otherpad); +} + +static gboolean +gst_base_transform_setcaps (GstPad * pad, GstCaps * caps) +{ + GstBaseTransform *trans; + GstBaseTransformClass *bclass; + gboolean result = TRUE; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (bclass->set_caps) + result = bclass->set_caps (trans, caps); + + return result; +} + +static gboolean +gst_base_transform_event (GstPad * pad, GstEvent * event) +{ + GstBaseTransform *trans; + GstBaseTransformClass *bclass; + gboolean ret = FALSE; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (bclass->event) + bclass->event (trans, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH: + if (GST_EVENT_FLUSH_DONE (event)) { + } + GST_STREAM_LOCK (pad); + break; + case GST_EVENT_EOS: + GST_STREAM_LOCK (pad); + break; + default: + break; + } + ret = gst_pad_event_default (pad, event); + GST_STREAM_UNLOCK (pad); + + return ret; +} + +static GstFlowReturn +gst_base_transform_getrange (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstBaseTransform *trans; + GstFlowReturn ret; + GstBuffer *inbuf; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + + GST_STREAM_LOCK (pad); + + ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf); + if (ret == GST_FLOW_OK) { + ret = gst_base_transform_handle_buffer (trans, inbuf, buffer); + } + + GST_STREAM_UNLOCK (pad); + + return ret; +} + +static GstFlowReturn +gst_base_transform_chain (GstPad * pad, GstBuffer * buffer) +{ + GstBaseTransform *trans; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + + GST_STREAM_LOCK (pad); + + ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf); + if (ret == GST_FLOW_OK) { + ret = gst_pad_push (trans->srcpad, outbuf); + } + + GST_STREAM_UNLOCK (pad); + + return ret; +} + +static GstFlowReturn +gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer ** outbuf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstBaseTransformClass *bclass; + + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + if (bclass->transform) + ret = bclass->transform (trans, inbuf, outbuf); + + gst_buffer_unref (inbuf); + + return ret; +} + +static void +gst_base_transform_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_transform_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_base_transform_sink_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result = FALSE; + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + result = TRUE; + break; + case GST_ACTIVATE_PULL: + result = TRUE; + break; + case GST_ACTIVATE_NONE: + result = TRUE; + break; + } + return result; +} + +static gboolean +gst_base_transform_src_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result = FALSE; + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + result = TRUE; + break; + case GST_ACTIVATE_PULL: + result = gst_pad_set_active (trans->sinkpad, mode); + result = gst_pad_peer_set_active (trans->sinkpad, mode); + break; + case GST_ACTIVATE_NONE: + result = TRUE; + break; + } + return result; +} + +static GstElementStateReturn +gst_base_transform_change_state (GstElement * element) +{ + GstBaseTransform *trans; + GstElementState transition; + GstElementStateReturn result; + + trans = GST_BASE_TRANSFORM (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_PLAYING_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_READY: + break; + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + + return result; +} diff --git a/gst/base/gstbasetransform.h b/gst/base/gstbasetransform.h new file mode 100644 index 0000000..788fe53 --- /dev/null +++ b/gst/base/gstbasetransform.h @@ -0,0 +1,67 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstbasetransform.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_BASE_TRANSFORM_H__ +#define __GST_BASE_TRANSFORM_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_TRANSFORM (gst_base_transform_get_type()) +#define GST_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransform)) +#define GST_BASE_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass)) +#define GST_BASE_TRANSFORM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass)) +#define GST_IS_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_TRANSFORM)) +#define GST_IS_BASE_TRANSFORM_CLASS(obj)(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_TRANSFORM)) + +/* the names of the templates for the sink and source pads */ +#define GST_BASE_TRANSFORM_SINK_NAME "sink" +#define GST_BASE_TRANSFORM_SRC_NAME "src" + +typedef struct _GstBaseTransform GstBaseTransform; +typedef struct _GstBaseTransformClass GstBaseTransformClass; + +struct _GstBaseTransform { + GstElement element; + + /* source and sink pads */ + GstPad *sinkpad; + GstPad *srcpad; +}; + +struct _GstBaseTransformClass { + GstElementClass parent_class; + + gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *caps); + + gboolean (*event) (GstBaseTransform *trans, GstEvent *event); + GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer **outbuf); +}; + +GType gst_base_transform_get_type(void); + +G_END_DECLS + +#endif /* __GST_BASE_TRANSFORM_H__ */ diff --git a/gst/elements/gstidentity.c b/gst/elements/gstidentity.c index 0b8a6d2..76a61f7 100644 --- a/gst/elements/gstidentity.c +++ b/gst/elements/gstidentity.c @@ -59,7 +59,6 @@ enum LAST_SIGNAL }; -#define DEFAULT_LOOP_BASED FALSE #define DEFAULT_SLEEP_TIME 0 #define DEFAULT_DUPLICATE 1 #define DEFAULT_ERROR_AFTER -1 @@ -73,11 +72,6 @@ enum enum { PROP_0, - PROP_HAS_GETRANGE, - PROP_HAS_CHAIN, - PROP_HAS_SINK_LOOP, - PROP_HAS_SRC_LOOP, - PROP_LOOP_BASED, PROP_SLEEP_TIME, PROP_DUPLICATE, PROP_ERROR_AFTER, @@ -91,14 +85,11 @@ enum }; -typedef GstFlowReturn (*IdentityPushFunc) (GstIdentity *, GstBuffer *); - - #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element"); -GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstElement, GST_TYPE_ELEMENT, - _do_init); +GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, _do_init); static void gst_identity_finalize (GObject * object); static void gst_identity_set_property (GObject * object, guint prop_id, @@ -107,17 +98,9 @@ static void gst_identity_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstElementStateReturn gst_identity_change_state (GstElement * element); -static gboolean gst_identity_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_identity_getrange (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer); -static GstFlowReturn gst_identity_chain (GstPad * pad, GstBuffer * buffer); -static void gst_identity_src_loop (GstPad * pad); -static void gst_identity_sink_loop (GstPad * pad); -static GstFlowReturn gst_identity_handle_buffer (GstIdentity * identity, - GstBuffer * buf); -static void gst_identity_set_clock (GstElement * element, GstClock * clock); -static GstCaps *gst_identity_proxy_getcaps (GstPad * pad); - +static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event); +static GstFlowReturn gst_identity_transform (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer ** outbuf); static guint gst_identity_signals[LAST_SIGNAL] = { 0 }; @@ -140,9 +123,6 @@ gst_identity_finalize (GObject * object) identity = GST_IDENTITY (object); - g_mutex_free (identity->pen_lock); - g_cond_free (identity->pen_cond); - g_free (identity->last_message); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -153,29 +133,15 @@ gst_identity_class_init (GstIdentityClass * 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_identity_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_GETRANGE, - g_param_spec_boolean ("has-getrange", "Has getrange", - "If the src pad will implement a getrange function", - TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_CHAIN, - g_param_spec_boolean ("has-chain", "Has chain", - "If the sink pad will implement a chain function", - TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_SRC_LOOP, - g_param_spec_boolean ("has-src-loop", "Has src loop", - "If the src pad will implement a loop function", - FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_SINK_LOOP, - g_param_spec_boolean ("has-sink-loop", "Has sink loop", - "If the sink pad will implement a loop function", - FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SLEEP_TIME, g_param_spec_uint ("sleep-time", "Sleep time", "Microseconds to sleep between processing", 0, G_MAXUINT, @@ -220,33 +186,16 @@ gst_identity_class_init (GstIdentityClass * klass) gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_identity_finalize); - gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_identity_set_clock); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_identity_change_state); + gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_identity_event); + gstbasetrans_class->transform = GST_DEBUG_FUNCPTR (gst_identity_transform); } static void gst_identity_init (GstIdentity * identity) { - identity->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate), - "sink"); - gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad); - gst_pad_set_getcaps_function (identity->sinkpad, - GST_DEBUG_FUNCPTR (gst_identity_proxy_getcaps)); - gst_pad_set_event_function (identity->sinkpad, - GST_DEBUG_FUNCPTR (gst_identity_event)); - - identity->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate), - "src"); - gst_pad_set_getcaps_function (identity->srcpad, - GST_DEBUG_FUNCPTR (gst_identity_proxy_getcaps)); - gst_pad_set_getrange_function (identity->srcpad, - GST_DEBUG_FUNCPTR (gst_identity_getrange)); - gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad); - identity->sleep_time = DEFAULT_SLEEP_TIME; identity->duplicate = DEFAULT_DUPLICATE; identity->error_after = DEFAULT_ERROR_AFTER; @@ -257,279 +206,78 @@ gst_identity_init (GstIdentity * identity) identity->check_perfect = DEFAULT_CHECK_PERFECT; identity->dump = DEFAULT_DUMP; identity->last_message = NULL; - identity->srccaps = NULL; - - identity->pen_data = NULL; - identity->pen_lock = g_mutex_new (); - identity->pen_cond = g_cond_new (); - identity->pen_flushing = FALSE; -} - -static void -gst_identity_set_clock (GstElement * element, GstClock * clock) -{ - GstIdentity *identity = GST_IDENTITY (element); - - gst_object_replace ((GstObject **) & identity->clock, (GstObject *) clock); -} - -static GstCaps * -gst_identity_proxy_getcaps (GstPad * pad) -{ - GstPad *otherpad; - GstIdentity *identity = GST_IDENTITY (GST_OBJECT_PARENT (pad)); - - otherpad = pad == identity->srcpad ? identity->sinkpad : identity->srcpad; - - return gst_pad_peer_get_caps (otherpad); -} - -static gboolean -identity_queue_push (GstIdentity * identity, GstData * data) -{ - gboolean ret; - - g_mutex_lock (identity->pen_lock); - while (identity->pen_data && !identity->pen_flushing) - g_cond_wait (identity->pen_cond, identity->pen_lock); - if (identity->pen_flushing) { - gst_data_unref (identity->pen_data); - identity->pen_data = NULL; - gst_data_unref (data); - ret = FALSE; - } else { - identity->pen_data = data; - ret = TRUE; - } - g_cond_signal (identity->pen_cond); - g_mutex_unlock (identity->pen_lock); - - return ret; -} - -static GstData * -identity_queue_pop (GstIdentity * identity) -{ - GstData *ret; - - g_mutex_lock (identity->pen_lock); - while (!(ret = identity->pen_data) && !identity->pen_flushing) - g_cond_wait (identity->pen_cond, identity->pen_lock); - g_cond_signal (identity->pen_cond); - g_mutex_unlock (identity->pen_lock); - - return ret; -} - -static void -identity_queue_flush (GstIdentity * identity) -{ - g_mutex_lock (identity->pen_lock); - identity->pen_flushing = TRUE; - g_cond_signal (identity->pen_cond); - g_mutex_unlock (identity->pen_lock); } static gboolean -gst_identity_event (GstPad * pad, GstEvent * event) +gst_identity_event (GstBaseTransform * trans, GstEvent * event) { GstIdentity *identity; - gboolean ret; - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); + identity = GST_IDENTITY (trans); if (!identity->silent) { g_free (identity->last_message); identity->last_message = g_strdup_printf ("chain ******* (%s:%s)E (type: %d) %p", - GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE (event), event); + GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), event); g_object_notify (G_OBJECT (identity), "last_message"); } - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH: - /* forward event */ - gst_pad_event_default (pad, event); - if (GST_EVENT_FLUSH_DONE (event)) { - if (identity->sink_mode == GST_ACTIVATE_PULL) { - /* already have the sink stream lock */ - gst_task_start (GST_RPAD_TASK (identity->sinkpad)); - } - if (identity->src_mode == GST_ACTIVATE_PUSH) { - GST_STREAM_LOCK (identity->srcpad); - gst_task_start (GST_RPAD_TASK (identity->srcpad)); - GST_STREAM_UNLOCK (identity->srcpad); - } - } else { - /* unblock both functions */ - identity_queue_flush (identity); - - } - ret = TRUE; - goto done; - case GST_EVENT_EOS: - if (identity->sink_mode == GST_ACTIVATE_PULL) { - /* already have the sink stream lock */ - gst_task_pause (GST_RPAD_TASK (identity->sinkpad)); - } - break; - default: - break; - } - - if (identity->decoupled) { - ret = identity_queue_push (identity, (GstData *) event); - } else { - ret = gst_pad_push_event (identity->srcpad, event); - } - -done: - GST_STREAM_UNLOCK (pad); - return ret; -} - -static GstFlowReturn -gst_identity_getrange (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer) -{ - GstIdentity *identity; - GstFlowReturn ret; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - ret = gst_pad_pull_range (identity->sinkpad, offset, length, buffer); - - GST_STREAM_UNLOCK (pad); - - return ret; -} - -static GstFlowReturn -gst_identity_chain (GstPad * pad, GstBuffer * buffer) -{ - GstIdentity *identity; - GstFlowReturn ret = GST_FLOW_OK; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - ret = gst_identity_handle_buffer (identity, buffer); - - GST_STREAM_UNLOCK (pad); - - return ret; + return TRUE; } -#define DEFAULT_PULL_SIZE 1024 - static void -gst_identity_sink_loop (GstPad * pad) +gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf) { - GstIdentity *identity; - GstBuffer *buffer; - GstFlowReturn ret; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - ret = gst_pad_pull_range (pad, identity->offset, DEFAULT_PULL_SIZE, &buffer); - if (ret != GST_FLOW_OK) - goto sink_loop_pause; - - ret = gst_identity_handle_buffer (identity, buffer); - if (ret != GST_FLOW_OK) - goto sink_loop_pause; - - GST_STREAM_UNLOCK (pad); - return; - -sink_loop_pause: - gst_task_pause (GST_RPAD_TASK (identity->sinkpad)); - GST_STREAM_UNLOCK (pad); - return; -} + GstClockTime timestamp; -static void -gst_identity_src_loop (GstPad * pad) -{ - GstIdentity *identity; - GstData *data; - GstFlowReturn ret; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - data = identity_queue_pop (identity); - if (!data) /* we're getting flushed */ - goto src_loop_pause; - - if (GST_IS_EVENT (data)) { - if (GST_EVENT_TYPE (data) == GST_EVENT_EOS) - gst_task_pause (GST_RPAD_TASK (identity->srcpad)); - gst_pad_push_event (identity->srcpad, GST_EVENT (data)); - } else { - ret = gst_pad_push (identity->srcpad, (GstBuffer *) data); - if (ret != GST_FLOW_OK) - goto src_loop_pause; - } - - GST_STREAM_UNLOCK (pad); - return; - -src_loop_pause: - gst_task_pause (GST_RPAD_TASK (identity->srcpad)); - GST_STREAM_UNLOCK (pad); - return; -} - -static GstFlowReturn -gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) -{ - GstFlowReturn ret = GST_FLOW_OK; - guint i; + timestamp = GST_BUFFER_TIMESTAMP (buf); /* see if we need to do perfect stream checking */ /* invalid timestamp drops us out of check. FIXME: maybe warn ? */ - if (identity->check_perfect && - GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { + if (timestamp != GST_CLOCK_TIME_NONE) { /* check if we had a previous buffer to compare to */ if (identity->prev_timestamp != GST_CLOCK_TIME_NONE) { - if (identity->prev_timestamp + identity->prev_duration != - GST_BUFFER_TIMESTAMP (buf)) { + guint64 offset; + + if (identity->prev_timestamp + identity->prev_duration != timestamp) { GST_WARNING_OBJECT (identity, "Buffer not time-contiguous with previous one: " "prev ts %" GST_TIME_FORMAT ", prev dur %" GST_TIME_FORMAT ", new ts %" GST_TIME_FORMAT, GST_TIME_ARGS (identity->prev_timestamp), - GST_TIME_ARGS (identity->prev_duration), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + GST_TIME_ARGS (identity->prev_duration), GST_TIME_ARGS (timestamp)); } - if (identity->prev_offset_end != GST_BUFFER_OFFSET (buf)) { + + offset = GST_BUFFER_OFFSET (buf); + if (identity->prev_offset_end != offset) { GST_WARNING_OBJECT (identity, "Buffer not data-contiguous with previous one: " "prev offset_end %" G_GINT64_FORMAT ", new offset %" - G_GINT64_FORMAT, identity->prev_offset_end, - GST_BUFFER_OFFSET (buf)); + G_GINT64_FORMAT, identity->prev_offset_end, offset); } } /* update prev values */ - identity->prev_timestamp = GST_BUFFER_TIMESTAMP (buf); + identity->prev_timestamp = timestamp; identity->prev_duration = GST_BUFFER_DURATION (buf); identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf); } +} + +static GstFlowReturn +gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer ** outbuf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstIdentity *identity = GST_IDENTITY (trans); + guint i; + + if (identity->check_perfect) + gst_identity_check_perfect (identity, inbuf); if (identity->error_after >= 0) { identity->error_after--; if (identity->error_after == 0) { - gst_buffer_unref (buf); GST_ELEMENT_ERROR (identity, CORE, FAILED, (_("Failed after iterations as requested.")), (NULL)); return GST_FLOW_ERROR; @@ -543,18 +291,18 @@ gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) g_strdup_printf ("dropping ******* (%s:%s)i (%d bytes, timestamp: %" GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %" G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", - GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf); + GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)), + GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf), + GST_BUFFER_FLAGS (inbuf), inbuf); g_object_notify (G_OBJECT (identity), "last-message"); - gst_buffer_unref (buf); return GST_FLOW_OK; } } if (identity->dump) { - gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_util_dump_mem (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); } for (i = identity->duplicate; i; i--) { @@ -566,77 +314,49 @@ gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, timestamp: %" GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %" G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", - GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf); + GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)), + GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf), + GST_BUFFER_FLAGS (inbuf), inbuf); g_object_notify (G_OBJECT (identity), "last-message"); } - time = GST_BUFFER_TIMESTAMP (buf); + time = GST_BUFFER_TIMESTAMP (inbuf); if (identity->datarate > 0) { time = identity->offset * GST_SECOND / identity->datarate; - GST_BUFFER_TIMESTAMP (buf) = time; - GST_BUFFER_DURATION (buf) = - GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate; + GST_BUFFER_TIMESTAMP (inbuf) = time; + GST_BUFFER_DURATION (inbuf) = + GST_BUFFER_SIZE (inbuf) * GST_SECOND / identity->datarate; } g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0, - buf); + inbuf); if (i > 1) - gst_buffer_ref (buf); + gst_buffer_ref (inbuf); if (identity->sync) { - if (identity->clock) { + if (GST_ELEMENT (identity)->clock) { /* gst_element_wait (GST_ELEMENT (identity), time); */ } } - identity->offset += GST_BUFFER_SIZE (buf); - if (identity->decoupled) { - if (!identity_queue_push (identity, (GstData *) buf)) - return GST_FLOW_UNEXPECTED; - } else { - ret = gst_pad_push (identity->srcpad, buf); - if (ret != GST_FLOW_OK) - return ret; - } + identity->offset += GST_BUFFER_SIZE (inbuf); if (identity->sleep_time) g_usleep (identity->sleep_time); + + gst_buffer_ref (inbuf); + *outbuf = inbuf; } return ret; } static void -gst_identity_set_dataflow_funcs (GstIdentity * identity) -{ - if (identity->has_getrange) - gst_pad_set_getrange_function (identity->srcpad, gst_identity_getrange); - else - gst_pad_set_getrange_function (identity->srcpad, NULL); - - if (identity->has_chain) - gst_pad_set_chain_function (identity->sinkpad, gst_identity_chain); - else - gst_pad_set_chain_function (identity->sinkpad, NULL); - - if (identity->has_src_loop) - gst_pad_set_loop_function (identity->srcpad, gst_identity_src_loop); - else - gst_pad_set_loop_function (identity->srcpad, NULL); - - if (identity->has_sink_loop) - gst_pad_set_loop_function (identity->sinkpad, gst_identity_sink_loop); - else - gst_pad_set_loop_function (identity->sinkpad, NULL); -} - -static void gst_identity_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { @@ -645,22 +365,6 @@ gst_identity_set_property (GObject * object, guint prop_id, identity = GST_IDENTITY (object); switch (prop_id) { - case PROP_HAS_GETRANGE: - identity->has_getrange = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; - case PROP_HAS_CHAIN: - identity->has_chain = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; - case PROP_HAS_SRC_LOOP: - identity->has_src_loop = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; - case PROP_HAS_SINK_LOOP: - identity->has_sink_loop = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; case PROP_SLEEP_TIME: identity->sleep_time = g_value_get_uint (value); break; @@ -703,18 +407,6 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value, identity = GST_IDENTITY (object); switch (prop_id) { - case PROP_HAS_GETRANGE: - g_value_set_boolean (value, identity->has_getrange); - break; - case PROP_HAS_CHAIN: - g_value_set_boolean (value, identity->has_chain); - break; - case PROP_HAS_SRC_LOOP: - g_value_set_boolean (value, identity->has_src_loop); - break; - case PROP_HAS_SINK_LOOP: - g_value_set_boolean (value, identity->has_sink_loop); - break; case PROP_SLEEP_TIME: g_value_set_uint (value, identity->sleep_time); break; @@ -755,12 +447,15 @@ static GstElementStateReturn gst_identity_change_state (GstElement * element) { GstIdentity *identity; + GstElementState transition; + GstElementStateReturn result; g_return_val_if_fail (GST_IS_IDENTITY (element), GST_STATE_FAILURE); identity = GST_IDENTITY (element); + transition = GST_STATE_TRANSITION (element); - switch (GST_STATE_TRANSITION (element)) { + switch (transition) { case GST_STATE_NULL_TO_READY: break; case GST_STATE_READY_TO_PAUSED: @@ -770,6 +465,14 @@ gst_identity_change_state (GstElement * element) identity->prev_offset_end = -1; break; case GST_STATE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { case GST_STATE_PLAYING_TO_PAUSED: break; case GST_STATE_PAUSED_TO_READY: @@ -782,8 +485,5 @@ gst_identity_change_state (GstElement * element) break; } - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - - return GST_STATE_SUCCESS; + return result; } diff --git a/gst/elements/gstidentity.h b/gst/elements/gstidentity.h index e187f2e..4a51a07 100644 --- a/gst/elements/gstidentity.h +++ b/gst/elements/gstidentity.h @@ -26,6 +26,7 @@ #include +#include G_BEGIN_DECLS @@ -45,24 +46,8 @@ typedef struct _GstIdentity GstIdentity; typedef struct _GstIdentityClass GstIdentityClass; struct _GstIdentity { - GstElement element; + GstBaseTransform element; - GstPad *sinkpad; - GstPad *srcpad; - - GstData *pen_data; - GMutex *pen_lock; - GCond *pen_cond; - gboolean pen_flushing; - - gboolean has_chain; - gboolean has_getrange; - gboolean has_src_loop; - gboolean has_sink_loop; - GstActivateMode sink_mode; - GstActivateMode src_mode; - gboolean decoupled; - guint duplicate; gint error_after; gfloat drop_probability; @@ -75,15 +60,12 @@ struct _GstIdentity { GstClockTime prev_timestamp; GstClockTime prev_duration; guint64 prev_offset_end; - GstClock *clock; gchar *last_message; - GstCaps *srccaps; - - guint64 offset; + guint64 offset; }; struct _GstIdentityClass { - GstElementClass parent_class; + GstBaseTransformClass parent_class; /* signals */ void (*handoff) (GstElement *element, GstBuffer *buf); diff --git a/gst/gstelement.c b/gst/gstelement.c index 6eaecf1..287e7a5 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -1983,7 +1983,7 @@ restart: if (GST_IS_REAL_PAD (pad)) { GstRealPad *peer; gboolean pad_loop, pad_get; - gboolean delay = FALSE; + gboolean done = FALSE; /* see if the pad has a loop function and grab * the peer */ @@ -2003,38 +2003,24 @@ restart: /* see if the peer has a loop function */ peer_loop = GST_RPAD_LOOPFUNC (peer) != NULL; - /* sinkpads with a loop function are delayed since they - * need the srcpad to be active first */ - if (GST_PAD_IS_SINK (pad) && pad_loop && peer_get) { + /* If the pad is a sink with loop and the peer has a get function, + * we can activate the sinkpad */ + if ((GST_PAD_IS_SINK (pad) && pad_loop && peer_get) || + (GST_PAD_IS_SRC (pad) && peer_loop && pad_get)) { GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, - "delaying pad %s", GST_OBJECT_NAME (pad)); - delay = TRUE; - } else if (GST_PAD_IS_SRC (pad) && peer_loop && pad_get) { - /* If the pad is a source and the peer has a loop function, - * we can activate the srcpad and then the loopbased sinkpad */ - GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, - "%sactivating pad %s", (active ? "" : "(de)"), + "%sactivating pad %s pull mode", (active ? "" : "(de)"), GST_OBJECT_NAME (pad)); result &= gst_pad_set_active (pad, (active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE)); - - GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, - "%sactivating delayed pad %s", (active ? "" : "(de)"), - GST_OBJECT_NAME (peer)); - result &= gst_pad_set_active (GST_PAD (peer), - (active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE)); - - /* set flag here since we don't want the code below to activate - * the pad again */ - delay = TRUE; + done = TRUE; } gst_object_unref (GST_OBJECT (peer)); } - /* all other conditions are just push based pads */ - if (!delay) { + if (!done) { + /* all other conditions are just push based pads */ GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, - "%sactivating pad %s", (active ? "" : "(de)"), + "%sactivating pad %s push mode", (active ? "" : "(de)"), GST_OBJECT_NAME (pad)); result &= gst_pad_set_active (pad, diff --git a/gst/gstpad.c b/gst/gstpad.c index 72ffefa..35fe793 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -437,9 +437,15 @@ lost_ghostpad: /** * gst_pad_set_active: * @pad: the #GstPad to activate or deactivate. - * @active: TRUE to activate the pad. + * @mode: the mode of the pad. * - * Activates or deactivates the given pad. + * Activates or deactivates the given pad in the given mode. + * + * For a source pad: PULL mode will call the getrange function, + * PUSH mode will require the element to call _push() on the pad. + * + * For a sink pad: PULL mode will require the element to call + * the _pull_range() function, PUSH mode will call the chain function. * * Returns: TRUE if the operation was successfull. * @@ -457,13 +463,12 @@ gst_pad_set_active (GstPad * pad, GstActivateMode mode) GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad); - active = (mode != GST_ACTIVATE_NONE); - + active = GST_PAD_MODE_ACTIVATE (mode); old = GST_PAD_IS_ACTIVE (realpad); /* if nothing changed, we can just exit */ if (G_UNLIKELY (old == active)) - goto exit; + goto was_ok; /* make sure data is disallowed when going inactive */ if (!active) { @@ -475,14 +480,16 @@ gst_pad_set_active (GstPad * pad, GstActivateMode mode) } if (active) { - if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) { + if (GST_RPAD_DIRECTION (realpad) == GST_PAD_SRC) { if (mode == GST_ACTIVATE_PULL) { if (!realpad->getrangefunc) goto wrong_mode; } else { - /* we can push if driven by a chain or loop on the sink pad */ + /* we can push if driven by a chain or loop on the sink pad. + * peer pad is assumed to be active now. */ } - } else { /* sink pads */ + } else { + /* sink pads */ if (mode == GST_ACTIVATE_PULL) { /* the src can drive us with getrange */ } else { @@ -509,18 +516,23 @@ gst_pad_set_active (GstPad * pad, GstActivateMode mode) goto activate_error; } - /* when going to active alow data passing now */ + /* when going to active allow data passing now */ if (active) { - GST_CAT_DEBUG (GST_CAT_PADS, "activating pad %s:%s", - GST_DEBUG_PAD_NAME (realpad)); + GST_CAT_DEBUG (GST_CAT_PADS, "activating pad %s:%s in mode %d", + GST_DEBUG_PAD_NAME (realpad), mode); GST_FLAG_SET (realpad, GST_PAD_ACTIVE); } - -exit: GST_UNLOCK (realpad); return TRUE; +was_ok: + { + GST_CAT_DEBUG (GST_CAT_PADS, + "pad %s:%s was active", GST_DEBUG_PAD_NAME (realpad)); + GST_UNLOCK (realpad); + return TRUE; + } /* errors */ lost_ghostpad: { @@ -545,6 +557,42 @@ activate_error: } /** + * gst_pad_peer_set_active: + * @pad: the #GstPad to activate or deactivate the peer of. + * @mode: the mode of the pad. + * + * Activates or deactivates the given peer of a pad. Elements + * that will perform a _pull_range() on their sinkpads need + * to call this function when the sinkpad is activated or when + * an internally linked source pad is activated in pull mode. + * + * Returns: TRUE if the operation was successfull. + * + * MT safe. + */ +gboolean +gst_pad_peer_set_active (GstPad * pad, GstActivateMode mode) +{ + GstPad *peer; + gboolean result = FALSE; + + peer = gst_pad_get_peer (pad); + if (!peer) + goto no_peer; + + result = gst_pad_set_active (peer, mode); + gst_object_unref (GST_OBJECT_CAST (peer)); + + return result; + + /* errors */ +no_peer: + { + return FALSE; + } +} + +/** * gst_pad_is_active: * @pad: the #GstPad to query * @@ -2909,6 +2957,74 @@ no_function: } } + +/** + * gst_pad_check_pull_range: + * @pad: a sink #GstRealPad. + * + * Checks if a #gst_pad_pull_range() can be performed on the peer + * source pad. This function is used by plugins that want to check + * if they can use random access on the peer source pad. + * + * The peer sourcepad can implement a custom #GstPadCheckGetRangeFunction + * if it needs to perform some logic to determine if pull_range is + * possible. + * + * Returns: a gboolean with the result. + * + * MT safe. + */ +gboolean +gst_pad_check_pull_range (GstPad * pad) +{ + GstRealPad *peer; + gboolean ret; + GstPadCheckGetRangeFunction checkgetrangefunc; + + g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK, + GST_FLOW_ERROR); + + GST_LOCK (pad); + + if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) + goto not_connected; + + gst_object_ref (GST_OBJECT_CAST (peer)); + GST_UNLOCK (pad); + + /* see note in above function */ + if (G_UNLIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) + goto no_function; + + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "calling checkgetrangefunc %s of peer pad %s:%s", + GST_DEBUG_FUNCPTR_NAME (checkgetrangefunc), GST_DEBUG_PAD_NAME (peer)); + + ret = checkgetrangefunc (GST_PAD_CAST (peer)); + + gst_object_unref (GST_OBJECT_CAST (peer)); + + return ret; + + /* ERROR recovery here */ +not_connected: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "checkinh pull range, but it was not linked"); + GST_UNLOCK (pad); + return FALSE; + } +no_function: + { + GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), + ("pad %s:%s checked pull_range but the peer pad %s:%s has no checkgetrangefunction", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer))); + gst_object_unref (GST_OBJECT (peer)); + return FALSE; + } +} + /** * gst_pad_pull_range: * @pad: a sink #GstPad. @@ -2943,6 +3059,12 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL)) goto not_connected; + if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer))) + goto not_active; + + if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer))) + goto flushing; + gst_object_ref (GST_OBJECT_CAST (peer)); GST_UNLOCK (pad); @@ -2951,8 +3073,10 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, goto no_function; GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, - "calling getrangefunc %s of peer pad %s:%s", - GST_DEBUG_FUNCPTR_NAME (getrangefunc), GST_DEBUG_PAD_NAME (peer)); + "calling getrangefunc %s of peer pad %s:%s, offset %" + G_GUINT64_FORMAT ", size %u", + GST_DEBUG_FUNCPTR_NAME (getrangefunc), GST_DEBUG_PAD_NAME (peer), + offset, size); ret = getrangefunc (GST_PAD_CAST (peer), offset, size, buffer); @@ -2968,6 +3092,20 @@ not_connected: GST_UNLOCK (pad); return GST_FLOW_NOT_CONNECTED; } +not_active: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pulling range, but it was inactive"); + GST_UNLOCK (pad); + return GST_FLOW_WRONG_STATE; + } +flushing: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, + "pulling range, but pad was flushing"); + GST_UNLOCK (pad); + return GST_FLOW_UNEXPECTED; + } no_function: { GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), @@ -3163,9 +3301,9 @@ gst_pad_template_new (const gchar * name_template, * Gets the capabilities of the pad template. * * Returns: the #GstCaps of the pad template. If you need to keep a reference to - * the caps, make a copy (see gst_caps_copy ()). + * the caps, take a ref (see gst_caps_ref ()). */ -const GstCaps * +GstCaps * gst_pad_template_get_caps (GstPadTemplate * templ) { g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL); @@ -3354,6 +3492,8 @@ gst_ghost_pad_new (const gchar * name, GstPad * pad) * The caller must free this list after use. * * Returns: a newly allocated #GList of pads. + * + * Not MT safe. */ GList * gst_pad_get_internal_links_default (GstPad * pad) @@ -3394,6 +3534,8 @@ gst_pad_get_internal_links_default (GstPad * pad) * The caller must free this list after use. * * Returns: a newly allocated #GList of pads. + * + * Not MT safe. */ GList * gst_pad_get_internal_links (GstPad * pad) diff --git a/gst/gstpad.h b/gst/gstpad.h index fc28d5d..7cfd561 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -96,8 +96,8 @@ typedef enum { GST_PAD_LINK_OK = 0, /* link ok */ } GstPadLinkReturn; -#define GST_PAD_LINK_FAILED(ret) (ret < GST_PAD_LINK_OK) -#define GST_PAD_LINK_SUCCESSFUL(ret) (ret >= GST_PAD_LINK_OK) +#define GST_PAD_LINK_FAILED(ret) ((ret) < GST_PAD_LINK_OK) +#define GST_PAD_LINK_SUCCESSFUL(ret) ((ret) >= GST_PAD_LINK_OK) typedef enum { GST_FLOW_OK = 0, /* data passing was ok */ @@ -116,6 +116,8 @@ typedef enum { GST_ACTIVATE_PULL, } GstActivateMode; +#define GST_PAD_MODE_ACTIVATE(mode) ((mode) != GST_ACTIVATE_NONE) + /* convenience functions */ #ifdef G_HAVE_ISO_VARARGS #define GST_PAD_QUERY_TYPE_FUNCTION(functionname, ...) GST_QUERY_TYPE_FUNCTION (GstPad *, functionname, __VA_ARGS__); @@ -136,6 +138,7 @@ typedef void (*GstPadLoopFunction) (GstPad *pad); typedef GstFlowReturn (*GstPadChainFunction) (GstPad *pad, GstBuffer *buffer); typedef GstFlowReturn (*GstPadGetRangeFunction) (GstPad *pad, guint64 offset, guint length, GstBuffer **buffer); +typedef gboolean (*GstPadCheckGetRangeFunction) (GstPad *pad); typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event); /* convert/query/format functions */ @@ -237,6 +240,7 @@ struct _GstRealPad { /* data transport functions */ GstPadLoopFunction loopfunc; GstPadChainFunction chainfunc; + GstPadCheckGetRangeFunction checkgetrangefunc; GstPadGetRangeFunction getrangefunc; GstPadEventFunction eventfunc; @@ -301,6 +305,7 @@ struct _GstGhostPadClass { #define GST_RPAD_ACTIVATEFUNC(pad) (GST_REAL_PAD_CAST(pad)->activatefunc) #define GST_RPAD_LOOPFUNC(pad) (GST_REAL_PAD_CAST(pad)->loopfunc) #define GST_RPAD_CHAINFUNC(pad) (GST_REAL_PAD_CAST(pad)->chainfunc) +#define GST_RPAD_CHECKGETRANGEFUNC(pad) (GST_REAL_PAD_CAST(pad)->checkgetrangefunc) #define GST_RPAD_GETRANGEFUNC(pad) (GST_REAL_PAD_CAST(pad)->getrangefunc) #define GST_RPAD_EVENTFUNC(pad) (GST_REAL_PAD_CAST(pad)->eventfunc) #define GST_RPAD_CONVERTFUNC(pad) (GST_REAL_PAD_CAST(pad)->convertfunc) @@ -458,6 +463,7 @@ GstElement* gst_pad_get_real_parent (GstPad *pad); GstPadDirection gst_pad_get_direction (GstPad *pad); gboolean gst_pad_set_active (GstPad *pad, GstActivateMode mode); +gboolean gst_pad_peer_set_active (GstPad *pad, GstActivateMode mode); gboolean gst_pad_is_active (GstPad *pad); gboolean gst_pad_set_blocked (GstPad *pad, gboolean blocked); gboolean gst_pad_set_blocked_async (GstPad *pad, gboolean blocked, @@ -524,6 +530,7 @@ GstCaps * gst_pad_get_filter_caps (GstPad * pad); /* data passing functions */ GstFlowReturn gst_pad_push (GstPad *pad, GstBuffer *buffer); +gboolean gst_pad_check_pull_range (GstPad *pad); GstFlowReturn gst_pad_pull_range (GstPad *pad, guint64 offset, guint size, GstBuffer **buffer); gboolean gst_pad_push_event (GstPad *pad, GstEvent *event); @@ -593,7 +600,7 @@ GstPadTemplate* gst_pad_template_new (const gchar *name_template, GstCaps *caps); GstPadTemplate * gst_static_pad_template_get (GstStaticPadTemplate *pad_template); -const GstCaps* gst_pad_template_get_caps (GstPadTemplate *templ); +GstCaps* gst_pad_template_get_caps (GstPadTemplate *templ); #ifndef GST_DISABLE_LOADSAVE xmlNodePtr gst_ghost_pad_save_thyself (GstPad *pad, diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am index 8ba1b85..dda7031 100644 --- a/libs/gst/base/Makefile.am +++ b/libs/gst/base/Makefile.am @@ -6,7 +6,8 @@ noinst_DATA = $(as_libtool_noinst_DATA_files) libgstbase_@GST_MAJORMINOR@_la_DEPENDENCIES = ../libgstreamer-@GST_MAJORMINOR@.la libgstbase_@GST_MAJORMINOR@_la_SOURCES = \ - gstbasesink.c + gstbasesink.c \ + gstbasetransform.c libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstbase_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) @@ -16,7 +17,8 @@ libgstbase_@GST_MAJORMINOR@includedir = \ $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/base libgstbase_@GST_MAJORMINOR@include_HEADERS = \ - gstbasesink.h + gstbasesink.h \ + gstbasetransform.h install-data-local: as-libtool-install-data-local diff --git a/libs/gst/base/README b/libs/gst/base/README index efd6e57..f9c1583 100644 --- a/libs/gst/base/README +++ b/libs/gst/base/README @@ -14,3 +14,14 @@ GstBaseSink FIXME: not much point making it operate in pull mode as a generic base class I guess... + +GstBaseTransform + + Base class for simple tranform filters + + - one sinkpad and one srcpad + - formats the same on sink and source pad. + - handles state changes + - does flushing + - push mode + - pull mode if transform can operate on arbitrary data diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index a476071..88d7d97 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -26,11 +26,6 @@ #include "gstbasesink.h" #include -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - GST_DEBUG_CATEGORY_STATIC (gst_basesink_debug); #define GST_CAT_DEFAULT gst_basesink_debug @@ -61,11 +56,35 @@ enum PROP_PREROLL_QUEUE_LEN }; -#define _do_init(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_basesink_debug, "basesink", 0, "basesink element"); +static GstElementClass *parent_class = NULL; + +static void gst_basesink_base_init (gpointer g_class); +static void gst_basesink_class_init (GstBaseSinkClass * klass); +static void gst_basesink_init (GstBaseSink * trans, gpointer g_class); + +GType +gst_basesink_get_type (void) +{ + static GType basesink_type = 0; + + if (!basesink_type) { + static const GTypeInfo basesink_info = { + sizeof (GstBaseSinkClass), + (GBaseInitFunc) gst_basesink_base_init, + NULL, + (GClassInitFunc) gst_basesink_class_init, + NULL, + NULL, + sizeof (GstBaseSink), + 0, + (GInstanceInitFunc) gst_basesink_init, + }; -GST_BOILERPLATE_FULL (GstBaseSink, gst_basesink, GstElement, GST_TYPE_ELEMENT, - _do_init); + basesink_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseSink", &basesink_info, G_TYPE_FLAG_ABSTRACT); + } + return basesink_type; +} static void gst_basesink_set_clock (GstElement * element, GstClock * clock); @@ -74,7 +93,6 @@ static void gst_basesink_set_property (GObject * object, guint prop_id, static void gst_basesink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstStaticPadTemplate *gst_base_sink_get_template (GstBaseSink * sink); static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink); static gboolean gst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps); static GstBuffer *gst_base_sink_buffer_alloc (GstBaseSink * sink, @@ -93,32 +111,11 @@ static gboolean gst_basesink_event (GstPad * pad, GstEvent * event); static inline void gst_basesink_handle_buffer (GstBaseSink * basesink, GstBuffer * buf); -static GstStaticPadTemplate * -gst_basesink_get_template (GstBaseSink * bsink) -{ - GstStaticPadTemplate *template = NULL; - GstBaseSinkClass *bclass; - - bclass = GST_BASESINK_GET_CLASS (bsink); - - if (bclass->get_template) - template = bclass->get_template (bsink); - - if (template == NULL) { - template = &sinktemplate; - } - return template; -} - static void gst_basesink_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_DEBUG_CATEGORY_INIT (gst_basesink_debug, "basesink", 0, + "basesink element"); } static void @@ -130,6 +127,8 @@ gst_basesink_class_init (GstBaseSinkClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_basesink_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_basesink_get_property); @@ -153,7 +152,6 @@ gst_basesink_class_init (GstBaseSinkClass * klass) klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_sink_get_caps); klass->set_caps = GST_DEBUG_FUNCPTR (gst_base_sink_set_caps); - klass->get_template = GST_DEBUG_FUNCPTR (gst_base_sink_get_template); klass->buffer_alloc = GST_DEBUG_FUNCPTR (gst_base_sink_buffer_alloc); klass->get_times = GST_DEBUG_FUNCPTR (gst_basesink_get_times); } @@ -171,13 +169,15 @@ gst_basesink_pad_getcaps (GstPad * pad) caps = bclass->get_caps (bsink); if (caps == NULL) { - GstStaticPadTemplate *stemplate; - GstPadTemplate *template; + GstPadTemplate *pad_template; - stemplate = gst_basesink_get_template (bsink); - template = gst_static_pad_template_get (stemplate); - caps = gst_caps_copy (gst_pad_template_get_caps (template)); + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink"); + if (pad_template != NULL) { + caps = gst_caps_ref (gst_pad_template_get_caps (pad_template)); + } } + return caps; } @@ -213,15 +213,16 @@ gst_basesink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size, } static void -gst_basesink_init (GstBaseSink * basesink) +gst_basesink_init (GstBaseSink * basesink, gpointer g_class) { - GstStaticPadTemplate *template; + GstPadTemplate *pad_template; + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); + g_return_if_fail (pad_template != NULL); - template = gst_basesink_get_template (basesink); + basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink"); - basesink->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get (template), - "sink"); gst_pad_set_getcaps_function (basesink->sinkpad, GST_DEBUG_FUNCPTR (gst_basesink_pad_getcaps)); gst_pad_set_setcaps_function (basesink->sinkpad, @@ -328,12 +329,6 @@ gst_basesink_get_property (GObject * object, guint prop_id, GValue * value, GST_UNLOCK (sink); } -static GstStaticPadTemplate * -gst_base_sink_get_template (GstBaseSink * sink) -{ - return &sinktemplate; -} - static GstCaps * gst_base_sink_get_caps (GstBaseSink * sink) { @@ -735,6 +730,7 @@ gst_basesink_activate (GstPad * pad, GstActivateMode mode) case GST_ACTIVATE_PULL: /* if we have a scheduler we can start the task */ g_return_val_if_fail (basesink->has_loop, FALSE); + gst_pad_peer_set_active (pad, mode); if (GST_ELEMENT_SCHEDULER (basesink)) { GST_STREAM_LOCK (pad); GST_RPAD_TASK (pad) = @@ -791,7 +787,7 @@ gst_basesink_change_state (GstElement * element) break; case GST_STATE_READY_TO_PAUSED: /* need to complete preroll before this state change completes, there - * is no data flow in READY so we cqn safely assume we need to preroll. */ + * is no data flow in READY so we can safely assume we need to preroll. */ basesink->offset = 0; GST_PREROLL_LOCK (basesink->sinkpad); basesink->preroll_queue = g_queue_new (); diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h index 3c64f78..b3eafad 100644 --- a/libs/gst/base/gstbasesink.h +++ b/libs/gst/base/gstbasesink.h @@ -66,8 +66,6 @@ struct _GstBaseSink { struct _GstBaseSinkClass { GstElementClass parent_class; - GstStaticPadTemplate* (*get_template) (GstBaseSink *sink); - GstCaps* (*get_caps) (GstBaseSink *sink); gboolean (*set_caps) (GstBaseSink *sink, GstCaps *caps); diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c new file mode 100644 index 0000000..c6032d6 --- /dev/null +++ b/libs/gst/base/gstbasetransform.c @@ -0,0 +1,404 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstbasetransform.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. + */ + + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "../gst-i18n-lib.h" +#include "gstbasetransform.h" +#include + +GST_DEBUG_CATEGORY_STATIC (gst_base_transform_debug); +#define GST_CAT_DEFAULT gst_base_transform_debug + +/* BaseTransform signals and args */ +enum +{ + SIGNAL_HANDOFF, + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, +}; + +static GstElementClass *parent_class = NULL; + +static void gst_base_transform_base_init (gpointer g_class); +static void gst_base_transform_class_init (GstBaseTransformClass * klass); +static void gst_base_transform_init (GstBaseTransform * trans, + gpointer g_class); + +GType +gst_base_transform_get_type (void) +{ + static GType base_transform_type = 0; + + if (!base_transform_type) { + static const GTypeInfo base_transform_info = { + sizeof (GstBaseTransformClass), + (GBaseInitFunc) gst_base_transform_base_init, + NULL, + (GClassInitFunc) gst_base_transform_class_init, + NULL, + NULL, + sizeof (GstBaseTransform), + 0, + (GInstanceInitFunc) gst_base_transform_init, + }; + + base_transform_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT); + } + return base_transform_type; +} + +static void gst_base_transform_finalize (GObject * object); +static void gst_base_transform_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_transform_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static gboolean gst_base_transform_src_activate (GstPad * pad, + GstActivateMode mode); +static gboolean gst_base_transform_sink_activate (GstPad * pad, + GstActivateMode mode); +static GstElementStateReturn gst_base_transform_change_state (GstElement * + element); + +static gboolean gst_base_transform_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buffer); +static GstFlowReturn gst_base_transform_chain (GstPad * pad, + GstBuffer * buffer); +static GstFlowReturn gst_base_transform_handle_buffer (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer ** outbuf); +static GstCaps *gst_base_transform_proxy_getcaps (GstPad * pad); +static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps); + +/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */ + +static void +gst_base_transform_base_init (gpointer g_class) +{ + GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0, + "basetransform element"); +} + +static void +gst_base_transform_finalize (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_base_transform_class_init (GstBaseTransformClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_base_transform_set_property); + gobject_class->get_property = + GST_DEBUG_FUNCPTR (gst_base_transform_get_property); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_transform_finalize); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_transform_change_state); +} + +static void +gst_base_transform_init (GstBaseTransform * trans, gpointer g_class) +{ + GstPadTemplate *pad_template; + + GST_DEBUG ("gst_base_transform_init"); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); + g_return_if_fail (pad_template != NULL); + trans->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + gst_pad_set_getcaps_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps)); + gst_pad_set_setcaps_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_setcaps)); + gst_pad_set_event_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_event)); + gst_pad_set_chain_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_chain)); + gst_pad_set_activate_function (trans->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate)); + gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + g_return_if_fail (pad_template != NULL); + trans->srcpad = gst_pad_new_from_template (pad_template, "src"); + gst_pad_set_getcaps_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps)); + gst_pad_set_getrange_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_getrange)); + gst_pad_set_activate_function (trans->srcpad, + GST_DEBUG_FUNCPTR (gst_base_transform_src_activate)); + gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad); +} + +static GstCaps * +gst_base_transform_proxy_getcaps (GstPad * pad) +{ + GstPad *otherpad; + GstBaseTransform *trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad)); + + otherpad = pad == trans->srcpad ? trans->sinkpad : trans->srcpad; + + return gst_pad_peer_get_caps (otherpad); +} + +static gboolean +gst_base_transform_setcaps (GstPad * pad, GstCaps * caps) +{ + GstBaseTransform *trans; + GstBaseTransformClass *bclass; + gboolean result = TRUE; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (bclass->set_caps) + result = bclass->set_caps (trans, caps); + + return result; +} + +static gboolean +gst_base_transform_event (GstPad * pad, GstEvent * event) +{ + GstBaseTransform *trans; + GstBaseTransformClass *bclass; + gboolean ret = FALSE; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + + if (bclass->event) + bclass->event (trans, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH: + if (GST_EVENT_FLUSH_DONE (event)) { + } + GST_STREAM_LOCK (pad); + break; + case GST_EVENT_EOS: + GST_STREAM_LOCK (pad); + break; + default: + break; + } + ret = gst_pad_event_default (pad, event); + GST_STREAM_UNLOCK (pad); + + return ret; +} + +static GstFlowReturn +gst_base_transform_getrange (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstBaseTransform *trans; + GstFlowReturn ret; + GstBuffer *inbuf; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + + GST_STREAM_LOCK (pad); + + ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf); + if (ret == GST_FLOW_OK) { + ret = gst_base_transform_handle_buffer (trans, inbuf, buffer); + } + + GST_STREAM_UNLOCK (pad); + + return ret; +} + +static GstFlowReturn +gst_base_transform_chain (GstPad * pad, GstBuffer * buffer) +{ + GstBaseTransform *trans; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf; + + trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad)); + + GST_STREAM_LOCK (pad); + + ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf); + if (ret == GST_FLOW_OK) { + ret = gst_pad_push (trans->srcpad, outbuf); + } + + GST_STREAM_UNLOCK (pad); + + return ret; +} + +static GstFlowReturn +gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer ** outbuf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstBaseTransformClass *bclass; + + bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); + if (bclass->transform) + ret = bclass->transform (trans, inbuf, outbuf); + + gst_buffer_unref (inbuf); + + return ret; +} + +static void +gst_base_transform_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_transform_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_base_transform_sink_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result = FALSE; + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + result = TRUE; + break; + case GST_ACTIVATE_PULL: + result = TRUE; + break; + case GST_ACTIVATE_NONE: + result = TRUE; + break; + } + return result; +} + +static gboolean +gst_base_transform_src_activate (GstPad * pad, GstActivateMode mode) +{ + gboolean result = FALSE; + GstBaseTransform *trans; + + trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad)); + + switch (mode) { + case GST_ACTIVATE_PUSH: + result = TRUE; + break; + case GST_ACTIVATE_PULL: + result = gst_pad_set_active (trans->sinkpad, mode); + result = gst_pad_peer_set_active (trans->sinkpad, mode); + break; + case GST_ACTIVATE_NONE: + result = TRUE; + break; + } + return result; +} + +static GstElementStateReturn +gst_base_transform_change_state (GstElement * element) +{ + GstBaseTransform *trans; + GstElementState transition; + GstElementStateReturn result; + + trans = GST_BASE_TRANSFORM (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_PLAYING_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_READY: + break; + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + + return result; +} diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h new file mode 100644 index 0000000..788fe53 --- /dev/null +++ b/libs/gst/base/gstbasetransform.h @@ -0,0 +1,67 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstbasetransform.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_BASE_TRANSFORM_H__ +#define __GST_BASE_TRANSFORM_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_TRANSFORM (gst_base_transform_get_type()) +#define GST_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransform)) +#define GST_BASE_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass)) +#define GST_BASE_TRANSFORM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_BASE_TRANSFORM,GstBaseTransformClass)) +#define GST_IS_BASE_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_TRANSFORM)) +#define GST_IS_BASE_TRANSFORM_CLASS(obj)(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_TRANSFORM)) + +/* the names of the templates for the sink and source pads */ +#define GST_BASE_TRANSFORM_SINK_NAME "sink" +#define GST_BASE_TRANSFORM_SRC_NAME "src" + +typedef struct _GstBaseTransform GstBaseTransform; +typedef struct _GstBaseTransformClass GstBaseTransformClass; + +struct _GstBaseTransform { + GstElement element; + + /* source and sink pads */ + GstPad *sinkpad; + GstPad *srcpad; +}; + +struct _GstBaseTransformClass { + GstElementClass parent_class; + + gboolean (*set_caps) (GstBaseTransform *trans, GstCaps *caps); + + gboolean (*event) (GstBaseTransform *trans, GstEvent *event); + GstFlowReturn (*transform) (GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer **outbuf); +}; + +GType gst_base_transform_get_type(void); + +G_END_DECLS + +#endif /* __GST_BASE_TRANSFORM_H__ */ diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c index 0b8a6d2..76a61f7 100644 --- a/plugins/elements/gstidentity.c +++ b/plugins/elements/gstidentity.c @@ -59,7 +59,6 @@ enum LAST_SIGNAL }; -#define DEFAULT_LOOP_BASED FALSE #define DEFAULT_SLEEP_TIME 0 #define DEFAULT_DUPLICATE 1 #define DEFAULT_ERROR_AFTER -1 @@ -73,11 +72,6 @@ enum enum { PROP_0, - PROP_HAS_GETRANGE, - PROP_HAS_CHAIN, - PROP_HAS_SINK_LOOP, - PROP_HAS_SRC_LOOP, - PROP_LOOP_BASED, PROP_SLEEP_TIME, PROP_DUPLICATE, PROP_ERROR_AFTER, @@ -91,14 +85,11 @@ enum }; -typedef GstFlowReturn (*IdentityPushFunc) (GstIdentity *, GstBuffer *); - - #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element"); -GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstElement, GST_TYPE_ELEMENT, - _do_init); +GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, _do_init); static void gst_identity_finalize (GObject * object); static void gst_identity_set_property (GObject * object, guint prop_id, @@ -107,17 +98,9 @@ static void gst_identity_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstElementStateReturn gst_identity_change_state (GstElement * element); -static gboolean gst_identity_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_identity_getrange (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer); -static GstFlowReturn gst_identity_chain (GstPad * pad, GstBuffer * buffer); -static void gst_identity_src_loop (GstPad * pad); -static void gst_identity_sink_loop (GstPad * pad); -static GstFlowReturn gst_identity_handle_buffer (GstIdentity * identity, - GstBuffer * buf); -static void gst_identity_set_clock (GstElement * element, GstClock * clock); -static GstCaps *gst_identity_proxy_getcaps (GstPad * pad); - +static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event); +static GstFlowReturn gst_identity_transform (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer ** outbuf); static guint gst_identity_signals[LAST_SIGNAL] = { 0 }; @@ -140,9 +123,6 @@ gst_identity_finalize (GObject * object) identity = GST_IDENTITY (object); - g_mutex_free (identity->pen_lock); - g_cond_free (identity->pen_cond); - g_free (identity->last_message); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -153,29 +133,15 @@ gst_identity_class_init (GstIdentityClass * 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_identity_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_GETRANGE, - g_param_spec_boolean ("has-getrange", "Has getrange", - "If the src pad will implement a getrange function", - TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_CHAIN, - g_param_spec_boolean ("has-chain", "Has chain", - "If the sink pad will implement a chain function", - TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_SRC_LOOP, - g_param_spec_boolean ("has-src-loop", "Has src loop", - "If the src pad will implement a loop function", - FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_SINK_LOOP, - g_param_spec_boolean ("has-sink-loop", "Has sink loop", - "If the sink pad will implement a loop function", - FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SLEEP_TIME, g_param_spec_uint ("sleep-time", "Sleep time", "Microseconds to sleep between processing", 0, G_MAXUINT, @@ -220,33 +186,16 @@ gst_identity_class_init (GstIdentityClass * klass) gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_identity_finalize); - gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_identity_set_clock); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_identity_change_state); + gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_identity_event); + gstbasetrans_class->transform = GST_DEBUG_FUNCPTR (gst_identity_transform); } static void gst_identity_init (GstIdentity * identity) { - identity->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate), - "sink"); - gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad); - gst_pad_set_getcaps_function (identity->sinkpad, - GST_DEBUG_FUNCPTR (gst_identity_proxy_getcaps)); - gst_pad_set_event_function (identity->sinkpad, - GST_DEBUG_FUNCPTR (gst_identity_event)); - - identity->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate), - "src"); - gst_pad_set_getcaps_function (identity->srcpad, - GST_DEBUG_FUNCPTR (gst_identity_proxy_getcaps)); - gst_pad_set_getrange_function (identity->srcpad, - GST_DEBUG_FUNCPTR (gst_identity_getrange)); - gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad); - identity->sleep_time = DEFAULT_SLEEP_TIME; identity->duplicate = DEFAULT_DUPLICATE; identity->error_after = DEFAULT_ERROR_AFTER; @@ -257,279 +206,78 @@ gst_identity_init (GstIdentity * identity) identity->check_perfect = DEFAULT_CHECK_PERFECT; identity->dump = DEFAULT_DUMP; identity->last_message = NULL; - identity->srccaps = NULL; - - identity->pen_data = NULL; - identity->pen_lock = g_mutex_new (); - identity->pen_cond = g_cond_new (); - identity->pen_flushing = FALSE; -} - -static void -gst_identity_set_clock (GstElement * element, GstClock * clock) -{ - GstIdentity *identity = GST_IDENTITY (element); - - gst_object_replace ((GstObject **) & identity->clock, (GstObject *) clock); -} - -static GstCaps * -gst_identity_proxy_getcaps (GstPad * pad) -{ - GstPad *otherpad; - GstIdentity *identity = GST_IDENTITY (GST_OBJECT_PARENT (pad)); - - otherpad = pad == identity->srcpad ? identity->sinkpad : identity->srcpad; - - return gst_pad_peer_get_caps (otherpad); -} - -static gboolean -identity_queue_push (GstIdentity * identity, GstData * data) -{ - gboolean ret; - - g_mutex_lock (identity->pen_lock); - while (identity->pen_data && !identity->pen_flushing) - g_cond_wait (identity->pen_cond, identity->pen_lock); - if (identity->pen_flushing) { - gst_data_unref (identity->pen_data); - identity->pen_data = NULL; - gst_data_unref (data); - ret = FALSE; - } else { - identity->pen_data = data; - ret = TRUE; - } - g_cond_signal (identity->pen_cond); - g_mutex_unlock (identity->pen_lock); - - return ret; -} - -static GstData * -identity_queue_pop (GstIdentity * identity) -{ - GstData *ret; - - g_mutex_lock (identity->pen_lock); - while (!(ret = identity->pen_data) && !identity->pen_flushing) - g_cond_wait (identity->pen_cond, identity->pen_lock); - g_cond_signal (identity->pen_cond); - g_mutex_unlock (identity->pen_lock); - - return ret; -} - -static void -identity_queue_flush (GstIdentity * identity) -{ - g_mutex_lock (identity->pen_lock); - identity->pen_flushing = TRUE; - g_cond_signal (identity->pen_cond); - g_mutex_unlock (identity->pen_lock); } static gboolean -gst_identity_event (GstPad * pad, GstEvent * event) +gst_identity_event (GstBaseTransform * trans, GstEvent * event) { GstIdentity *identity; - gboolean ret; - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); + identity = GST_IDENTITY (trans); if (!identity->silent) { g_free (identity->last_message); identity->last_message = g_strdup_printf ("chain ******* (%s:%s)E (type: %d) %p", - GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE (event), event); + GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), event); g_object_notify (G_OBJECT (identity), "last_message"); } - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH: - /* forward event */ - gst_pad_event_default (pad, event); - if (GST_EVENT_FLUSH_DONE (event)) { - if (identity->sink_mode == GST_ACTIVATE_PULL) { - /* already have the sink stream lock */ - gst_task_start (GST_RPAD_TASK (identity->sinkpad)); - } - if (identity->src_mode == GST_ACTIVATE_PUSH) { - GST_STREAM_LOCK (identity->srcpad); - gst_task_start (GST_RPAD_TASK (identity->srcpad)); - GST_STREAM_UNLOCK (identity->srcpad); - } - } else { - /* unblock both functions */ - identity_queue_flush (identity); - - } - ret = TRUE; - goto done; - case GST_EVENT_EOS: - if (identity->sink_mode == GST_ACTIVATE_PULL) { - /* already have the sink stream lock */ - gst_task_pause (GST_RPAD_TASK (identity->sinkpad)); - } - break; - default: - break; - } - - if (identity->decoupled) { - ret = identity_queue_push (identity, (GstData *) event); - } else { - ret = gst_pad_push_event (identity->srcpad, event); - } - -done: - GST_STREAM_UNLOCK (pad); - return ret; -} - -static GstFlowReturn -gst_identity_getrange (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer) -{ - GstIdentity *identity; - GstFlowReturn ret; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - ret = gst_pad_pull_range (identity->sinkpad, offset, length, buffer); - - GST_STREAM_UNLOCK (pad); - - return ret; -} - -static GstFlowReturn -gst_identity_chain (GstPad * pad, GstBuffer * buffer) -{ - GstIdentity *identity; - GstFlowReturn ret = GST_FLOW_OK; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - ret = gst_identity_handle_buffer (identity, buffer); - - GST_STREAM_UNLOCK (pad); - - return ret; + return TRUE; } -#define DEFAULT_PULL_SIZE 1024 - static void -gst_identity_sink_loop (GstPad * pad) +gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf) { - GstIdentity *identity; - GstBuffer *buffer; - GstFlowReturn ret; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - ret = gst_pad_pull_range (pad, identity->offset, DEFAULT_PULL_SIZE, &buffer); - if (ret != GST_FLOW_OK) - goto sink_loop_pause; - - ret = gst_identity_handle_buffer (identity, buffer); - if (ret != GST_FLOW_OK) - goto sink_loop_pause; - - GST_STREAM_UNLOCK (pad); - return; - -sink_loop_pause: - gst_task_pause (GST_RPAD_TASK (identity->sinkpad)); - GST_STREAM_UNLOCK (pad); - return; -} + GstClockTime timestamp; -static void -gst_identity_src_loop (GstPad * pad) -{ - GstIdentity *identity; - GstData *data; - GstFlowReturn ret; - - identity = GST_IDENTITY (GST_PAD_PARENT (pad)); - - GST_STREAM_LOCK (pad); - - data = identity_queue_pop (identity); - if (!data) /* we're getting flushed */ - goto src_loop_pause; - - if (GST_IS_EVENT (data)) { - if (GST_EVENT_TYPE (data) == GST_EVENT_EOS) - gst_task_pause (GST_RPAD_TASK (identity->srcpad)); - gst_pad_push_event (identity->srcpad, GST_EVENT (data)); - } else { - ret = gst_pad_push (identity->srcpad, (GstBuffer *) data); - if (ret != GST_FLOW_OK) - goto src_loop_pause; - } - - GST_STREAM_UNLOCK (pad); - return; - -src_loop_pause: - gst_task_pause (GST_RPAD_TASK (identity->srcpad)); - GST_STREAM_UNLOCK (pad); - return; -} - -static GstFlowReturn -gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) -{ - GstFlowReturn ret = GST_FLOW_OK; - guint i; + timestamp = GST_BUFFER_TIMESTAMP (buf); /* see if we need to do perfect stream checking */ /* invalid timestamp drops us out of check. FIXME: maybe warn ? */ - if (identity->check_perfect && - GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { + if (timestamp != GST_CLOCK_TIME_NONE) { /* check if we had a previous buffer to compare to */ if (identity->prev_timestamp != GST_CLOCK_TIME_NONE) { - if (identity->prev_timestamp + identity->prev_duration != - GST_BUFFER_TIMESTAMP (buf)) { + guint64 offset; + + if (identity->prev_timestamp + identity->prev_duration != timestamp) { GST_WARNING_OBJECT (identity, "Buffer not time-contiguous with previous one: " "prev ts %" GST_TIME_FORMAT ", prev dur %" GST_TIME_FORMAT ", new ts %" GST_TIME_FORMAT, GST_TIME_ARGS (identity->prev_timestamp), - GST_TIME_ARGS (identity->prev_duration), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + GST_TIME_ARGS (identity->prev_duration), GST_TIME_ARGS (timestamp)); } - if (identity->prev_offset_end != GST_BUFFER_OFFSET (buf)) { + + offset = GST_BUFFER_OFFSET (buf); + if (identity->prev_offset_end != offset) { GST_WARNING_OBJECT (identity, "Buffer not data-contiguous with previous one: " "prev offset_end %" G_GINT64_FORMAT ", new offset %" - G_GINT64_FORMAT, identity->prev_offset_end, - GST_BUFFER_OFFSET (buf)); + G_GINT64_FORMAT, identity->prev_offset_end, offset); } } /* update prev values */ - identity->prev_timestamp = GST_BUFFER_TIMESTAMP (buf); + identity->prev_timestamp = timestamp; identity->prev_duration = GST_BUFFER_DURATION (buf); identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf); } +} + +static GstFlowReturn +gst_identity_transform (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer ** outbuf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstIdentity *identity = GST_IDENTITY (trans); + guint i; + + if (identity->check_perfect) + gst_identity_check_perfect (identity, inbuf); if (identity->error_after >= 0) { identity->error_after--; if (identity->error_after == 0) { - gst_buffer_unref (buf); GST_ELEMENT_ERROR (identity, CORE, FAILED, (_("Failed after iterations as requested.")), (NULL)); return GST_FLOW_ERROR; @@ -543,18 +291,18 @@ gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) g_strdup_printf ("dropping ******* (%s:%s)i (%d bytes, timestamp: %" GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %" G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", - GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf); + GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)), + GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf), + GST_BUFFER_FLAGS (inbuf), inbuf); g_object_notify (G_OBJECT (identity), "last-message"); - gst_buffer_unref (buf); return GST_FLOW_OK; } } if (identity->dump) { - gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_util_dump_mem (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); } for (i = identity->duplicate; i; i--) { @@ -566,77 +314,49 @@ gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, timestamp: %" GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %" G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", - GST_DEBUG_PAD_NAME (identity->sinkpad), GST_BUFFER_SIZE (buf), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf); + GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (inbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)), + GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf), + GST_BUFFER_FLAGS (inbuf), inbuf); g_object_notify (G_OBJECT (identity), "last-message"); } - time = GST_BUFFER_TIMESTAMP (buf); + time = GST_BUFFER_TIMESTAMP (inbuf); if (identity->datarate > 0) { time = identity->offset * GST_SECOND / identity->datarate; - GST_BUFFER_TIMESTAMP (buf) = time; - GST_BUFFER_DURATION (buf) = - GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate; + GST_BUFFER_TIMESTAMP (inbuf) = time; + GST_BUFFER_DURATION (inbuf) = + GST_BUFFER_SIZE (inbuf) * GST_SECOND / identity->datarate; } g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0, - buf); + inbuf); if (i > 1) - gst_buffer_ref (buf); + gst_buffer_ref (inbuf); if (identity->sync) { - if (identity->clock) { + if (GST_ELEMENT (identity)->clock) { /* gst_element_wait (GST_ELEMENT (identity), time); */ } } - identity->offset += GST_BUFFER_SIZE (buf); - if (identity->decoupled) { - if (!identity_queue_push (identity, (GstData *) buf)) - return GST_FLOW_UNEXPECTED; - } else { - ret = gst_pad_push (identity->srcpad, buf); - if (ret != GST_FLOW_OK) - return ret; - } + identity->offset += GST_BUFFER_SIZE (inbuf); if (identity->sleep_time) g_usleep (identity->sleep_time); + + gst_buffer_ref (inbuf); + *outbuf = inbuf; } return ret; } static void -gst_identity_set_dataflow_funcs (GstIdentity * identity) -{ - if (identity->has_getrange) - gst_pad_set_getrange_function (identity->srcpad, gst_identity_getrange); - else - gst_pad_set_getrange_function (identity->srcpad, NULL); - - if (identity->has_chain) - gst_pad_set_chain_function (identity->sinkpad, gst_identity_chain); - else - gst_pad_set_chain_function (identity->sinkpad, NULL); - - if (identity->has_src_loop) - gst_pad_set_loop_function (identity->srcpad, gst_identity_src_loop); - else - gst_pad_set_loop_function (identity->srcpad, NULL); - - if (identity->has_sink_loop) - gst_pad_set_loop_function (identity->sinkpad, gst_identity_sink_loop); - else - gst_pad_set_loop_function (identity->sinkpad, NULL); -} - -static void gst_identity_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { @@ -645,22 +365,6 @@ gst_identity_set_property (GObject * object, guint prop_id, identity = GST_IDENTITY (object); switch (prop_id) { - case PROP_HAS_GETRANGE: - identity->has_getrange = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; - case PROP_HAS_CHAIN: - identity->has_chain = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; - case PROP_HAS_SRC_LOOP: - identity->has_src_loop = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; - case PROP_HAS_SINK_LOOP: - identity->has_sink_loop = g_value_get_boolean (value); - gst_identity_set_dataflow_funcs (identity); - break; case PROP_SLEEP_TIME: identity->sleep_time = g_value_get_uint (value); break; @@ -703,18 +407,6 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value, identity = GST_IDENTITY (object); switch (prop_id) { - case PROP_HAS_GETRANGE: - g_value_set_boolean (value, identity->has_getrange); - break; - case PROP_HAS_CHAIN: - g_value_set_boolean (value, identity->has_chain); - break; - case PROP_HAS_SRC_LOOP: - g_value_set_boolean (value, identity->has_src_loop); - break; - case PROP_HAS_SINK_LOOP: - g_value_set_boolean (value, identity->has_sink_loop); - break; case PROP_SLEEP_TIME: g_value_set_uint (value, identity->sleep_time); break; @@ -755,12 +447,15 @@ static GstElementStateReturn gst_identity_change_state (GstElement * element) { GstIdentity *identity; + GstElementState transition; + GstElementStateReturn result; g_return_val_if_fail (GST_IS_IDENTITY (element), GST_STATE_FAILURE); identity = GST_IDENTITY (element); + transition = GST_STATE_TRANSITION (element); - switch (GST_STATE_TRANSITION (element)) { + switch (transition) { case GST_STATE_NULL_TO_READY: break; case GST_STATE_READY_TO_PAUSED: @@ -770,6 +465,14 @@ gst_identity_change_state (GstElement * element) identity->prev_offset_end = -1; break; case GST_STATE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { case GST_STATE_PLAYING_TO_PAUSED: break; case GST_STATE_PAUSED_TO_READY: @@ -782,8 +485,5 @@ gst_identity_change_state (GstElement * element) break; } - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - - return GST_STATE_SUCCESS; + return result; } diff --git a/plugins/elements/gstidentity.h b/plugins/elements/gstidentity.h index e187f2e..4a51a07 100644 --- a/plugins/elements/gstidentity.h +++ b/plugins/elements/gstidentity.h @@ -26,6 +26,7 @@ #include +#include G_BEGIN_DECLS @@ -45,24 +46,8 @@ typedef struct _GstIdentity GstIdentity; typedef struct _GstIdentityClass GstIdentityClass; struct _GstIdentity { - GstElement element; + GstBaseTransform element; - GstPad *sinkpad; - GstPad *srcpad; - - GstData *pen_data; - GMutex *pen_lock; - GCond *pen_cond; - gboolean pen_flushing; - - gboolean has_chain; - gboolean has_getrange; - gboolean has_src_loop; - gboolean has_sink_loop; - GstActivateMode sink_mode; - GstActivateMode src_mode; - gboolean decoupled; - guint duplicate; gint error_after; gfloat drop_probability; @@ -75,15 +60,12 @@ struct _GstIdentity { GstClockTime prev_timestamp; GstClockTime prev_duration; guint64 prev_offset_end; - GstClock *clock; gchar *last_message; - GstCaps *srccaps; - - guint64 offset; + guint64 offset; }; struct _GstIdentityClass { - GstElementClass parent_class; + GstBaseTransformClass parent_class; /* signals */ void (*handoff) (GstElement *element, GstBuffer *buf); -- 2.7.4