From 9dfa6cd089464ea5792092dea66f13693b3f5455 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 23 Apr 2005 23:29:47 +0000 Subject: [PATCH] gst/elements/: New element that acts like an identity, but filters caps. Will eventually replace filtered caps in pa... Original commit message from CVS: * gst/elements/Makefile.am: * gst/elements/gstcapsfilter.c: New element that acts like an identity, but filters caps. Will eventually replace filtered caps in pad linking. * gst/gstutils.c: (gst_element_create_all_pads): New function to create all the ALWAYS pads that are registered with an element class. This functionality should eventually be merged in with GstElement initialization. * gst/gstutils.h: * testsuite/trigger/README: part of trigger test code that should have been checked in a long time ago. --- ChangeLog | 14 ++ gst/elements/Makefile.am | 2 + gst/elements/gstcapsfilter.c | 230 +++++++++++++++++++++++++++++ gst/gstutils.c | 32 ++++ gst/gstutils.h | 1 + plugins/elements/Makefile.am | 2 + plugins/elements/gstcapsfilter.c | 230 +++++++++++++++++++++++++++++ tests/old/testsuite/trigger/README | 24 +++ testsuite/trigger/README | 24 +++ 9 files changed, 559 insertions(+) create mode 100644 gst/elements/gstcapsfilter.c create mode 100644 plugins/elements/gstcapsfilter.c create mode 100644 tests/old/testsuite/trigger/README create mode 100644 testsuite/trigger/README diff --git a/ChangeLog b/ChangeLog index b25951fcb1..2f66eb1114 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2005-04-23 David Schleef + + * gst/elements/Makefile.am: + * gst/elements/gstcapsfilter.c: New element that acts like an + identity, but filters caps. Will eventually replace filtered + caps in pad linking. + * gst/gstutils.c: (gst_element_create_all_pads): New function + to create all the ALWAYS pads that are registered with an + element class. This functionality should eventually be + merged in with GstElement initialization. + * gst/gstutils.h: + * testsuite/trigger/README: part of trigger test code that should + have been checked in a long time ago. + 2005-04-23 David Schleef * gst/Makefile.am: Remove as-libtool stuff. It's likely not diff --git a/gst/elements/Makefile.am b/gst/elements/Makefile.am index 79286f0d64..2d631c75ab 100644 --- a/gst/elements/Makefile.am +++ b/gst/elements/Makefile.am @@ -12,6 +12,7 @@ pipefilter = gstpipefilter.c libgstelements_la_DEPENDENCIES = ../libgstreamer-@GST_MAJORMINOR@.la libgstelements_la_SOURCES = \ gstbufferstore.c \ + gstcapsfilter.c \ gstfakesrc.c \ gstfakesink.c \ gstfilesrc.c \ @@ -25,6 +26,7 @@ libgstelements_la_SOURCES = \ # these files above, then this will be unnecessary EXTRA_DIST = \ gstaggregator.c \ + gstcapsfilter.c \ gstfilesink.c \ gstfdsink.c \ gstfdsrc.c \ diff --git a/gst/elements/gstcapsfilter.c b/gst/elements/gstcapsfilter.c new file mode 100644 index 0000000000..b6e7774a2f --- /dev/null +++ b/gst/elements/gstcapsfilter.c @@ -0,0 +1,230 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * 2005 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "../gst-i18n-lib.h" +#include +#include + + +#define GST_TYPE_CAPSFILTER \ + (gst_capsfilter_get_type()) +#define GST_CAPSFILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAPSFILTER,GstCapsFilter)) +#define GST_CAPSFILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAPSFILTER,GstCapsFilterClass)) +#define GST_IS_CAPSFILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAPSFILTER)) +#define GST_IS_CAPSFILTER_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAPSFILTER)) + +typedef struct _GstCapsFilter GstCapsFilter; +typedef struct _GstCapsFilterClass GstCapsFilterClass; + +struct _GstCapsFilter +{ + GstElement element; + + GstPad *srcpad; + GstPad *sinkpad; + + GstCaps *filter_caps; +}; + +struct _GstCapsFilterClass +{ + GstElementClass element_class; + +}; + +GType gst_capsfilter_get_type (void); + + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_capsfilter_debug); +#define GST_CAT_DEFAULT gst_capsfilter_debug + +GstElementDetails gst_capsfilter_details = GST_ELEMENT_DETAILS ("CapsFilter", + "Generic", + "Pass data without modification, limiting formats", + "David Schleef "); + +enum +{ + PROP_0, + PROP_FILTER_CAPS +}; + + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, "capsfilter element"); + +GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstElement, + GST_TYPE_ELEMENT, _do_init); + +static void gst_capsfilter_finalize (GObject * object); +static void gst_capsfilter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_capsfilter_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstCaps *gst_capsfilter_getcaps (GstPad * pad); +static GstFlowReturn gst_capsfilter_chain (GstPad * pad, GstBuffer * buf); + +static void +gst_capsfilter_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 (&srctemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + gst_element_class_set_details (gstelement_class, &gst_capsfilter_details); +} + +static void +gst_capsfilter_finalize (GObject * object) +{ + GstCapsFilter *capsfilter; + + capsfilter = GST_CAPSFILTER (object); + + gst_caps_unref (capsfilter->filter_caps); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_capsfilter_class_init (GstCapsFilterClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_capsfilter_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_capsfilter_get_property); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_capsfilter_finalize); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILTER_CAPS, + g_param_spec_boxed ("filter_caps", _("Filter caps"), + _("Caps to use to filter the possible allowed formats"), + GST_TYPE_CAPS, G_PARAM_READWRITE)); +} + +static void +gst_capsfilter_init (GstCapsFilter * capsfilter) +{ + gst_element_create_all_pads (GST_ELEMENT (capsfilter)); + + capsfilter->srcpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "src"); + capsfilter->sinkpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "sink"); + + gst_pad_set_getcaps_function (capsfilter->srcpad, gst_capsfilter_getcaps); + + gst_pad_set_getcaps_function (capsfilter->sinkpad, gst_capsfilter_getcaps); + gst_pad_set_chain_function (capsfilter->sinkpad, gst_capsfilter_chain); + + capsfilter->filter_caps = gst_caps_new_any (); +} + +static GstCaps * +gst_capsfilter_getcaps (GstPad * pad) +{ + GstPad *otherpad; + GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_OBJECT_PARENT (pad)); + GstCaps *caps; + GstCaps *icaps; + + otherpad = (pad == capsfilter->srcpad) ? capsfilter->sinkpad : + capsfilter->srcpad; + + caps = gst_pad_peer_get_caps (otherpad); + icaps = gst_caps_intersect (caps, capsfilter->filter_caps); + gst_caps_unref (caps); + + return icaps; +} + +static GstFlowReturn +gst_capsfilter_chain (GstPad * pad, GstBuffer * buf) +{ + GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_PAD_PARENT (pad)); + + gst_pad_push (capsfilter->srcpad, buf); + + return GST_FLOW_OK; +} + +static void +gst_capsfilter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCapsFilter *capsfilter; + + capsfilter = GST_CAPSFILTER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS: + capsfilter->filter_caps = gst_caps_copy (gst_value_get_caps (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_capsfilter_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstCapsFilter *capsfilter; + + capsfilter = GST_CAPSFILTER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS: + gst_value_set_caps (value, capsfilter->filter_caps); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst/gstutils.c b/gst/gstutils.c index 10ac425c44..244bc34ddc 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -370,6 +370,38 @@ gst_print_element_args (GString * buf, gint indent, GstElement * element) g_free (specs); } +/** + * gst_element_create_all_pads: + * @element: a #GstElement to create pads for + * + * Creates a pad for each pad template that is always available. + * This function is only useful during object intialization of + * subclasses of #GstElement. + */ +void +gst_element_create_all_pads (GstElement * element) +{ + GList *padlist; + + /* FIXME: lock element */ + + padlist = + gst_element_class_get_pad_template_list (GST_ELEMENT_CLASS + (G_OBJECT_GET_CLASS (element))); + + while (padlist) { + GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data; + + if (padtempl->presence == GST_PAD_ALWAYS) { + GstPad *pad; + + pad = gst_pad_new_from_template (padtempl, padtempl->name_template); + + gst_element_add_pad (element, pad); + } + } +} + /** * gst_element_get_compatible_pad_template: * @element: a #GstElement to get a compatible pad template for. diff --git a/gst/gstutils.h b/gst/gstutils.h index e323fa07c2..2b00ed02ad 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -232,6 +232,7 @@ void gst_object_default_error (GstObject * source, GstFlowReturn gst_element_abort_preroll (GstElement *element); GstFlowReturn gst_element_finish_preroll (GstElement *element, GstPad *pad); +void gst_element_create_all_pads (GstElement *element); GstPad* gst_element_get_compatible_pad (GstElement *element, GstPad *pad); GstPad* gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, const GstCaps *filtercaps); diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am index 79286f0d64..2d631c75ab 100644 --- a/plugins/elements/Makefile.am +++ b/plugins/elements/Makefile.am @@ -12,6 +12,7 @@ pipefilter = gstpipefilter.c libgstelements_la_DEPENDENCIES = ../libgstreamer-@GST_MAJORMINOR@.la libgstelements_la_SOURCES = \ gstbufferstore.c \ + gstcapsfilter.c \ gstfakesrc.c \ gstfakesink.c \ gstfilesrc.c \ @@ -25,6 +26,7 @@ libgstelements_la_SOURCES = \ # these files above, then this will be unnecessary EXTRA_DIST = \ gstaggregator.c \ + gstcapsfilter.c \ gstfilesink.c \ gstfdsink.c \ gstfdsrc.c \ diff --git a/plugins/elements/gstcapsfilter.c b/plugins/elements/gstcapsfilter.c new file mode 100644 index 0000000000..b6e7774a2f --- /dev/null +++ b/plugins/elements/gstcapsfilter.c @@ -0,0 +1,230 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * 2005 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "../gst-i18n-lib.h" +#include +#include + + +#define GST_TYPE_CAPSFILTER \ + (gst_capsfilter_get_type()) +#define GST_CAPSFILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAPSFILTER,GstCapsFilter)) +#define GST_CAPSFILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAPSFILTER,GstCapsFilterClass)) +#define GST_IS_CAPSFILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAPSFILTER)) +#define GST_IS_CAPSFILTER_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAPSFILTER)) + +typedef struct _GstCapsFilter GstCapsFilter; +typedef struct _GstCapsFilterClass GstCapsFilterClass; + +struct _GstCapsFilter +{ + GstElement element; + + GstPad *srcpad; + GstPad *sinkpad; + + GstCaps *filter_caps; +}; + +struct _GstCapsFilterClass +{ + GstElementClass element_class; + +}; + +GType gst_capsfilter_get_type (void); + + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_capsfilter_debug); +#define GST_CAT_DEFAULT gst_capsfilter_debug + +GstElementDetails gst_capsfilter_details = GST_ELEMENT_DETAILS ("CapsFilter", + "Generic", + "Pass data without modification, limiting formats", + "David Schleef "); + +enum +{ + PROP_0, + PROP_FILTER_CAPS +}; + + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, "capsfilter element"); + +GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstElement, + GST_TYPE_ELEMENT, _do_init); + +static void gst_capsfilter_finalize (GObject * object); +static void gst_capsfilter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_capsfilter_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstCaps *gst_capsfilter_getcaps (GstPad * pad); +static GstFlowReturn gst_capsfilter_chain (GstPad * pad, GstBuffer * buf); + +static void +gst_capsfilter_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 (&srctemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + gst_element_class_set_details (gstelement_class, &gst_capsfilter_details); +} + +static void +gst_capsfilter_finalize (GObject * object) +{ + GstCapsFilter *capsfilter; + + capsfilter = GST_CAPSFILTER (object); + + gst_caps_unref (capsfilter->filter_caps); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_capsfilter_class_init (GstCapsFilterClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_capsfilter_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_capsfilter_get_property); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_capsfilter_finalize); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILTER_CAPS, + g_param_spec_boxed ("filter_caps", _("Filter caps"), + _("Caps to use to filter the possible allowed formats"), + GST_TYPE_CAPS, G_PARAM_READWRITE)); +} + +static void +gst_capsfilter_init (GstCapsFilter * capsfilter) +{ + gst_element_create_all_pads (GST_ELEMENT (capsfilter)); + + capsfilter->srcpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "src"); + capsfilter->sinkpad = gst_element_get_pad (GST_ELEMENT (capsfilter), "sink"); + + gst_pad_set_getcaps_function (capsfilter->srcpad, gst_capsfilter_getcaps); + + gst_pad_set_getcaps_function (capsfilter->sinkpad, gst_capsfilter_getcaps); + gst_pad_set_chain_function (capsfilter->sinkpad, gst_capsfilter_chain); + + capsfilter->filter_caps = gst_caps_new_any (); +} + +static GstCaps * +gst_capsfilter_getcaps (GstPad * pad) +{ + GstPad *otherpad; + GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_OBJECT_PARENT (pad)); + GstCaps *caps; + GstCaps *icaps; + + otherpad = (pad == capsfilter->srcpad) ? capsfilter->sinkpad : + capsfilter->srcpad; + + caps = gst_pad_peer_get_caps (otherpad); + icaps = gst_caps_intersect (caps, capsfilter->filter_caps); + gst_caps_unref (caps); + + return icaps; +} + +static GstFlowReturn +gst_capsfilter_chain (GstPad * pad, GstBuffer * buf) +{ + GstCapsFilter *capsfilter = GST_CAPSFILTER (GST_PAD_PARENT (pad)); + + gst_pad_push (capsfilter->srcpad, buf); + + return GST_FLOW_OK; +} + +static void +gst_capsfilter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCapsFilter *capsfilter; + + capsfilter = GST_CAPSFILTER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS: + capsfilter->filter_caps = gst_caps_copy (gst_value_get_caps (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_capsfilter_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstCapsFilter *capsfilter; + + capsfilter = GST_CAPSFILTER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS: + gst_value_set_caps (value, capsfilter->filter_caps); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/tests/old/testsuite/trigger/README b/tests/old/testsuite/trigger/README new file mode 100644 index 0000000000..a6f56ee71f --- /dev/null +++ b/tests/old/testsuite/trigger/README @@ -0,0 +1,24 @@ + + +caps issues: + + - We can't really tell until PAUSED that 'sinesrc ! identity ! ximagesink' + will fail (since identity has ANY as the pad template caps). + Because of this, it's nearly useless to perform the pad + template check. + + Alternatives: + + proxy pad template caps, but that reinstates the O(N^2) issue + in 0.8 during linking lots of elements. + + remove checking of pad template caps compatibility + + add a means of checking a pipeline for caps compatibility before + setting to PAUSED (ugly, requires special processing in each + element) + + + + + diff --git a/testsuite/trigger/README b/testsuite/trigger/README new file mode 100644 index 0000000000..a6f56ee71f --- /dev/null +++ b/testsuite/trigger/README @@ -0,0 +1,24 @@ + + +caps issues: + + - We can't really tell until PAUSED that 'sinesrc ! identity ! ximagesink' + will fail (since identity has ANY as the pad template caps). + Because of this, it's nearly useless to perform the pad + template check. + + Alternatives: + + proxy pad template caps, but that reinstates the O(N^2) issue + in 0.8 during linking lots of elements. + + remove checking of pad template caps compatibility + + add a means of checking a pipeline for caps compatibility before + setting to PAUSED (ugly, requires special processing in each + element) + + + + +