diff options
author | Dave Robillard <dave@drobilla.net> | 2009-07-03 20:01:30 -0400 |
---|---|---|
committer | Dave Robillard <dave@drobilla.net> | 2009-07-03 20:01:30 -0400 |
commit | caba48f261421d397900471b19350da2e5a4a4e5 (patch) | |
tree | ace87e1bd5c819454aefaa722203c30ed83f4ec1 /gst/debugutils/gstcapssetter.c | |
parent | 699e4f4d044d8111053b631baba4b324a60b1274 (diff) | |
parent | 6a763f6a471e9fbbd86358b0175498a6af78666e (diff) | |
download | gst-plugins-bad-caba48f261421d397900471b19350da2e5a4a4e5.tar.gz gst-plugins-bad-caba48f261421d397900471b19350da2e5a4a4e5.tar.bz2 gst-plugins-bad-caba48f261421d397900471b19350da2e5a4a4e5.zip |
Merge branch 'master' of git://anongit.freedesktop.org/gstreamer/gst-plugins-bad into fdo
Diffstat (limited to 'gst/debugutils/gstcapssetter.c')
-rw-r--r-- | gst/debugutils/gstcapssetter.c | 350 |
1 files changed, 350 insertions, 0 deletions
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 <mnauw@users.sourceforge.net> + * + * 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 + * + * <refsect2> + * <para> + * Sets or merges caps on a stream's buffers. + * That is, a buffer's caps are updated using (fields of) + * <link linkend="GstCapsSetter--caps">caps</link>. Note that this may + * contain multiple structures (though not likely recommended), but each + * of these must be fixed (or will otherwise be rejected). + * </para> + * <para> + * If <link linkend="GstCapsSetter--join">join</link> + * 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. + * </para> + * <para> + * If <link linkend="GstCapsSetter--replace">replace</link> + * 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 + * </para> + * <para> + * 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. + * </para> + * </refsect2> + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstcapssetter.h" + +#include <string.h> + + +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 <mnauw@users.sourceforge.net>"); + +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; + } +} |