mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-08 07:35:52 +00:00
c9f30f98b7
Original commit message from CVS: * gst/elements/gstcapsfilter.c: (gst_capsfilter_set_property): Free existing caps if the capsfilter changes. Add a FIXME about setting those caps on the pads. * gst/gstutils.c: (gst_element_get_compatible_pad), (ghost_up): Before adding a ghost pad to a parent bin, check that there isn't already one for the element on the bin. Prevents infinite recursion when using decodebin in parse pipelines. Andy says he'll rewrite the way this works anyway, so ignore the hack.
242 lines
6.7 KiB
C
242 lines
6.7 KiB
C
/* GStreamer
|
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
|
* 2000 Wim Taymans <wtay@chello.be>
|
|
* 2005 Wim Taymans <wim@fluendo.com>
|
|
* 2005 David Schleef <ds@schleef.org>
|
|
*
|
|
* 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 <stdlib.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include "../gst-i18n-lib.h"
|
|
#include <gst/gstmarshal.h>
|
|
#include <gst/gst.h>
|
|
|
|
|
|
#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 <ds@schleef.org>");
|
|
|
|
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);
|
|
if (caps == NULL)
|
|
caps = gst_caps_new_any ();
|
|
|
|
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:{
|
|
GstCaps *new_caps = gst_caps_copy (gst_value_get_caps (value));
|
|
|
|
g_return_if_fail (new_caps != NULL);
|
|
|
|
gst_caps_unref (capsfilter->filter_caps);
|
|
capsfilter->filter_caps = new_caps;
|
|
|
|
/* FIXME: Need to activate these caps on the pads */
|
|
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;
|
|
}
|
|
}
|