From 8241b05038211b1a99985678b17b827d7405d72a Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 25 Jun 2009 16:41:49 +0200 Subject: capssetter: import element into -bad --- docs/plugins/Makefile.am | 1 + docs/plugins/gst-plugins-bad-plugins-docs.sgml | 1 + docs/plugins/gst-plugins-bad-plugins-sections.txt | 14 + docs/plugins/gst-plugins-bad-plugins.args | 29 ++ docs/plugins/gst-plugins-bad-plugins.hierarchy | 1 + docs/plugins/inspect/plugin-debugutilsbad.xml | 21 ++ gst/debugutils/Makefile.am | 4 +- gst/debugutils/debugutilsbad.c | 5 +- gst/debugutils/gstcapssetter.c | 350 ++++++++++++++++++++++ gst/debugutils/gstcapssetter.h | 62 ++++ 10 files changed, 485 insertions(+), 3 deletions(-) create mode 100644 gst/debugutils/gstcapssetter.c create mode 100644 gst/debugutils/gstcapssetter.h diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 03b2e71c..30fd9422 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -124,6 +124,7 @@ EXTRA_HFILES = \ $(top_srcdir)/gst/dccp/gstdccpserversink.h \ $(top_srcdir)/gst/dccp/gstdccpserversrc.h \ $(top_srcdir)/gst/debugutils/fpsdisplaysink.h \ + $(top_srcdir)/gst/debugutils/gstcapssetter.h \ $(top_srcdir)/gst/dtmf/gstdtmfsrc.h \ $(top_srcdir)/gst/dtmf/gstrtpdtmfsrc.h \ $(top_srcdir)/gst/dtmf/gstrtpdtmfdepay.h \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index 959c9cb1..0557d27c 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -25,6 +25,7 @@ + diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index 70afb729..8f748c6f 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -111,6 +111,20 @@ GST_IS_CAMERABIN_CLASS gst_camerabin_get_type +
+element-capssetter +capssetter +GstCapsSetter + +GstCapsSetterClass +GST_TYPE_CAPS_SETTER +GST_CAPS_SETTER +GST_IS_CAPS_SETTER +GST_CAPS_SETTER_CLASS +GST_IS_CAPS_SETTER_CLASS +gst_caps_setter_get_type +
+
element-celtdec celtdec diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index b13244f2..82bcfd30 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -23503,3 +23503,32 @@ TRUE + +GstCapsSetter::caps +GstCaps* + +rw +Merge caps +Merge these caps (thereby overwriting) in the stream. + + + + +GstCapsSetter::join +gboolean + +rw +Join +Match incoming caps' mime-type to mime-type of provided caps. +TRUE + + + +GstCapsSetter::replace +gboolean + +rw +Replace +Drop fields of incoming caps. +FALSE + diff --git a/docs/plugins/gst-plugins-bad-plugins.hierarchy b/docs/plugins/gst-plugins-bad-plugins.hierarchy index a1204ca6..daf967df 100644 --- a/docs/plugins/gst-plugins-bad-plugins.hierarchy +++ b/docs/plugins/gst-plugins-bad-plugins.hierarchy @@ -76,6 +76,7 @@ GObject GstVideoMark GstIIR GstLegacyresample + GstCapsSetter GstSignalProcessor ladspa-noise-white ladspa-delay-5s diff --git a/docs/plugins/inspect/plugin-debugutilsbad.xml b/docs/plugins/inspect/plugin-debugutilsbad.xml index 0aabef1a..ff6d4b92 100644 --- a/docs/plugins/inspect/plugin-debugutilsbad.xml +++ b/docs/plugins/inspect/plugin-debugutilsbad.xml @@ -9,6 +9,27 @@ GStreamer Bad Plug-ins source release Unknown package origin + + capssetter + CapsSetter + Generic + Set/merge caps on stream + Mark Nauwelaerts <mnauw@users.sourceforge.net> + + + src + source + always +
ANY
+
+ + sink + sink + always +
ANY
+
+
+
fpsdisplaysink Measure and show framerate on videosink diff --git a/gst/debugutils/Makefile.am b/gst/debugutils/Makefile.am index 3b93fa91..60fb794a 100644 --- a/gst/debugutils/Makefile.am +++ b/gst/debugutils/Makefile.am @@ -1,10 +1,10 @@ plugin_LTLIBRARIES = libgstdebugutilsbad.la -libgstdebugutilsbad_la_SOURCES = fpsdisplaysink.c debugutilsbad.c +libgstdebugutilsbad_la_SOURCES = fpsdisplaysink.c gstcapssetter.c debugutilsbad.c libgstdebugutilsbad_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) libgstdebugutilsbad_la_LIBADD = $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) libgstdebugutilsbad_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstdebugutilsbad_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = fpsdisplaysink.h +noinst_HEADERS = fpsdisplaysink.h gstcapssetter.h diff --git a/gst/debugutils/debugutilsbad.c b/gst/debugutils/debugutilsbad.c index b1fb6e05..d1b10263 100644 --- a/gst/debugutils/debugutilsbad.c +++ b/gst/debugutils/debugutilsbad.c @@ -24,12 +24,15 @@ #include GType fps_display_sink_get_type (void); +GType gst_caps_setter_get_type (void); static gboolean plugin_init (GstPlugin * plugin) { return gst_element_register (plugin, "fpsdisplaysink", GST_RANK_NONE, - fps_display_sink_get_type ()); + fps_display_sink_get_type ()) && + gst_element_register (plugin, "capssetter", GST_RANK_NONE, + gst_caps_setter_get_type ()); } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, diff --git a/gst/debugutils/gstcapssetter.c b/gst/debugutils/gstcapssetter.c new file mode 100644 index 00000000..12077c0d --- /dev/null +++ b/gst/debugutils/gstcapssetter.c @@ -0,0 +1,350 @@ +/* GStreamer Element + * Copyright (C) 2006-2009 Mark Nauwelaerts + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1307, USA. + */ + +/** + * SECTION:element-capssetter + * + * + * + * Sets or merges caps on a stream's buffers. + * That is, a buffer's caps are updated using (fields of) + * caps. Note that this may + * contain multiple structures (though not likely recommended), but each + * of these must be fixed (or will otherwise be rejected). + * + * + * If join + * is TRUE, then the incoming caps' mime-type is compared to the mime-type(s) + * of provided caps and only matching structure(s) are considered for updating. + * + * + * If replace + * is TRUE, then any caps update is preceded by clearing existing fields, + * making provided fields (as a whole) replace incoming ones. + * Otherwise, no clearing is performed, in which case provided fields are + * added/merged onto incoming caps + * + * + * Although this element might mainly serve as debug helper, + * it can also practically be used to correct a faulty pixel-aspect-ratio, + * or to modify a yuv fourcc value to effectively swap chroma components or such + * alike. + * + * + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstcapssetter.h" + +#include + + +GST_DEBUG_CATEGORY_STATIC (caps_setter_debug); +#define GST_CAT_DEFAULT caps_setter_debug + + +/* signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_CAPS, + PROP_JOIN, + PROP_REPLACE + /* FILL ME */ +}; + +#define DEFAULT_JOIN TRUE +#define DEFAULT_REPLACE FALSE + +static GstElementDetails caps_setter_details = +GST_ELEMENT_DETAILS ("CapsSetter", + "Generic", + "Set/merge caps on stream", + "Mark Nauwelaerts "); + +static GstStaticPadTemplate gst_caps_setter_src_template = +GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME, + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_caps_setter_sink_template = +GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SINK_NAME, + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +static gboolean gst_caps_setter_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, guint size, + GstCaps * othercaps, guint * othersize); +static GstCaps *gst_caps_setter_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps); +static GstFlowReturn gst_caps_setter_transform_ip (GstBaseTransform * btrans, + GstBuffer * in); + +static void gst_caps_setter_finalize (GObject * object); + +static void gst_caps_setter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_caps_setter_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GST_BOILERPLATE (GstCapsSetter, gst_caps_setter, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); + +static void +gst_caps_setter_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details (element_class, &caps_setter_details); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_caps_setter_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_caps_setter_src_template)); +} + +static void +gst_caps_setter_class_init (GstCapsSetterClass * g_class) +{ + GObjectClass *gobject_class; + GstBaseTransformClass *trans_class; + + gobject_class = G_OBJECT_CLASS (g_class); + trans_class = GST_BASE_TRANSFORM_CLASS (g_class); + + GST_DEBUG_CATEGORY_INIT (caps_setter_debug, "capssetter", 0, "capssetter"); + + gobject_class->set_property = gst_caps_setter_set_property; + gobject_class->get_property = gst_caps_setter_get_property; + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_caps_setter_finalize); + + g_object_class_install_property (gobject_class, PROP_CAPS, + g_param_spec_boxed ("caps", "Merge caps", + "Merge these caps (thereby overwriting) in the stream", + GST_TYPE_CAPS, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_JOIN, + g_param_spec_boolean ("join", "Join", + "Match incoming caps' mime-type to mime-type of provided caps", + DEFAULT_JOIN, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_REPLACE, + g_param_spec_boolean ("replace", "Replace", + "Drop fields of incoming caps", DEFAULT_REPLACE, G_PARAM_READWRITE)); + + trans_class->transform_size = + GST_DEBUG_FUNCPTR (gst_caps_setter_transform_size); + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_caps_setter_transform_caps); + /* dummy seems needed */ + trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_caps_setter_transform_ip); +} + +static void +gst_caps_setter_init (GstCapsSetter * filter, GstCapsSetterClass * g_class) +{ + filter->caps = gst_caps_new_any (); + filter->join = DEFAULT_JOIN; + filter->replace = DEFAULT_REPLACE; +} + +static void +gst_caps_setter_finalize (GObject * object) +{ + GstCapsSetter *filter = GST_CAPS_SETTER (object); + + gst_caps_replace (&filter->caps, NULL); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_caps_setter_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, guint size, + GstCaps * othercaps, guint * othersize) +{ + *othersize = size; + + return TRUE; +} + +static GstCaps * +gst_caps_setter_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +{ + GstCapsSetter *filter; + GstCaps *ret, *filter_caps; + GstStructure *structure, *merge; + const gchar *name; + gint i, j; + + filter = GST_CAPS_SETTER (trans); + + GST_DEBUG_OBJECT (trans, "receiving caps: %" GST_PTR_FORMAT, caps); + + ret = gst_caps_copy (caps); + + /* this function is always called with a simple caps */ + if (!GST_CAPS_IS_SIMPLE (ret) || direction != GST_PAD_SINK) + return ret; + + structure = gst_caps_get_structure (ret, 0); + name = gst_structure_get_name (structure); + + GST_OBJECT_LOCK (filter); + filter_caps = gst_caps_ref (filter->caps); + GST_OBJECT_UNLOCK (filter); + + for (i = 0; i < gst_caps_get_size (filter_caps); ++i) { + merge = gst_caps_get_structure (filter_caps, i); + if (gst_structure_has_name (merge, name) || !filter->join) { + + if (!filter->join) + gst_structure_set_name (structure, gst_structure_get_name (merge)); + + if (filter->replace) + gst_structure_remove_all_fields (structure); + + for (j = 0; j < gst_structure_n_fields (merge); ++j) { + const gchar *fname; + + fname = gst_structure_nth_field_name (merge, j); + gst_structure_set_value (structure, fname, + gst_structure_get_value (merge, fname)); + } + } + } + + GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret); + + gst_caps_unref (filter_caps); + + return ret; +} + +static GstFlowReturn +gst_caps_setter_transform_ip (GstBaseTransform * btrans, GstBuffer * in) +{ + return GST_FLOW_OK; +} + +static gboolean +gst_caps_is_fixed_foreach (GQuark field_id, const GValue * value, + gpointer unused) +{ + return gst_value_is_fixed (value); +} + +static void +gst_caps_setter_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCapsSetter *filter; + + g_return_if_fail (GST_IS_CAPS_SETTER (object)); + filter = GST_CAPS_SETTER (object); + + switch (prop_id) { + case PROP_CAPS:{ + GstCaps *new_caps; + const GstCaps *new_caps_val = gst_value_get_caps (value); + gint i; + + if (new_caps_val == NULL) { + new_caps = gst_caps_new_any (); + } else { + new_caps = gst_caps_copy (new_caps_val); + } + + for (i = 0; new_caps && (i < gst_caps_get_size (new_caps)); ++i) { + GstStructure *s; + + s = gst_caps_get_structure (new_caps, i); + if (!gst_structure_foreach (s, gst_caps_is_fixed_foreach, NULL)) { + GST_ERROR_OBJECT (filter, "rejected unfixed caps: %" GST_PTR_FORMAT, + new_caps); + gst_caps_unref (new_caps); + new_caps = NULL; + break; + } + } + + if (new_caps) { + GST_OBJECT_LOCK (filter); + gst_caps_replace (&filter->caps, new_caps); + /* drop extra ref */ + gst_caps_unref (new_caps); + GST_OBJECT_UNLOCK (filter); + + GST_DEBUG_OBJECT (filter, "set new caps %" GST_PTR_FORMAT, new_caps); + } + + /* try to activate these new caps next time around */ + gst_base_transform_reconfigure (GST_BASE_TRANSFORM (filter)); + break; + } + case PROP_JOIN: + filter->join = g_value_get_boolean (value); + break; + case PROP_REPLACE: + filter->replace = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_caps_setter_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstCapsSetter *filter; + + g_return_if_fail (GST_IS_CAPS_SETTER (object)); + filter = GST_CAPS_SETTER (object); + + switch (prop_id) { + case PROP_CAPS: + gst_value_set_caps (value, filter->caps); + break; + case PROP_JOIN: + g_value_set_boolean (value, filter->join); + break; + case PROP_REPLACE: + g_value_set_boolean (value, filter->replace); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst/debugutils/gstcapssetter.h b/gst/debugutils/gstcapssetter.h new file mode 100644 index 00000000..e792931c --- /dev/null +++ b/gst/debugutils/gstcapssetter.h @@ -0,0 +1,62 @@ +/* GStreamer Element + * Copyright (C) 2006-2009 Mark Nauwelaerts + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1307, USA. + */ + + +#ifndef __GST_CAPS_SETTER_H__ +#define __GST_CAPS_SETTER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CAPS_SETTER \ + (gst_caps_setter_get_type()) +#define GST_CAPS_SETTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAPS_SETTER,GstCapsSetter)) +#define GST_CAPS_SETTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAPS_SETTER,GstCapsSetterClass)) +#define GST_IS_CAPS_SETTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAPS_SETTER)) +#define GST_IS_CAPS_SETTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAPS_SETTER)) + +GType gst_caps_setter_get_type (void); + +typedef struct _GstCapsSetter GstCapsSetter; +typedef struct _GstCapsSetterClass GstCapsSetterClass; + +struct _GstCapsSetter +{ + GstBaseTransform parent; + + /* properties */ + GstCaps *caps; + gboolean join; + gboolean replace; +}; + + +struct _GstCapsSetterClass +{ + GstBaseTransformClass parent_class; +}; + +G_END_DECLS + +#endif /* __GST_CAPS_SETTER_H__ */ -- cgit v1.2.1