/* if we have a match, connect the pads */
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
- !GST_PAD_CONNECTED (pad) && !GST_PAD_CONNECTED(sinkpad))
+ !GST_PAD_IS_CONNECTED (pad) && !GST_PAD_IS_CONNECTED(sinkpad))
{
- if ((connected = gst_pad_try_connect (pad, sinkpad))) {
+ if ((connected = gst_pad_connect (pad, sinkpad))) {
break;
}
else {
return gst_pad_get_bufferpool (identity->srcpad);
}
-static GstPadNegotiateReturn
-gst_identity_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstIdentity *identity;
-
- identity = GST_IDENTITY (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, identity->sinkpad, caps);
-}
-
-static GstPadNegotiateReturn
-gst_identity_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstIdentity *identity;
-
- identity = GST_IDENTITY (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, identity->srcpad, caps);
-}
-
static void
gst_identity_init (GstIdentity *identity)
{
gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
gst_pad_set_chain_function (identity->sinkpad, GST_DEBUG_FUNCPTR (gst_identity_chain));
gst_pad_set_bufferpool_function (identity->sinkpad, gst_identity_get_bufferpool);
- gst_pad_set_negotiate_function (identity->sinkpad, gst_identity_negotiate_sink);
identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
- gst_pad_set_negotiate_function (identity->srcpad, gst_identity_negotiate_src);
identity->loop_based = FALSE;
identity->sleep_time = 0;
return gst_pad_get_bufferpool (statistics->srcpad);
}
-static GstPadNegotiateReturn
-gst_statistics_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstStatistics *statistics;
-
- statistics = GST_STATISTICS (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, statistics->sinkpad, caps);
-}
-
-static GstPadNegotiateReturn
-gst_statistics_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstStatistics *statistics;
-
- statistics = GST_STATISTICS (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, statistics->srcpad, caps);
-}
-
static void
gst_statistics_init (GstStatistics *statistics)
{
gst_element_add_pad (GST_ELEMENT (statistics), statistics->sinkpad);
gst_pad_set_chain_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_chain));
gst_pad_set_bufferpool_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_get_bufferpool));
- gst_pad_set_negotiate_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_sink));
statistics->srcpad = gst_pad_new ("src", GST_PAD_SRC);
gst_element_add_pad (GST_ELEMENT (statistics), statistics->srcpad);
- gst_pad_set_negotiate_function (statistics->srcpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_src));
statistics->timer = NULL;
statistics->last_timer = NULL;
static void gst_tee_chain (GstPad *pad, GstBuffer *buf);
-static GstPadNegotiateReturn gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
static GstElementClass *parent_class = NULL;
/*static guint gst_tee_signals[LAST_SIGNAL] = { 0 };*/
FALSE, G_PARAM_READWRITE));
-
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_tee_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_tee_get_property);
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_tee_request_new_pad);
}
+static gboolean
+gst_tee_sinkconnect (GstPad *pad, GstCaps *caps)
+{
+ GstTee *tee;
+ GList *pads;
+
+ tee = GST_TEE (gst_pad_get_parent (pad));
+
+ /* go through all the src pads */
+ pads = gst_element_get_pad_list (GST_ELEMENT (tee));
+
+ while (pads) {
+ GstPad *outpad = GST_PAD (pads->data);
+ pads = g_list_next (pads);
+
+ if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_IS_CONNECTED (outpad))
+ continue;
+
+ if (!(gst_pad_try_set_caps (outpad, caps))) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
static void
gst_tee_init (GstTee *tee)
{
tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
- gst_pad_set_negotiate_function (tee->sinkpad, GST_DEBUG_FUNCPTR(gst_tee_handle_negotiate_sink));
+ gst_pad_set_connect_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_sinkconnect));
tee->silent = FALSE;
}
GST_PAD_ELEMENT_PRIVATE (srcpad) = NULL;
if (GST_PAD_CAPS (tee->sinkpad)) {
- gst_pad_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
+ gst_pad_try_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
}
return srcpad;
GstEvent *event = GST_EVENT (GST_PAD_ELEMENT_PRIVATE (outpad));
GST_PAD_ELEMENT_PRIVATE (outpad) = NULL;
- if (GST_PAD_CONNECTED (outpad))
+ if (GST_PAD_IS_CONNECTED (outpad))
gst_pad_push (outpad, GST_BUFFER (event));
else
gst_event_free (event);
}
if (!tee->silent) {
- gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu) \n",
+ gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu)",
GST_DEBUG_PAD_NAME (outpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
}
- if (GST_PAD_CONNECTED (outpad))
+ if (GST_PAD_IS_CONNECTED (outpad))
gst_pad_push (outpad, buf);
else
gst_buffer_unref (buf);
return TRUE;
}
-static GstPadNegotiateReturn
-gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer* data)
-{
- GstCaps* tempcaps;
- gint i;
- GstTee* tee = GST_TEE (GST_OBJECT_PARENT (pad));
- GList *pads;
-
- if (*caps==NULL)
- return GST_PAD_NEGOTIATE_FAIL;
-
- /* go through all the src pads */
- pads = gst_element_get_pad_list (GST_ELEMENT (tee));
-
- while (pads) {
- GstPad *outpad = GST_PAD (pads->data);
- pads = g_list_next (pads);
-
- if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_CONNECTED (outpad))
- continue;
-
- if (!(gst_pad_set_caps (outpad, *caps))) {
- return GST_PAD_NEGOTIATE_FAIL;
- }
- }
- return GST_PAD_NEGOTIATE_AGREE;
-}
GstCaps*
gst_caps_new (const gchar *name, const gchar *mime, GstProps *props)
{
- GstCaps *caps;
-
g_return_val_if_fail (mime != NULL, NULL);
+ return gst_caps_new_id (name, get_type_for_mime (mime), props);
+}
+
+/**
+ * gst_caps_new_id:
+ * @name: the name of this capability
+ * @id: the id of the mime type
+ * @props: the properties to add to this capability
+ *
+ * Create a new capability with the given mime typeid and properties.
+ *
+ * Returns: a new capability
+ */
+GstCaps*
+gst_caps_new_id (const gchar *name, const guint16 id, GstProps *props)
+{
+ GstCaps *caps;
+
g_mutex_lock (_gst_caps_chunk_lock);
caps = g_mem_chunk_alloc (_gst_caps_chunk);
g_mutex_unlock (_gst_caps_chunk_lock);
caps->name = g_strdup (name);
- caps->id = get_type_for_mime (mime);
+ caps->id = id;
caps->properties = props;
caps->next = NULL;
caps->refcount = 1;
caps->lock = g_mutex_new ();
+ if (props)
+ caps->fixed = props->fixed;
+ else
+ caps->fixed = TRUE;
return caps;
}
{
GstCaps *next;
- g_return_if_fail (caps != NULL);
-
+ if (caps == NULL)
+ return;
+
GST_CAPS_LOCK (caps);
next = caps->next;
- g_free (caps->name);
- g_free (caps);
GST_CAPS_UNLOCK (caps);
+ g_mutex_free (caps->lock);
+ gst_props_unref (caps->properties);
+ g_free (caps->name);
+ g_mutex_lock (_gst_caps_chunk_lock);
+ g_mem_chunk_free (_gst_caps_chunk, caps);
+ g_mutex_unlock (_gst_caps_chunk_lock);
+
if (next)
gst_caps_unref (next);
}
+void
+gst_caps_debug (GstCaps *caps)
+{
+ GST_DEBUG_ENTER ("caps debug");
+ while (caps) {
+ GST_DEBUG (GST_CAT_CAPS, "caps: %p %s %s\n", caps, caps->name, gst_caps_get_mime (caps));
+
+ if (caps->properties) {
+ gst_props_debug (caps->properties);
+ }
+ else {
+ GST_DEBUG (GST_CAT_CAPS, "no properties\n");
+ }
+
+ caps = caps->next;
+ }
+ GST_DEBUG_LEAVE ("caps debug");
+}
+
/**
* gst_caps_unref:
* @caps: the caps to unref
gboolean zero;
GstCaps **next;
- g_return_val_if_fail (caps != NULL, NULL);
+ if (caps == NULL)
+ return NULL;
+
g_return_val_if_fail (caps->refcount > 0, NULL);
GST_CAPS_LOCK (caps);
GstCaps*
gst_caps_copy (GstCaps *caps)
{
- GstCaps *new = caps;;
+ GstCaps *new = NULL, *walk = NULL;
- g_return_val_if_fail (caps != NULL, NULL);
+ while (caps) {
+ GstCaps *newcaps;
- GST_CAPS_LOCK (caps);
- new = gst_caps_new (
+ newcaps = gst_caps_new_id (
caps->name,
- (gst_type_find_by_id (caps->id))->mime,
+ caps->id,
gst_props_copy (caps->properties));
- GST_CAPS_UNLOCK (caps);
+
+ if (new == NULL) {
+ new = walk = newcaps;
+ }
+ else {
+ walk = walk->next = newcaps;
+ }
+ caps = caps->next;
+ }
return new;
}
{
GstCaps *orig = capstoadd;
- g_return_val_if_fail (caps != capstoadd, caps);
-
if (capstoadd == NULL)
return caps;
+ g_return_val_if_fail (caps != capstoadd, caps);
+
while (capstoadd->next) {
capstoadd = capstoadd->next;
}
return FALSE;
}
+static GstCaps*
+gst_caps_intersect_func (GstCaps *caps1, GstCaps *caps2)
+{
+ GstCaps *result = NULL;
+ GstProps *props;
+
+ if (caps1->id != caps2->id) {
+ GST_DEBUG (GST_CAT_CAPS,"mime types differ (%s to %s)\n",
+ gst_type_find_by_id (caps1->id)->mime,
+ gst_type_find_by_id (caps2->id)->mime);
+ return NULL;
+ }
+
+ if (caps1->properties == NULL) {
+ return gst_caps_ref (caps2);
+ }
+ if (caps2->properties == NULL) {
+ return gst_caps_ref (caps1);
+ }
+
+ props = gst_props_intersect (caps1->properties, caps2->properties);
+ if (props) {
+ result = gst_caps_new_id ("intersect", caps1->id, props);
+ }
+
+ return result;
+}
+
+/**
+ * gst_caps_intersect:
+ * @caps1: a capabilty
+ * @caps2: a capabilty
+ *
+ * Make the intersection between two caps.
+ *
+ * Returns: The intersection of the two caps or NULL if the intersection
+ * is empty.
+ */
+GstCaps*
+gst_caps_intersect (GstCaps *caps1, GstCaps *caps2)
+{
+ GstCaps *result = NULL, *walk = NULL;
+
+ if (caps1 == NULL) {
+ GST_DEBUG (GST_CAT_CAPS, "first caps is NULL, return other caps\n");
+ return gst_caps_copy (caps2);
+ }
+ if (caps2 == NULL) {
+ GST_DEBUG (GST_CAT_CAPS, "second caps is NULL, return other caps\n");
+ return gst_caps_copy (caps1);
+ }
+
+ while (caps1) {
+ GstCaps *othercaps = caps2;
+
+ while (othercaps) {
+ GstCaps *intersection = gst_caps_intersect_func (caps1, othercaps);
+
+ if (intersection) {
+ if (!result) {
+ walk = result = intersection;
+ }
+ else {
+ walk = walk->next = intersection;
+ }
+ }
+ othercaps = othercaps->next;
+ }
+ caps1 = caps1->next;
+ }
+
+ return result;
+}
+
+GstCaps*
+gst_caps_normalize (GstCaps *caps)
+{
+ GstCaps *result = NULL, *walk = caps;
+
+ if (caps == NULL)
+ return caps;
+
+ while (caps) {
+ GList *proplist;
+
+ proplist = gst_props_normalize (caps->properties);
+ if (proplist && g_list_next (proplist) == NULL) {
+ if (result == NULL)
+ walk = result = caps;
+ else {
+ walk = walk->next = caps;
+ }
+ goto next;
+ }
+
+ while (proplist) {
+ GstProps *props = (GstProps *) proplist->data;
+ GstCaps *newcaps = gst_caps_new_id (caps->name, caps->id, props);
+
+ if (result == NULL)
+ walk = result = newcaps;
+ else {
+ walk = walk->next = newcaps;
+ }
+ proplist = g_list_next (proplist);
+ }
+next:
+ caps = caps->next;
+ }
+ return result;
+}
+
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
/**
* gst_caps_save_thyself:
caps->refcount = 1;
caps->lock = g_mutex_new ();
caps->next = NULL;
+ caps->fixed = TRUE;
while (subfield) {
if (!strcmp (subfield->name, "name")) {
#define GST_CAPS_TRYLOCK(caps) (g_mutex_trylock(GST_CAPS(caps)->lock))
#define GST_CAPS_UNLOCK(caps) (g_mutex_unlock(GST_CAPS(caps)->lock))
+#define GST_CAPS_IS_FIXED(caps) ((caps)->fixed)
+#define GST_CAPS_IS_CHAINED(caps) ((caps)->next)
+
struct _GstCaps {
- gchar *name; /* the name of this caps */
- guint16 id; /* type id (major type) */
+ gchar *name; /* the name of this caps */
+ guint16 id; /* type id (major type) */
- guint refcount;
- GMutex *lock; /* global lock for this capability */
+ guint refcount;
+ GMutex *lock; /* global lock for this capability */
+ gboolean fixed; /* this caps doesn't contain variable properties */
- GstProps *properties; /* properties for this capability */
+ GstProps *properties; /* properties for this capability */
- GstCaps *next;
+ GstCaps *next;
};
#define GST_CAPS_NEW(name, type, a...) \
void _gst_caps_initialize (void);
GstCaps* gst_caps_new (const gchar *name, const gchar *mime, GstProps *props);
+GstCaps* gst_caps_new_id (const gchar *name, const guint16 id, GstProps *props);
GstCaps* gst_caps_unref (GstCaps *caps);
GstCaps* gst_caps_ref (GstCaps *caps);
void gst_caps_destroy (GstCaps *caps);
+void gst_caps_debug (GstCaps *caps);
+
GstCaps* gst_caps_copy (GstCaps *caps);
GstCaps* gst_caps_copy_on_write (GstCaps *caps);
#define gst_caps_get_fourcc_int(caps, name) gst_props_get_fourcc_int ((caps)->properties, name)
#define gst_caps_get_boolean(caps, name) gst_props_get_boolean ((caps)->properties, name)
#define gst_caps_get_string(caps, name) gst_props_get_string ((caps)->properties, name)
+#define gst_caps_has_property(caps, name) gst_props_has_property ((caps)->properties, name)
GstCaps* gst_caps_get_by_name (GstCaps *caps, const gchar *name);
GstCaps* gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd);
gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps);
+GstCaps* gst_caps_intersect (GstCaps *caps1, GstCaps *caps2);
+GstCaps* gst_caps_normalize (GstCaps *caps);
#ifndef GST_DISABLE_LOADSAVE
xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent);
}
/**
- * gst_element_connect:
+ * gst_element_connect_filtered:
* @src: element containing source pad
* @srcpadname: name of pad in source element
* @dest: element containing destination pad
* @destpadname: name of pad in destination element
+ * @filtercaps: the caps to use as a filter
*
* Connect the two named pads of the source and destination elements.
* Side effect is that if one of the pads has no parent, it becomes a
* child of the parent of the other element. If they have different
* parents, the connection fails.
+ *
+ * Return: TRUE if the pads could be connected.
*/
-void
-gst_element_connect (GstElement *src, const gchar *srcpadname,
- GstElement *dest, const gchar *destpadname)
+gboolean
+gst_element_connect_filtered (GstElement *src, const gchar *srcpadname,
+ GstElement *dest, const gchar *destpadname,
+ GstCaps *filtercaps)
{
GstPad *srcpad,*destpad;
- g_return_if_fail (src != NULL);
- g_return_if_fail (GST_IS_ELEMENT(src));
- g_return_if_fail (srcpadname != NULL);
- g_return_if_fail (dest != NULL);
- g_return_if_fail (GST_IS_ELEMENT(dest));
- g_return_if_fail (destpadname != NULL);
+ g_return_val_if_fail (src != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
+ g_return_val_if_fail (srcpadname != NULL, FALSE);
+ g_return_val_if_fail (dest != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
+ g_return_val_if_fail (destpadname != NULL, FALSE);
/* obtain the pads requested */
srcpad = gst_element_get_pad (src, srcpadname);
if (srcpad == NULL) {
- GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
- return;
+ GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
+ return FALSE;
}
destpad = gst_element_get_pad (dest, destpadname);
if (srcpad == NULL) {
- GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
- return;
+ GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
+ return FALSE;
}
/* we're satisified they can be connected, let's do it */
- gst_pad_connect(srcpad,destpad);
+ return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
+}
+
+/**
+ * gst_element_connect:
+ * @src: element containing source pad
+ * @srcpadname: name of pad in source element
+ * @dest: element containing destination pad
+ * @destpadname: name of pad in destination element
+ *
+ * Connect the two named pads of the source and destination elements.
+ * Side effect is that if one of the pads has no parent, it becomes a
+ * child of the parent of the other element. If they have different
+ * parents, the connection fails.
+ *
+ * Return: TRUE if the pads could be connected.
+ */
+gboolean
+gst_element_connect (GstElement *src, const gchar *srcpadname,
+ GstElement *dest, const gchar *destpadname)
+{
+ return gst_element_connect_filtered (src, srcpadname, dest, destpadname, NULL);
}
/**
GstPad* gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ);
GstPad* gst_element_request_pad_by_name (GstElement *element, const gchar *name);
-void gst_element_connect (GstElement *src, const gchar *srcpadname,
+gboolean gst_element_connect (GstElement *src, const gchar *srcpadname,
GstElement *dest, const gchar *destpadname);
+gboolean gst_element_connect_filtered (GstElement *src, const gchar *srcpadname,
+ GstElement *dest, const gchar *destpadname,
+ GstCaps *filtercaps);
void gst_element_disconnect (GstElement *src, const gchar *srcpadname,
GstElement *dest, const gchar *destpadname);
static void gst_pad_class_init (GstPadClass *klass);
static void gst_pad_init (GstPad *pad);
+static gboolean gst_pad_try_reconnect_filtered_func (GstPad *pad, GstCaps *caps, gboolean clear);
+
#ifndef GST_DISABLE_LOADSAVE
static xmlNodePtr gst_pad_save_thyself (GstObject *object, xmlNodePtr parent);
#endif
/* gtk_object_add_arg_type ("GstRealPad::active", G_TYPE_BOOLEAN, */
/* GTK_ARG_READWRITE, REAL_ARG_ACTIVE); */
- g_object_class_install_property (G_OBJECT_CLASS(klass), REAL_ARG_ACTIVE,
- g_param_spec_boolean("active","Active","Whether the pad is active.",
- TRUE,G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), REAL_ARG_ACTIVE,
+ g_param_spec_boolean ("active", "Active", "Whether the pad is active.",
+ TRUE,G_PARAM_READWRITE));
#ifndef GST_DISABLE_LOADSAVE
- gstobject_class->save_thyself = GST_DEBUG_FUNCPTR(gst_pad_save_thyself);
+ gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself);
#endif
gstobject_class->path_string_separator = ".";
}
pad->getfunc = NULL;
pad->getregionfunc = NULL;
- pad->chainhandler = GST_DEBUG_FUNCPTR(gst_pad_push_func);
+ pad->chainhandler = GST_DEBUG_FUNCPTR (gst_pad_push_func);
pad->gethandler = NULL;
pad->pullregionfunc = NULL;
pad->bufferpoolfunc = NULL;
pad->ghostpads = NULL;
pad->caps = NULL;
+
+ pad->connectfunc = NULL;
+ pad->getcapsfunc = NULL;
}
static void
gst_real_pad_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
- g_return_if_fail(GST_IS_PAD(object));
+ g_return_if_fail (GST_IS_PAD (object));
switch (prop_id) {
case REAL_ARG_ACTIVE:
- if (g_value_get_boolean(value)) {
- GST_DEBUG(GST_CAT_PADS,"activating pad %s:%s\n",GST_DEBUG_PAD_NAME(object));
- GST_FLAG_UNSET(object,GST_PAD_DISABLED);
+ if (g_value_get_boolean (value)) {
+ GST_DEBUG (GST_CAT_PADS, "activating pad %s:%s\n", GST_DEBUG_PAD_NAME (object));
+ GST_FLAG_UNSET (object, GST_PAD_DISABLED);
} else {
- GST_DEBUG(GST_CAT_PADS,"de-activating pad %s:%s\n",GST_DEBUG_PAD_NAME(object));
- GST_FLAG_SET(object,GST_PAD_DISABLED);
+ GST_DEBUG (GST_CAT_PADS, "de-activating pad %s:%s\n", GST_DEBUG_PAD_NAME (object));
+ GST_FLAG_SET (object, GST_PAD_DISABLED);
}
- g_signal_emit(G_OBJECT(object), gst_real_pad_signals[REAL_SET_ACTIVE], 0,
- ! GST_FLAG_IS_SET(object,GST_PAD_DISABLED));
+ g_signal_emit (G_OBJECT (object), gst_real_pad_signals[REAL_SET_ACTIVE], 0,
+ !GST_FLAG_IS_SET (object, GST_PAD_DISABLED));
break;
default:
break;
switch (prop_id) {
case REAL_ARG_ACTIVE:
- g_value_set_boolean(value, ! GST_FLAG_IS_SET (object, GST_PAD_DISABLED) );
+ g_value_set_boolean (value, !GST_FLAG_IS_SET (object, GST_PAD_DISABLED));
break;
default:
break;
pad = g_object_new (gst_real_pad_get_type (), NULL);
gst_object_set_name (GST_OBJECT (pad), name);
- GST_RPAD_DIRECTION(pad) = direction;
+ GST_RPAD_DIRECTION (pad) = direction;
- return GST_PAD(pad);
+ return GST_PAD (pad);
}
/**
pad = gst_pad_new (name, templ->direction);
gst_object_ref (GST_OBJECT (templ));
- GST_PAD_PADTEMPLATE(pad) = templ;
+ GST_PAD_PADTEMPLATE (pad) = templ;
return pad;
}
g_return_val_if_fail (pad != NULL, GST_PAD_UNKNOWN);
g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
- return GST_PAD_DIRECTION(pad);
+ return GST_PAD_DIRECTION (pad);
}
/**
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_CHAINFUNC(pad) = chain;
- GST_DEBUG (GST_CAT_PADS,"chainfunc for %s:%s set to %s\n",
- GST_DEBUG_PAD_NAME(pad),GST_DEBUG_FUNCPTR_NAME(chain));
+ GST_DEBUG (GST_CAT_PADS, "chainfunc for %s:%s set to %s\n",
+ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (chain));
}
/**
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_GETFUNC(pad) = get;
- GST_DEBUG (GST_CAT_PADS,"getfunc for %s:%s set to %s\n",
- GST_DEBUG_PAD_NAME(pad),GST_DEBUG_FUNCPTR_NAME(get));
+ GST_DEBUG (GST_CAT_PADS, "getfunc for %s:%s set to %s\n",
+ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (get));
}
/**
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_EVENTFUNC(pad) = event;
- GST_DEBUG (GST_CAT_PADS,"eventfunc for %s:%s set to %s\n",
- GST_DEBUG_PAD_NAME(pad),GST_DEBUG_FUNCPTR_NAME(event));
+ GST_DEBUG (GST_CAT_PADS, "eventfunc for %s:%s set to %s\n",
+ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (event));
}
/**
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_GETREGIONFUNC(pad) = getregion;
- GST_DEBUG (GST_CAT_PADS,"getregionfunc for %s:%s set to %s\n",
- GST_DEBUG_PAD_NAME(pad),GST_DEBUG_FUNCPTR_NAME(getregion));
+ GST_DEBUG (GST_CAT_PADS, "getregionfunc for %s:%s set to %s\n",
+ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getregion));
}
/**
- * gst_pad_set_negotiate_function:
- * @pad: the pad to set the negotiate function for
- * @nego: the negotiate function
+ * gst_pad_set_connect_function:
+ * @pad: the pad to set the connect function for
+ * @connect: the connect function
*
- * Set the given negotiate function for the pad.
+ * Set the given connect function for the pad. It will be called
+ * when the pad is connected or reconnected with caps.
*/
void
-gst_pad_set_negotiate_function (GstPad *pad,
- GstPadNegotiateFunction nego)
+gst_pad_set_connect_function (GstPad *pad,
+ GstPadConnectFunction connect)
{
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_REAL_PAD (pad));
- GST_RPAD_NEGOTIATEFUNC(pad) = nego;
- GST_DEBUG (GST_CAT_PADS,"negotiatefunc for %s:%s set to %s\n",
- GST_DEBUG_PAD_NAME(pad),GST_DEBUG_FUNCPTR_NAME(nego));
+ GST_RPAD_CONNECTFUNC (pad) = connect;
+ GST_DEBUG (GST_CAT_PADS, "connectfunc for %s:%s set to %s\n",
+ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (connect));
}
/**
- * gst_pad_set_newcaps_function:
- * @pad: the pad to set the newcaps function for
- * @newcaps: the newcaps function
+ * gst_pad_set_getcaps_function:
+ * @pad: the pad to set the getcaps function for
+ * @getcaps: the getcaps function
*
- * Set the given newcaps function for the pad.
+ * Set the given getcaps function for the pad.
*/
void
-gst_pad_set_newcaps_function (GstPad *pad,
- GstPadNewCapsFunction newcaps)
+gst_pad_set_getcaps_function (GstPad *pad,
+ GstPadGetCapsFunction getcaps)
{
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_REAL_PAD (pad));
- GST_RPAD_NEWCAPSFUNC (pad) = newcaps;
- GST_DEBUG (GST_CAT_PADS,"newcapsfunc for %s:%s set to %s\n",
- GST_DEBUG_PAD_NAME(pad),GST_DEBUG_FUNCPTR_NAME(newcaps));
+ GST_RPAD_GETCAPSFUNC (pad) = getcaps;
+ GST_DEBUG (GST_CAT_PADS, "getcapsfunc for %s:%s set to %s\n",
+ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getcaps));
}
-
/**
* gst_pad_set_bufferpool_function:
* @pad: the pad to set the bufferpool function for
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_BUFFERPOOLFUNC (pad) = bufpool;
- GST_DEBUG (GST_CAT_PADS,"bufferpoolfunc for %s:%s set to %s\n",
- GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME(bufpool));
+ GST_DEBUG (GST_CAT_PADS, "bufferpoolfunc for %s:%s set to %s\n",
+ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (bufpool));
}
static void
gst_pad_push_func(GstPad *pad, GstBuffer *buf)
{
- if (GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad)) != NULL) {
- GST_DEBUG (GST_CAT_DATAFLOW,"calling chain function %s\n",
- GST_DEBUG_FUNCPTR_NAME(GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad))));
- (GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad)))(pad,buf);
+ if (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad)) != NULL) {
+ GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function %s\n",
+ GST_DEBUG_FUNCPTR_NAME (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad))));
+ (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad))) (pad, buf);
} else {
- GST_DEBUG (GST_CAT_DATAFLOW,"default pad_push handler in place, no chain function\n");
+ GST_DEBUG (GST_CAT_DATAFLOW, "default pad_push handler in place, no chain function\n");
g_warning ("(internal error) default pad_push in place for pad %s:%s but it has no chain function",
GST_DEBUG_PAD_NAME (pad));
}
g_return_if_fail (GST_IS_PAD (sinkpad));
GST_INFO (GST_CAT_ELEMENT_PADS, "disconnecting %s:%s(%p) and %s:%s(%p)",
- GST_DEBUG_PAD_NAME(srcpad), srcpad, GST_DEBUG_PAD_NAME(sinkpad), sinkpad);
+ GST_DEBUG_PAD_NAME (srcpad), srcpad, GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
/* now we need to deal with the real/ghost stuff */
- realsrc = GST_PAD_REALIZE(srcpad);
- realsink = GST_PAD_REALIZE(sinkpad);
+ realsrc = GST_PAD_REALIZE (srcpad);
+ realsink = GST_PAD_REALIZE (sinkpad);
- g_return_if_fail (GST_RPAD_PEER(realsrc) != NULL);
- g_return_if_fail (GST_RPAD_PEER(realsink) != NULL);
+ g_return_if_fail (GST_RPAD_PEER (realsrc) != NULL);
+ g_return_if_fail (GST_RPAD_PEER (realsink) != NULL);
- if ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SINK) &&
- (GST_RPAD_DIRECTION(realsink) == GST_PAD_SRC)) {
+ if ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
+ (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) {
GstRealPad *temppad;
temppad = realsrc;
realsrc = realsink;
realsink = temppad;
}
- g_return_if_fail ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
- (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK));
+ g_return_if_fail ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
+ (GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK));
/* first clear peers */
- GST_RPAD_PEER(realsrc) = NULL;
- GST_RPAD_PEER(realsink) = NULL;
+ GST_RPAD_PEER (realsrc) = NULL;
+ GST_RPAD_PEER (realsink) = NULL;
+
+ /* reset the filters, both filters are refcounted once */
+ if (GST_RPAD_FILTER (realsrc)) {
+ gst_caps_unref (GST_RPAD_FILTER (realsrc));
+ GST_RPAD_FILTER (realsink) = NULL;
+ GST_RPAD_FILTER (realsrc) = NULL;
+ }
/* now tell the scheduler */
if (GST_PAD_PARENT (realsrc)->sched)
gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsink)->sched, (GstPad *)realsrc, (GstPad *)realsink);
/* fire off a signal to each of the pads telling them that they've been disconnected */
- g_signal_emit(G_OBJECT(realsrc), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsink);
- g_signal_emit(G_OBJECT(realsink), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsrc);
+ g_signal_emit (G_OBJECT (realsrc), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsink);
+ g_signal_emit (G_OBJECT (realsink), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsrc);
GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
-}
-
-/**
- * gst_pad_connect:
- * @srcpad: the source pad to connect
- * @sinkpad: the sink pad to connect
- *
- * Connects the source pad to the sink pad.
- *
- * You shouldn't use this API in a real application because the
- * failure mode dumps diagnostics to stderr. A professional
- * application should never fail, or use gst_pad_try_connect and
- * check the return code.
- */
-void
-gst_pad_connect (GstPad *srcpad,
- GstPad *sinkpad)
-{
- if (!gst_pad_try_connect (srcpad, sinkpad)) {
- g_warning ("couldn't connect %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME (srcpad),
- GST_DEBUG_PAD_NAME (sinkpad));
- }
+ GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
}
/**
- * gst_pad_try_connect:
+ * gst_pad_connect_filtered:
* @srcpad: the source pad to connect
* @sinkpad: the sink pad to connect
+ * @filtercaps: the filter caps.
*
- * Connects the source pad to the sink pad.
+ * Connects the source pad to the sink pad. The filter indicates the media type
+ * that should flow trought this connection.
*
- * Returns: TRUE if the pad could be connected
+ * Returns: TRUE if the pad could be connected, FALSE otherwise
*/
gboolean
-gst_pad_try_connect (GstPad *srcpad,
- GstPad *sinkpad)
+gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps)
{
GstRealPad *realsrc, *realsink;
gboolean negotiated = FALSE;
/* generic checks */
- g_return_val_if_fail(srcpad != NULL, FALSE);
- g_return_val_if_fail(GST_IS_PAD(srcpad), FALSE);
- g_return_val_if_fail(sinkpad != NULL, FALSE);
- g_return_val_if_fail(GST_IS_PAD(sinkpad), FALSE);
+ g_return_val_if_fail (srcpad != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
+ g_return_val_if_fail (sinkpad != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
GST_INFO (GST_CAT_PADS, "connecting %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+ GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
/* now we need to deal with the real/ghost stuff */
- realsrc = GST_PAD_REALIZE(srcpad);
- realsink = GST_PAD_REALIZE(sinkpad);
+ realsrc = GST_PAD_REALIZE (srcpad);
+ realsink = GST_PAD_REALIZE (sinkpad);
if ((GST_PAD (realsrc) != srcpad) || (GST_PAD (realsink) != sinkpad))
GST_INFO (GST_CAT_PADS, "*actually* connecting %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME(realsrc), GST_DEBUG_PAD_NAME(realsink));
+ GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
- g_return_val_if_fail(GST_RPAD_PEER(realsrc) == NULL, FALSE);
- g_return_val_if_fail(GST_RPAD_PEER(realsink) == NULL, FALSE);
+ g_return_val_if_fail (GST_RPAD_PEER (realsrc) == NULL, FALSE);
+ g_return_val_if_fail (GST_RPAD_PEER (realsink) == NULL, FALSE);
/* check for reversed directions and swap if necessary */
- if ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SINK) &&
- (GST_RPAD_DIRECTION(realsink) == GST_PAD_SRC)) {
+ if ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
+ (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) {
GstRealPad *temppad;
temppad = realsrc;
realsrc = realsink;
realsink = temppad;
}
- g_return_val_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
- (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK), FALSE);
-
+ g_return_val_if_fail ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
+ (GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK), FALSE);
/* first set peers */
- GST_RPAD_PEER(realsrc) = realsink;
- GST_RPAD_PEER(realsink) = realsrc;
+ GST_RPAD_PEER (realsrc) = realsink;
+ GST_RPAD_PEER (realsink) = realsrc;
- if (GST_PAD_CAPS (srcpad)) {
- GST_DEBUG(GST_CAT_PADS, "renegotiation from srcpad\n");
- negotiated = gst_pad_renegotiate (srcpad);
- }
- else if (GST_PAD_CAPS (sinkpad)) {
- GST_DEBUG(GST_CAT_PADS, "renegotiation from sinkpad\n");
- negotiated = gst_pad_renegotiate (sinkpad);
- }
- else {
- GST_DEBUG(GST_CAT_PADS, "not renegotiating connection\n");
- negotiated = TRUE;
- }
+ if (!gst_pad_try_reconnect_filtered_func (GST_PAD (realsrc), filtercaps, FALSE)) {
+ GST_DEBUG (GST_CAT_CAPS, "pads cannot connect\n");
+
+ GST_RPAD_PEER (realsrc) = NULL;
+ GST_RPAD_PEER (realsink) = NULL;
- if (!negotiated) {
- GST_INFO(GST_CAT_PADS, "pads %s:%s and %s:%s failed to negotiate, disconnecting",
- GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
- gst_pad_disconnect (GST_PAD (realsrc), GST_PAD (realsink));
return FALSE;
}
-
+
/* fire off a signal to each of the pads telling them that they've been connected */
- g_signal_emit(G_OBJECT(realsrc), gst_real_pad_signals[REAL_CONNECTED], 0, realsink);
- g_signal_emit(G_OBJECT(realsink), gst_real_pad_signals[REAL_CONNECTED], 0, realsrc);
+ g_signal_emit (G_OBJECT (realsrc), gst_real_pad_signals[REAL_CONNECTED], 0, realsink);
+ g_signal_emit (G_OBJECT (realsink), gst_real_pad_signals[REAL_CONNECTED], 0, realsrc);
/* now tell the scheduler(s) */
if (realsrc->sched)
gst_scheduler_pad_connect (realsink->sched, (GstPad *)realsrc, (GstPad *)realsink);
GST_INFO (GST_CAT_PADS, "connected %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+ GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+
return TRUE;
}
+/**
+ * gst_pad_connect:
+ * @srcpad: the source pad to connect
+ * @sinkpad: the sink pad to connect
+ *
+ * Connects the source pad to the sink pad.
+ *
+ * Returns: TRUE if the pad could be connected, FALSE otherwise
+ */
+gboolean
+gst_pad_connect (GstPad *srcpad, GstPad *sinkpad)
+{
+ return gst_pad_connect_filtered (srcpad, sinkpad, NULL);
+}
+
/**
* gst_pad_set_parent:
* @pad: the pad to set the parent
g_return_if_fail (ghostpad != NULL);
g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
- realpad = GST_PAD_REALIZE(pad);
+ realpad = GST_PAD_REALIZE (pad);
realpad->ghostpads = g_list_prepend (realpad->ghostpads, ghostpad);
}
return GST_PAD_REALIZE(pad)->ghostpads;
}
+static GstPadConnectReturn
+gst_pad_try_set_caps_func (GstPad *pad, GstCaps *caps, gboolean notify, gboolean set_caps)
+{
+ GstCaps *oldcaps;
+
+ GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
+ caps, GST_DEBUG_PAD_NAME (pad));
+
+ if (notify && GST_RPAD_CONNECTFUNC (pad)) {
+ GstPadConnectReturn res;
+ gchar *debug_string;
+
+ GST_INFO (GST_CAT_CAPS, "calling connect function on pad %s:%s",
+ GST_DEBUG_PAD_NAME (pad));
+
+ res = GST_RPAD_CONNECTFUNC (pad) (pad, caps);
+
+ switch (res) {
+ case GST_PAD_CONNECT_REFUSED:
+ debug_string = "REFUSED";
+ break;
+ case GST_PAD_CONNECT_OK:
+ debug_string = "OK";
+ break;
+ case GST_PAD_CONNECT_DONE:
+ debug_string = "DONE";
+ break;
+ case GST_PAD_CONNECT_DELAYED:
+ debug_string = "DELAYED";
+ break;
+ default:
+ g_warning ("unknown return code from connect function of pad %s:%s",
+ GST_DEBUG_PAD_NAME (pad));
+ return GST_PAD_CONNECT_REFUSED;
+ }
+
+ GST_INFO (GST_CAT_CAPS, "got reply %s (%d) from connect function on pad %s:%s",
+ debug_string, res, GST_DEBUG_PAD_NAME (pad));
+
+ if (res == GST_PAD_CONNECT_DONE) {
+ GST_INFO (GST_CAT_CAPS, "pad %s:%s is done", GST_DEBUG_PAD_NAME (pad));
+ return GST_PAD_CONNECT_DONE;
+ }
+ if (res == GST_PAD_CONNECT_REFUSED) {
+ GST_INFO (GST_CAT_CAPS, "pad %s:%s doesn't accept caps",
+ GST_DEBUG_PAD_NAME (pad));
+ return GST_PAD_CONNECT_REFUSED;
+ }
+ }
+ /* we can only set caps on the pad if they are ficed */
+ if (GST_CAPS_IS_FIXED (caps)) {
+
+ if (set_caps) {
+ GST_INFO (GST_CAT_CAPS, "setting caps on pad %s:%s",
+ GST_DEBUG_PAD_NAME (pad));
+ /* if we got this far all is ok */
+ oldcaps = GST_PAD_CAPS (pad);
+ if (caps) gst_caps_ref (caps);
+ GST_PAD_CAPS (pad) = caps;
+ if (oldcaps) gst_caps_unref (oldcaps);
+ }
+ else {
+ GST_INFO (GST_CAT_CAPS, "NOT setting caps on pad %s:%s, as requested",
+ GST_DEBUG_PAD_NAME (pad));
+ }
+ }
+ else {
+ GST_INFO (GST_CAT_CAPS, "caps are not fixed on pad %s:%s, not setting them yet",
+ GST_DEBUG_PAD_NAME (pad));
+ }
+
+ return GST_PAD_CONNECT_OK;
+}
+
+gboolean
+gst_pad_try_set_caps (GstPad *pad, GstCaps *caps)
+{
+ GstCaps *oldcaps;
+ GstPad *peer;
+
+ peer = GST_PAD (GST_RPAD_PEER (pad));
+
+ GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
+ caps, GST_DEBUG_PAD_NAME (pad));
+
+ if (!GST_CAPS_IS_FIXED (caps)) {
+ g_warning ("trying to set non fixed caps on pad %s:%s, caps dump follow",
+ GST_DEBUG_PAD_NAME (pad));
+ gst_caps_debug (caps);
+ return FALSE;
+ }
+ if (peer && !gst_pad_try_set_caps_func (peer, caps, TRUE, TRUE))
+ return FALSE;
+ if (!gst_pad_try_set_caps_func (pad, caps, FALSE, TRUE))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static gboolean
+gst_pad_try_reconnect_filtered_func (GstPad *pad, GstCaps *filtercaps, gboolean clear)
+{
+ GstCaps *srccaps, *sinkcaps;
+ GstCaps *intersection = NULL;
+ GstRealPad *realsrc, *realsink;
+
+ g_return_val_if_fail (pad != NULL, FALSE);
+
+ realsrc = GST_PAD_REALIZE (pad);
+ realsink = GST_PAD_REALIZE (GST_RPAD_PEER (realsrc));
+
+ g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
+ g_return_val_if_fail (GST_RPAD_PEER (realsink) != NULL, FALSE);
+
+ GST_INFO (GST_CAT_PADS, "reconnect filtered %s:%s and %s:%s",
+ GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
+
+ if (clear) {
+ GST_INFO (GST_CAT_PADS, "reconnect filtered %s:%s and %s:%s, clearing caps",
+ GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
+
+ GST_PAD_CAPS (GST_PAD (realsrc)) = NULL;
+ GST_PAD_CAPS (GST_PAD (realsink)) = NULL;
+ }
+
+ srccaps = gst_pad_get_caps (GST_PAD (realsrc));
+ GST_INFO (GST_CAT_PADS, "dumping caps of pad %s:%s", GST_DEBUG_PAD_NAME (realsrc));
+ gst_caps_debug (srccaps);
+ sinkcaps = gst_pad_get_caps (GST_PAD (realsink));
+ GST_INFO (GST_CAT_PADS, "dumping caps of pad %s:%s", GST_DEBUG_PAD_NAME (realsink));
+ gst_caps_debug (sinkcaps);
+
+ intersection = gst_caps_intersect (srccaps, sinkcaps);
+
+ /* if we have no intersection but one of the caps was not NULL.. */
+ if (!intersection && (srccaps || sinkcaps )) {
+ /* the intersection is NULL, this means they have no common format */
+ GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s have no common type",
+ GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
+ return FALSE;
+ }
+ else {
+ GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s intersected to %s caps",
+ GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink),
+ ((intersection && GST_CAPS_IS_FIXED (intersection)) ? "fixed" : "variable"));
+
+ if (filtercaps) {
+ GstCaps *filtered_intersection = gst_caps_intersect (intersection, filtercaps);
+
+ /* get rid of the old intersection here */
+ gst_caps_unref (intersection);
+
+ if (!filtered_intersection) {
+ GST_INFO (GST_CAT_PADS, "filtered connection between pads %s:%s and %s:%s is empty, disconnecting",
+ GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
+ return FALSE;
+ }
+ intersection = filtered_intersection;
+
+ GST_RPAD_APPFILTER (realsink) = filtercaps;
+ GST_RPAD_APPFILTER (realsrc) = filtercaps;
+ }
+ }
+ GST_DEBUG (GST_CAT_CAPS, "setting filter for connection to:\n");
+ gst_caps_debug (intersection);
+
+ GST_RPAD_FILTER (realsrc) = intersection;
+ GST_RPAD_FILTER (realsink) = intersection;
+
+ if (intersection) {
+ GstPadConnectReturn res;
+
+ res = gst_pad_try_set_caps_func (GST_PAD (realsrc), intersection, TRUE, TRUE);
+ if (res == GST_PAD_CONNECT_REFUSED)
+ return FALSE;
+ if (res == GST_PAD_CONNECT_DONE)
+ return TRUE;
+
+ res = gst_pad_try_set_caps_func (GST_PAD (realsink), intersection, TRUE, TRUE);
+ if (res == GST_PAD_CONNECT_REFUSED)
+ return FALSE;
+ if (res == GST_PAD_CONNECT_DONE)
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
/**
- * gst_pad_set_caps:
- * @pad: the pad to set the caps to
- * @caps: the capabilities to attach to this pad
+ * gst_pad_try_reconnect_filtered:
+ * @pad: the pad to reconnect
+ * @caps: the capabilities to use in the reconnectiong
*
- * Set the capabilities of this pad.
+ * Try to reconnect this pad and its peer with the specified caps
*
- * Returns: a boolean indicating the caps could be set on the pad
+ * Returns: a boolean indicating the peer pad could accept the caps.
*/
gboolean
-gst_pad_set_caps (GstPad *pad,
- GstCaps *caps)
+gst_pad_try_reconnect_filtered (GstPad *pad, GstCaps *filtercaps)
{
- GstCaps *oldcaps;
-
g_return_val_if_fail (pad != NULL, FALSE);
- g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE); /* NOTE this restriction */
+ g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE);
+ g_return_val_if_fail (GST_PAD_IS_CONNECTED (pad), FALSE);
+
+ return gst_pad_try_reconnect_filtered_func (pad, filtercaps, TRUE);
+}
- GST_INFO (GST_CAT_CAPS, "setting caps %p on pad %s:%s",
- caps, GST_DEBUG_PAD_NAME(pad));
+/**
+ * gst_pad_reconnect_filtered:
+ * @pad: the pad to reconnect
+ * @caps: the capabilities to use in the reconnectiong
+ *
+ * Try to reconnect this pad and its peer with the specified caps.
+ *
+ * Returns: a boolean indicating the peer pad could accept the caps.
+ * if FALSE is returned, the pads are disconnected.
+ */
+gboolean
+gst_pad_reconnect_filtered (GstPad *pad, GstCaps *filtercaps)
+{
+ g_return_val_if_fail (pad != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE);
+ g_return_val_if_fail (GST_PAD_IS_CONNECTED (pad), FALSE);
- if (!gst_caps_check_compatibility (caps, gst_pad_get_padtemplate_caps (pad))) {
- g_warning ("pad %s:%s tried to set caps incompatible with its padtemplate\n",
- GST_DEBUG_PAD_NAME (pad));
+ if (!gst_pad_try_reconnect_filtered_func (pad, filtercaps, TRUE)) {
+ gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
return FALSE;
}
-
- oldcaps = GST_PAD_CAPS (pad);
+ return TRUE;
+}
- if (caps)
- gst_caps_ref (caps);
- GST_PAD_CAPS(pad) = caps;
+/**
+ * gst_pad_proxy_connect:
+ * @pad: the pad to proxy to
+ * @caps: the capabilities to use in the proxying
+ *
+ * Proxy the connect function to the specified pad.
+ *
+ * Returns: a boolean indicating the peer pad could accept the caps.
+ */
+GstPadConnectReturn
+gst_pad_proxy_connect (GstPad *pad, GstCaps *caps)
+{
+ GstPad *peer;
+
+ peer = GST_PAD (GST_RPAD_PEER (pad));
- if (oldcaps)
- gst_caps_unref (oldcaps);
+ GST_INFO (GST_CAT_CAPS, "proxy connect to pad %s:%s",
+ GST_DEBUG_PAD_NAME (pad));
- return gst_pad_renegotiate (pad);
+ if (peer && !gst_pad_try_set_caps_func (peer, caps, TRUE, TRUE))
+ return GST_PAD_CONNECT_REFUSED;
+ if (!gst_pad_try_set_caps_func (pad, caps, FALSE, TRUE))
+ return GST_PAD_CONNECT_REFUSED;
+
+ return GST_PAD_CONNECT_OK;
}
/**
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- if (GST_PAD_CAPS (pad))
+ GST_DEBUG (GST_CAT_CAPS, "get pad caps of %s:%s (%p)\n",
+ GST_DEBUG_PAD_NAME (pad), pad);
+
+ if (GST_PAD_CAPS (pad)) {
+ GST_DEBUG (GST_CAT_CAPS, "using pad real caps\n");
return GST_PAD_CAPS (pad);
- else if (GST_PAD_PADTEMPLATE (pad))
+ }
+ else if GST_RPAD_GETCAPSFUNC (pad) {
+ GST_DEBUG (GST_CAT_CAPS, "using pad get function\n");
+ return GST_RPAD_GETCAPSFUNC (pad) (pad, NULL);
+ }
+ else if (GST_PAD_PADTEMPLATE (pad)) {
+ GST_DEBUG (GST_CAT_CAPS, "using pad template\n");
return GST_PADTEMPLATE_CAPS (GST_PAD_PADTEMPLATE (pad));
+ }
+ GST_DEBUG (GST_CAT_CAPS, "pad has no caps\n");
return NULL;
}
g_return_val_if_fail (sinkpad != NULL, FALSE);
g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
- if (GST_PAD_CAPS(srcpad) && GST_PAD_CAPS(sinkpad)) {
- if (!gst_caps_check_compatibility (GST_PAD_CAPS(srcpad), GST_PAD_CAPS(sinkpad))) {
+ if (GST_PAD_CAPS (srcpad) && GST_PAD_CAPS (sinkpad)) {
+ if (!gst_caps_check_compatibility (GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad))) {
return FALSE;
}
else {
}
}
else {
- GST_DEBUG (GST_CAT_PADS,"could not check capabilities of pads (%s:%s) and (%s:%s) %p %p\n",
+ GST_DEBUG (GST_CAT_PADS, "could not check capabilities of pads (%s:%s) and (%s:%s) %p %p\n",
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad),
GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad));
return TRUE;
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- return GST_PAD(GST_PAD_PEER(pad));
+ return GST_PAD (GST_PAD_PEER (pad));
+}
+
+/**
+ * gst_pad_get_allowed_caps:
+ * @pad: the pad to get the allowed caps from
+ *
+ * Gst the caps of the allowed media types that can
+ * go through this pad.
+ *
+ * Returns: the allowed caps
+ */
+GstCaps*
+gst_pad_get_allowed_caps (GstPad *pad)
+{
+ GstRealPad *peer;
+
+ g_return_val_if_fail (pad != NULL, NULL);
+ g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+ peer = GST_RPAD_PEER (pad);
+
+ GST_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s\n", GST_DEBUG_PAD_NAME (pad));
+ /* this is not very correct: ...
+ if (peer && GST_RPAD_GETCAPSFUNC (peer)) {
+ GST_DEBUG (GST_CAT_PROPERTIES, "using getcaps function of peer %s:%s\n",
+ GST_DEBUG_PAD_NAME (peer));
+ return GST_RPAD_GETCAPSFUNC (peer) (GST_PAD (peer), NULL);
+ }
+ */
+ return gst_caps_copy (GST_RPAD_FILTER (pad));
+}
+
+/**
+ * gst_pad_get_allowed_caps:
+ * @pad: the pad to get the allowed caps from
+ *
+ * Gst the caps of the allowed media types that can
+ * go through this pad.
+ *
+ * Returns: the allowed caps
+ */
+gboolean
+gst_pad_recalc_allowed_caps (GstPad *pad)
+{
+ GstRealPad *peer;
+
+ g_return_if_fail (pad != NULL);
+ g_return_if_fail (GST_IS_PAD (pad));
+
+ GST_DEBUG (GST_CAT_PROPERTIES, "set allowed caps of %s:%s\n", GST_DEBUG_PAD_NAME (pad));
+
+ peer = GST_RPAD_PEER (pad);
+ if (peer)
+ gst_pad_try_reconnect_filtered (pad, GST_RPAD_APPFILTER (pad));
}
/**
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- peer = GST_RPAD_PEER(pad);
+ peer = GST_RPAD_PEER (pad);
- g_return_val_if_fail (peer != NULL, NULL);
+ if (!peer)
+ return NULL;
- GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
+ GST_DEBUG_ENTER ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
if (peer->bufferpoolfunc) {
- GST_DEBUG (GST_CAT_PADS,"calling bufferpoolfunc &%s (@%p) of peer pad %s:%s\n",
- GST_DEBUG_FUNCPTR_NAME(peer->bufferpoolfunc),&peer->bufferpoolfunc,GST_DEBUG_PAD_NAME(((GstPad*)peer)));
- return (peer->bufferpoolfunc)(((GstPad*)peer));
+ GST_DEBUG (GST_CAT_PADS, "calling bufferpoolfunc &%s (@%p) of peer pad %s:%s\n",
+ GST_DEBUG_FUNCPTR_NAME (peer->bufferpoolfunc), &peer->bufferpoolfunc, GST_DEBUG_PAD_NAME (((GstPad*) peer)));
+ return (peer->bufferpoolfunc) (((GstPad*) peer));
} else {
- GST_DEBUG (GST_CAT_PADS,"no bufferpoolfunc for peer pad %s:%s at %p\n",GST_DEBUG_PAD_NAME(((GstPad*)peer)),&peer->bufferpoolfunc);
+ GST_DEBUG (GST_CAT_PADS, "no bufferpoolfunc for peer pad %s:%s at %p\n",
+ GST_DEBUG_PAD_NAME (((GstPad*) peer)), &peer->bufferpoolfunc);
return NULL;
}
}
gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
}
- /* FIXME we should destroy the ghostpads, because they are nothing without the real pad */
+ /* we destroy the ghostpads, because they are nothing without the real pad */
if (GST_REAL_PAD (pad)->ghostpads) {
GList *orig, *ghostpads;
GstPad *ghostpad = GST_PAD (ghostpads->data);
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){
- GST_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'\n", GST_OBJECT_NAME(GST_OBJECT_PARENT (ghostpad)));
+ GST_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'\n",
+ GST_OBJECT_NAME (GST_OBJECT_PARENT (ghostpad)));
+
gst_element_remove_ghost_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), GST_PAD (ghostpad));
}
ghostpads = g_list_next (ghostpads);
}
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))){
- GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
+ GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",
+ GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
+
gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
}
cleanup:
g_strfreev (split);
}
-#endif /* GST_DISABLE_LOADSAVE */
-
-static gboolean
-gst_pad_renegotiate_func (GstPad *pad, gpointer *data1, GstPad *peerpad, gpointer *data2, GstCaps **newcaps)
-{
- GstRealPad *currentpad, *otherpad;
- gpointer *currentdata, *otherdata;
- GstPadNegotiateReturn result;
- gint counter = 0;
-
- g_return_val_if_fail (pad != NULL, FALSE);
-
- currentpad = GST_PAD_REALIZE (pad);
- otherpad = GST_REAL_PAD (peerpad);
- currentdata = data1;
- otherdata = data2;
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "negotiating pad %s:%s and %s:%s data:%p\n",
- GST_DEBUG_PAD_NAME(currentpad), GST_DEBUG_PAD_NAME(otherpad), currentdata);
-
- do {
- gboolean matchtempl;
-
- if (!*newcaps) {
- if (otherpad->negotiatefunc) {
- GstRealPad *temp;
- gpointer *tempdata;
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "requesting other caps from pad %s:%s data:%p\n",
- GST_DEBUG_PAD_NAME(otherpad), otherdata);
- otherpad->negotiatefunc (GST_PAD (otherpad), newcaps, otherdata);
-
- temp = otherpad;
- otherpad = currentpad;
- currentpad = temp;
-
- tempdata = otherdata;
- otherdata = currentdata;
- currentdata = tempdata;
- }
- }
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "checking compatibility with pad %s:%s\n",
- GST_DEBUG_PAD_NAME(otherpad));
- matchtempl = gst_caps_check_compatibility (*newcaps, gst_pad_get_padtemplate_caps (GST_PAD (otherpad)));
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "caps compatibility check %s\n", (matchtempl?"ok":"fail"));
-
- if (matchtempl) {
- GST_DEBUG (GST_CAT_NEGOTIATION, "checking if other pad %s:%s can negotiate data:%p\n",
- GST_DEBUG_PAD_NAME(otherpad), otherdata);
- if (otherpad->negotiatefunc) {
- GstRealPad *temp;
- gpointer *tempdata;
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "switching pad for next phase\n");
-
- temp = currentpad;
- currentpad = otherpad;
- otherpad = temp;
-
- tempdata = otherdata;
- otherdata = currentdata;
- currentdata = tempdata;
- }
- else if (gst_caps_check_compatibility (*newcaps, GST_PAD_CAPS (otherpad))) {
- GST_DEBUG (GST_CAT_NEGOTIATION, "negotiation succeeded\n");
- return TRUE;
- }
- else {
- *newcaps = GST_PAD_CAPS (otherpad);
- if (*newcaps) gst_caps_ref(*newcaps);
- }
- }
- else {
- *newcaps = GST_PAD_CAPS (otherpad);
- if (*newcaps) gst_caps_ref(*newcaps);
- }
-
- counter++;
-
- if (currentpad->negotiatefunc) {
- GST_DEBUG (GST_CAT_NEGOTIATION, "calling negotiate function on pad %s:%s data: %p\n",
- GST_DEBUG_PAD_NAME (currentpad), currentdata);
- result = currentpad->negotiatefunc (GST_PAD (currentpad), newcaps, currentdata);
-
- switch (result) {
- case GST_PAD_NEGOTIATE_FAIL:
- GST_DEBUG (GST_CAT_NEGOTIATION, "negotiation failed\n");
- return FALSE;
- case GST_PAD_NEGOTIATE_AGREE:
- GST_DEBUG (GST_CAT_NEGOTIATION, "negotiation succeeded\n");
- return TRUE;
- case GST_PAD_NEGOTIATE_TRY:
- GST_DEBUG (GST_CAT_NEGOTIATION, "try another option\n");
- break;
- default:
- GST_DEBUG (GST_CAT_NEGOTIATION, "invalid return\n");
- break;
- }
- }
- else {
- GST_DEBUG (GST_CAT_NEGOTIATION, "negotiation failed, no more options\n");
- return FALSE;
- }
-
- } while (counter < 100);
-
- g_warning ("negotiation between (%s:%s) and (%s:%s) failed: too many attempts (%d)\n",
- GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(peerpad), counter);
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "negotiation failed, too many attempts\n");
-
- return FALSE;
-}
-
-/**
- * gst_pad_renegotiate:
- * @pad: the pad to perform the negotiation on
- *
- * Perform the negotiation process with the peer pad.
- *
- * Returns: TRUE if the negotiation process succeded
- */
-gboolean
-gst_pad_renegotiate (GstPad *pad)
-{
- GstCaps *newcaps = NULL;
- GstRealPad *peerpad, *currentpad, *otherpad;
- gboolean result;
- gpointer data1 = NULL, data2 = NULL;
-
- g_return_val_if_fail (pad != NULL, FALSE);
-
- peerpad = GST_PAD_PEER (pad);
-
- currentpad = GST_PAD_REALIZE (pad);
-
- if (!peerpad) {
- GST_DEBUG (GST_CAT_NEGOTIATION, "no peer pad for pad %s:%s\n",
- GST_DEBUG_PAD_NAME(currentpad));
- return TRUE;
- }
-
- otherpad = GST_REAL_PAD (peerpad);
-
- GST_INFO (GST_CAT_NEGOTIATION, "negotiating pad %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(peerpad));
-
- newcaps = GST_PAD_CAPS (pad);
-
- result = gst_pad_renegotiate_func (GST_PAD (currentpad), &data1, GST_PAD (otherpad), &data2, &newcaps);
-
- if (!result) {
- GST_DEBUG (GST_CAT_NEGOTIATION, "firing caps_nego_failed signal on %s:%s and %s:%s to give it a chance to succeed\n",
- GST_DEBUG_PAD_NAME(currentpad),GST_DEBUG_PAD_NAME(otherpad));
- g_signal_emit (G_OBJECT(currentpad),
- gst_real_pad_signals[REAL_CAPS_NEGO_FAILED], 0, &result);
- g_signal_emit (G_OBJECT(otherpad),
- gst_real_pad_signals[REAL_CAPS_NEGO_FAILED], 0, &result);
- if (result)
- GST_DEBUG (GST_CAT_NEGOTIATION, "caps_nego_failed handler claims success at renego, believing\n");
- }
-
- if (result) {
- GST_DEBUG (GST_CAT_NEGOTIATION, "pads aggreed on caps :)\n");
-
- newcaps = GST_PAD_CAPS (pad);
- /* g_return_val_if_fail(newcaps != NULL, FALSE); FIXME is this valid? */
-
- /* here we have some sort of aggreement of the caps */
- GST_PAD_CAPS (currentpad) = gst_caps_ref (newcaps);
- if (GST_RPAD_NEWCAPSFUNC (currentpad))
- GST_RPAD_NEWCAPSFUNC (currentpad) (GST_PAD (currentpad), newcaps);
-
- GST_PAD_CAPS (otherpad) = gst_caps_ref (newcaps);
- if (GST_RPAD_NEWCAPSFUNC (otherpad))
- GST_RPAD_NEWCAPSFUNC (otherpad) (GST_PAD (otherpad), newcaps);
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "firing caps_changed signal on %s:%s and %s:%s\n",
- GST_DEBUG_PAD_NAME(currentpad),GST_DEBUG_PAD_NAME(otherpad));
- g_signal_emit (G_OBJECT(currentpad),
- gst_real_pad_signals[REAL_CAPS_CHANGED], 0, GST_PAD_CAPS(currentpad));
- g_signal_emit (G_OBJECT(otherpad),
- gst_real_pad_signals[REAL_CAPS_CHANGED], 0, GST_PAD_CAPS(otherpad));
- }
-
- return result;
-}
-/**
- * gst_pad_negotiate_proxy:
- * @srcpad: the pad that proxies
- * @destpad: the pad to proxy the negotiation to
- * @caps: the current caps
- *
- * Proxies the negotiation pad from srcpad to destpad. Further
- * negotiation is done on the peers of both pad instead.
- *
- * Returns: the result of the negotiation preocess.
- */
-GstPadNegotiateReturn
-gst_pad_negotiate_proxy (GstPad *srcpad, GstPad *destpad, GstCaps **caps)
-{
- GstRealPad *srcpeer;
- GstRealPad *destpeer;
- gboolean result;
- gpointer data1 = NULL, data2 = NULL;
-
- g_return_val_if_fail (srcpad != NULL, GST_PAD_NEGOTIATE_FAIL);
- g_return_val_if_fail (destpad != NULL, GST_PAD_NEGOTIATE_FAIL);
-
- GST_DEBUG (GST_CAT_NEGOTIATION, "negotiation proxied from pad (%s:%s) to pad (%s:%s)\n",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
-
- srcpeer = GST_RPAD_PEER (srcpad);
- destpeer = GST_RPAD_PEER (destpad);
-
- if (srcpeer && destpeer) {
- result = gst_pad_renegotiate_func (GST_PAD (srcpeer), &data1, GST_PAD (destpeer), &data2, caps);
-
- if (result) {
- GST_DEBUG (GST_CAT_NEGOTIATION, "pads (%s:%s) and (%s:%s) aggreed on caps :)\n",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
-
- /* here we have some sort of aggreement of the caps */
- GST_PAD_CAPS (destpeer) = *caps;
- if (GST_RPAD_NEWCAPSFUNC (destpeer))
- GST_RPAD_NEWCAPSFUNC (destpeer) (GST_PAD (destpeer), *caps);
-
- GST_PAD_CAPS (destpad) = *caps;
- if (GST_RPAD_NEWCAPSFUNC (destpad))
- GST_RPAD_NEWCAPSFUNC (destpad) (GST_PAD (destpad), *caps);
- }
- else {
- GST_DEBUG (GST_CAT_NEGOTIATION, "pads did not aggree on caps :(\n");
- return GST_PAD_NEGOTIATE_FAIL;
- }
- }
- else {
- GST_PAD_CAPS (destpad) = *caps;
- if (GST_RPAD_NEWCAPSFUNC (destpad))
- GST_RPAD_NEWCAPSFUNC (destpad) (GST_PAD (destpad), *caps);
- }
-
- return GST_PAD_NEGOTIATE_AGREE;
-}
-
-#ifndef GST_DISABLE_LOADSAVE
/**
* gst_pad_save_thyself:
* @pad: the pad to save
va_start (var_args, caps);
while (caps) {
+ new->fixed &= caps->fixed;
thecaps = gst_caps_append (thecaps, caps);
caps = va_arg (var_args, GstCaps*);
}
GstGhostPad *ghostpad;
g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (GST_IS_PAD(pad), NULL);
+ g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- ghostpad = g_object_new(gst_ghost_pad_get_type () ,NULL);
+ ghostpad = g_object_new (gst_ghost_pad_get_type () ,NULL);
gst_pad_set_name (GST_PAD (ghostpad), name);
- GST_GPAD_REALPAD(ghostpad) = GST_PAD_REALIZE(pad);
- GST_PAD_PADTEMPLATE(ghostpad) = GST_PAD_PADTEMPLATE(pad);
+ GST_GPAD_REALPAD (ghostpad) = GST_PAD_REALIZE (pad);
+ GST_PAD_PADTEMPLATE (ghostpad) = GST_PAD_PADTEMPLATE (pad);
/* add ourselves to the real pad's list of ghostpads */
- gst_pad_add_ghost_pad (pad, GST_PAD(ghostpad));
+ gst_pad_add_ghost_pad (pad, GST_PAD (ghostpad));
/* FIXME need to ref the real pad here... ? */
- GST_DEBUG(GST_CAT_PADS,"created ghost pad \"%s\"\n",name);
+ GST_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\"\n", name);
- return GST_PAD(ghostpad);
+ return GST_PAD (ghostpad);
}
static void
pads = g_list_next (pads);
/* for all pads in the opposite direction that are connected */
- if (GST_PAD_DIRECTION (eventpad) != GST_PAD_DIRECTION (pad) && GST_PAD_CONNECTED (eventpad)) {
+ if (GST_PAD_DIRECTION (eventpad) != GST_PAD_DIRECTION (pad) && GST_PAD_IS_CONNECTED (eventpad)) {
if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
gst_pad_push (eventpad, GST_BUFFER (gst_event_new (GST_EVENT_TYPE (event))));
GST_REGION_TIME_LEN,
} GstRegionType;
-typedef enum {
- GST_PAD_NEGOTIATE_FAIL,
- GST_PAD_NEGOTIATE_AGREE,
- GST_PAD_NEGOTIATE_TRY,
-} GstPadNegotiateReturn;
-
+typedef enum {
+ GST_PAD_CONNECT_REFUSED = 0,
+ GST_PAD_CONNECT_OK = 1,
+ GST_PAD_CONNECT_DONE = 2,
+ GST_PAD_CONNECT_DELAYED = 3,
+} GstPadConnectReturn;
/* this defines the functions used to chain buffers
* pad is the sink pad (so the same chain function can be used for N pads)
* buf is the buffer being passed */
-typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
-typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
-typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
-
-typedef GstBuffer* (*GstPadGetRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
-typedef GstBuffer* (*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
-typedef GstPadNegotiateReturn (*GstPadNegotiateFunction) (GstPad *pad, GstCaps **caps, gpointer *data);
-typedef void (*GstPadNewCapsFunction) (GstPad *pad, GstCaps *caps);
-typedef GstBufferPool* (*GstPadBufferPoolFunction) (GstPad *pad);
+typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
+typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
+typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
+
+typedef GstBuffer* (*GstPadGetRegionFunction) (GstPad *pad, GstRegionType type,
+ guint64 offset, guint64 len);
+typedef GstBuffer* (*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type,
+ guint64 offset, guint64 len);
+typedef GstPadConnectReturn (*GstPadConnectFunction) (GstPad *pad, GstCaps *caps);
+typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad, GstCaps *caps);
+typedef GstBufferPool* (*GstPadBufferPoolFunction) (GstPad *pad);
typedef enum {
GST_PAD_UNKNOWN,
GstPad pad;
GstCaps *caps;
+ GstCaps *filter;
+ GstCaps *appfilter;
GstPadDirection direction;
GstScheduler *sched;
GstPadGetRegionFunction getregionfunc;
GstPadPullRegionFunction pullregionfunc;
- GstPadNegotiateFunction negotiatefunc;
- GstPadNewCapsFunction newcapsfunc;
+ GstPadGetCapsFunction getcapsfunc;
+ GstPadConnectFunction connectfunc;
GstPadBufferPoolFunction bufferpoolfunc;
GList *ghostpads;
/* GstRealPad */
#define GST_RPAD_DIRECTION(pad) (((GstRealPad *)(pad))->direction)
#define GST_RPAD_CAPS(pad) (((GstRealPad *)(pad))->caps)
+#define GST_RPAD_FILTER(pad) (((GstRealPad *)(pad))->filter)
+#define GST_RPAD_APPFILTER(pad) (((GstRealPad *)(pad))->appfilter)
#define GST_RPAD_PEER(pad) (((GstRealPad *)(pad))->peer)
#define GST_RPAD_BUFPEN(pad) (((GstRealPad *)(pad))->bufpen)
#define GST_RPAD_SCHED(pad) (((GstRealPad *)(pad))->sched)
#define GST_RPAD_GETREGIONFUNC(pad) (((GstRealPad *)(pad))->getregionfunc)
#define GST_RPAD_PULLREGIONFUNC(pad) (((GstRealPad *)(pad))->pullregionfunc)
-#define GST_RPAD_NEGOTIATEFUNC(pad) (((GstRealPad *)(pad))->negotiatefunc)
-#define GST_RPAD_NEWCAPSFUNC(pad) (((GstRealPad *)(pad))->newcapsfunc)
+#define GST_RPAD_CONNECTFUNC(pad) (((GstRealPad *)(pad))->connectfunc)
+#define GST_RPAD_GETCAPSFUNC(pad) (((GstRealPad *)(pad))->getcapsfunc)
#define GST_RPAD_BUFFERPOOLFUNC(pad) (((GstRealPad *)(pad))->bufferpoolfunc)
#define GST_RPAD_REGIONTYPE(pad) (((GstRealPad *)(pad))->regiontype)
#define GST_PAD_PEER(pad) GST_RPAD_PEER(GST_PAD_REALIZE(pad))
/* Some check functions (unused?) */
-#define GST_PAD_CONNECTED(pad) (GST_PAD_PEER(pad) != NULL)
+#define GST_PAD_IS_CONNECTED(pad) (GST_PAD_PEER(pad) != NULL)
#define GST_PAD_CAN_PULL(pad) (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->gethandler != NULL)
-
+#define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC)
+#define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK)
/***** PadTemplate *****/
#define GST_TYPE_PADTEMPLATE (gst_padtemplate_get_type ())
#define GST_PADTEMPLATE_DIRECTION(templ) (((GstPadTemplate *)(templ))->direction)
#define GST_PADTEMPLATE_PRESENCE(templ) (((GstPadTemplate *)(templ))->presence)
#define GST_PADTEMPLATE_CAPS(templ) (((GstPadTemplate *)(templ))->caps)
+#define GST_PADTEMPLATE_FIXED(templ) (((GstPadTemplate *)(templ))->fixed)
+
+#define GST_PADTEMPLATE_IS_FIXED(templ) (GST_PADTEMPLATE_FIXED(templ) == TRUE)
struct _GstPadTemplate {
GstObject object;
GstPadDirection direction;
GstPadPresence presence;
GstCaps *caps;
+ gboolean fixed;
};
struct _GstPadTemplateClass {
#define GST_PADTEMPLATE_GET(fact) (fact)()
-GType gst_pad_get_type (void);
-GType gst_real_pad_get_type (void);
-GType gst_ghost_pad_get_type (void);
+GType gst_pad_get_type (void);
+GType gst_real_pad_get_type (void);
+GType gst_ghost_pad_get_type (void);
-GstPad* gst_pad_new (gchar *name, GstPadDirection direction);
-#define gst_pad_destroy(pad) gst_object_destroy (GST_OBJECT (pad))
-GstPad* gst_pad_new_from_template (GstPadTemplate *templ, gchar *name);
+GstPad* gst_pad_new (gchar *name, GstPadDirection direction);
+#define gst_pad_destroy(pad) gst_object_destroy (GST_OBJECT (pad))
+GstPad* gst_pad_new_from_template (GstPadTemplate *templ, gchar *name);
-GstPadDirection gst_pad_get_direction (GstPad *pad);
+GstPadDirection gst_pad_get_direction (GstPad *pad);
-void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
-void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get);
-void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
+void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
+void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get);
+void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
-void gst_pad_set_getregion_function (GstPad *pad, GstPadGetRegionFunction getregion);
+void gst_pad_set_getregion_function (GstPad *pad, GstPadGetRegionFunction getregion);
-void gst_pad_set_negotiate_function (GstPad *pad, GstPadNegotiateFunction nego);
-void gst_pad_set_newcaps_function (GstPad *pad, GstPadNewCapsFunction newcaps);
-void gst_pad_set_bufferpool_function (GstPad *pad, GstPadBufferPoolFunction bufpool);
+void gst_pad_set_connect_function (GstPad *pad, GstPadConnectFunction connect);
+void gst_pad_set_getcaps_function (GstPad *pad, GstPadGetCapsFunction getcaps);
+void gst_pad_set_bufferpool_function (GstPad *pad, GstPadBufferPoolFunction bufpool);
-gboolean gst_pad_set_caps (GstPad *pad, GstCaps *caps);
-GstCaps* gst_pad_get_caps (GstPad *pad);
-GstCaps* gst_pad_get_padtemplate_caps (GstPad *pad);
-gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad);
+GstCaps* gst_pad_get_caps (GstPad *pad);
+GstCaps* gst_pad_get_padtemplate_caps (GstPad *pad);
+gboolean gst_pad_try_set_caps (GstPad *pad, GstCaps *caps);
+gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad);
-void gst_pad_set_element_private (GstPad *pad, gpointer priv);
-gpointer gst_pad_get_element_private (GstPad *pad);
+void gst_pad_set_element_private (GstPad *pad, gpointer priv);
+gpointer gst_pad_get_element_private (GstPad *pad);
-void gst_pad_set_name (GstPad *pad, const gchar *name);
-const gchar* gst_pad_get_name (GstPad *pad);
+void gst_pad_set_name (GstPad *pad, const gchar *name);
+const gchar* gst_pad_get_name (GstPad *pad);
-void gst_pad_set_parent (GstPad *pad, GstObject *parent);
-GstElement* gst_pad_get_parent (GstPad *pad);
-GstElement* gst_pad_get_real_parent (GstPad *pad);
+void gst_pad_set_parent (GstPad *pad, GstObject *parent);
+GstElement* gst_pad_get_parent (GstPad *pad);
+GstElement* gst_pad_get_real_parent (GstPad *pad);
-void gst_pad_set_sched (GstPad *pad, GstScheduler *sched);
-GstScheduler* gst_pad_get_sched (GstPad *pad);
+void gst_pad_set_sched (GstPad *pad, GstScheduler *sched);
+GstScheduler* gst_pad_get_sched (GstPad *pad);
-void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad);
-void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad);
-GList* gst_pad_get_ghost_pad_list (GstPad *pad);
+void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad);
+void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad);
+GList* gst_pad_get_ghost_pad_list (GstPad *pad);
-GstPadTemplate* gst_pad_get_padtemplate (GstPad *pad);
+GstPadTemplate* gst_pad_get_padtemplate (GstPad *pad);
-GstPad* gst_pad_get_peer (GstPad *pad);
+GstPad* gst_pad_get_peer (GstPad *pad);
-GstBufferPool* gst_pad_get_bufferpool (GstPad *pad);
+GstBufferPool* gst_pad_get_bufferpool (GstPad *pad);
-gboolean gst_pad_try_connect (GstPad *srcpad, GstPad *sinkpad);
-void gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
-void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad);
+gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
+gboolean gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
+void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad);
-gboolean gst_pad_renegotiate (GstPad *pad);
-GstPadNegotiateReturn gst_pad_negotiate_proxy (GstPad *srcpad, GstPad *destpad, GstCaps **caps);
+GstPadConnectReturn gst_pad_proxy_connect (GstPad *pad, GstCaps *caps);
+gboolean gst_pad_reconnect_filtered (GstPad *pad, GstCaps *filtercaps);
+gboolean gst_pad_try_reconnect_filtered (GstPad *pad, GstCaps *filtercaps);
+GstCaps* gst_pad_get_allowed_caps (GstPad *pad);
+gboolean gst_pad_recalc_allowed_caps (GstPad *pad);
#if 1
-void gst_pad_push (GstPad *pad, GstBuffer *buf);
+void gst_pad_push (GstPad *pad, GstBuffer *buf);
#else
#define gst_pad_push(pad,buf) G_STMT_START{ \
if (((GstRealPad *)(pad))->peer->chainhandler) \
}G_STMT_END
#endif
#if 1
-GstBuffer* gst_pad_pull (GstPad *pad);
-GstBuffer* gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
+GstBuffer* gst_pad_pull (GstPad *pad);
+GstBuffer* gst_pad_pullregion (GstPad *pad, GstRegionType type,
+ guint64 offset, guint64 len);
#else
#define gst_pad_pull(pad) \
( (((GstRealPad *)(pad))->peer->gethandler) ? \
NULL )
#endif
-gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
-void gst_pad_event_default (GstPad *pad, GstEvent *event);
+gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
+void gst_pad_event_default (GstPad *pad, GstEvent *event);
-GstBuffer* gst_pad_peek (GstPad *pad);
-GstPad* gst_pad_select (GList *padlist);
-GstPad* gst_pad_selectv (GstPad *pad, ...);
+GstBuffer* gst_pad_peek (GstPad *pad);
+GstPad* gst_pad_select (GList *padlist);
+GstPad* gst_pad_selectv (GstPad *pad, ...);
#ifndef GST_DISABLE_LOADSAVE
-void gst_pad_load_and_connect (xmlNodePtr self, GstObject *parent);
+void gst_pad_load_and_connect (xmlNodePtr self, GstObject *parent);
#endif
/* ghostpads */
-GstPad* gst_ghost_pad_new (gchar *name,GstPad *pad);
+GstPad* gst_ghost_pad_new (gchar *name,GstPad *pad);
/* templates and factories */
-GType gst_padtemplate_get_type (void);
+GType gst_padtemplate_get_type (void);
-GstPadTemplate* gst_padtemplate_new (gchar *name_template,
- GstPadDirection direction, GstPadPresence presence,
- GstCaps *caps, ...);
+GstPadTemplate* gst_padtemplate_new (gchar *name_template,
+ GstPadDirection direction, GstPadPresence presence,
+ GstCaps *caps, ...);
-GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ);
+GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ);
GstCaps* gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name);
#ifndef GST_DISABLE_LOADSAVE
-xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent);
-GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent);
+xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent);
+GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent);
#endif
-xmlNodePtr gst_pad_ghost_save_thyself (GstPad *pad,
- GstElement *bin,
- xmlNodePtr parent);
+xmlNodePtr gst_pad_ghost_save_thyself (GstPad *pad,
+ GstElement *bin,
+ xmlNodePtr parent);
#ifdef __cplusplus
}
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wtay@chello.be>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
*
* gstprops.c: Properties subsystem for generic usage
*
static GMutex *_gst_props_chunk_lock;
static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2);
+static GList* gst_props_list_copy (GList *propslist);
+
void
_gst_props_initialize (void)
static void
gst_props_debug_entry (GstPropsEntry *entry)
{
+ gchar *name = g_quark_to_string (entry->propid);
+
switch (entry->propstype) {
case GST_PROPS_INT_ID:
- GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.int_data);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%s: int %d\n", name, entry->data.int_data);
break;
case GST_PROPS_FLOAT_ID:
- GST_DEBUG (GST_CAT_PROPERTIES, "%f\n", entry->data.float_data);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%s: float %f\n", name, entry->data.float_data);
break;
case GST_PROPS_FOURCC_ID:
- GST_DEBUG (GST_CAT_PROPERTIES, "%4.4s\n", (gchar*)&entry->data.fourcc_data);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%s: fourcc %4.4s\n", name, (gchar*)&entry->data.fourcc_data);
break;
case GST_PROPS_BOOL_ID:
- GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.bool_data);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%s: bool %d\n", name, entry->data.bool_data);
break;
case GST_PROPS_STRING_ID:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s\n", entry->data.string_data.string);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%s: string %s\n", name, entry->data.string_data.string);
break;
case GST_PROPS_INT_RANGE_ID:
- GST_DEBUG (GST_CAT_PROPERTIES, "%d-%d\n", entry->data.int_range_data.min,
+ GST_DEBUG (GST_CAT_PROPERTIES, "%s: int range %d-%d\n", name, entry->data.int_range_data.min,
entry->data.int_range_data.max);
break;
case GST_PROPS_FLOAT_RANGE_ID:
- GST_DEBUG (GST_CAT_PROPERTIES, "%f-%f\n", entry->data.float_range_data.min,
+ GST_DEBUG (GST_CAT_PROPERTIES, "%s: float range %f-%f\n", name, entry->data.float_range_data.min,
entry->data.float_range_data.max);
break;
case GST_PROPS_LIST_ID:
GST_DEBUG (GST_CAT_PROPERTIES, "[list]\n");
+ {
+ GList *entries = entry->data.list_data.entries;
+
+ while (entries) {
+ gst_props_debug_entry ((GstPropsEntry *)entries->data);
+ entries = g_list_next (entries);
+ }
+ }
+ break;
default:
+ g_warning ("unknown property type %d", entry->propstype);
break;
}
}
gconstpointer b)
{
GstPropsEntry *entry2 = (GstPropsEntry *)a;
- GQuark entry1 = (GQuark) GPOINTER_TO_INT (b);
+ GQuark quark = (GQuark) GPOINTER_TO_INT (b);
- return (entry1 - entry2->propid);
+ return (quark - entry2->propid);
}
/* This is implemented as a huge macro because we cannot pass
} \
} G_STMT_END
+static GstPropsEntry*
+gst_props_alloc_entry (void)
+{
+ GstPropsEntry *entry;
+
+ g_mutex_lock (_gst_props_entries_chunk_lock);
+ entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
+ g_mutex_unlock (_gst_props_entries_chunk_lock);
+
+ return entry;
+}
+
+static void
+gst_props_entry_destroy (GstPropsEntry *entry)
+{
+ switch (entry->propstype) {
+ case GST_PROPS_STRING_ID:
+ g_free (entry->data.string_data.string);
+ break;
+ case GST_PROPS_LIST_ID:
+ {
+ GList *entries = entry->data.list_data.entries;
+
+ while (entries) {
+ gst_props_entry_destroy ((GstPropsEntry *)entries->data);
+ entries = g_list_next (entries);
+ }
+ g_list_free (entry->data.list_data.entries);
+ break;
+ }
+ default:
+ break;
+ }
+ g_mutex_lock (_gst_props_entries_chunk_lock);
+ g_mem_chunk_free (_gst_props_entries_chunk, entry);
+ g_mutex_unlock (_gst_props_entries_chunk_lock);
+}
+
+static GstProps*
+gst_props_alloc (void)
+{
+ GstProps *props;
+
+ g_mutex_lock (_gst_props_chunk_lock);
+ props = g_mem_chunk_alloc (_gst_props_chunk);
+ g_mutex_unlock (_gst_props_chunk_lock);
+
+ props->properties = NULL;
+ props->refcount = 1;
+ props->fixed = TRUE;
+
+ return props;
+}
+
+static void
+gst_props_add_entry (GstProps *props, GstPropsEntry *entry)
+{
+ g_return_if_fail (props);
+ g_return_if_fail (entry);
+
+ if (props->fixed && GST_PROPS_ENTRY_IS_VARIABLE (entry)) {
+ props->fixed = FALSE;
+ }
+ props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
+}
+
/**
* gst_props_new:
* @firstname: the first property name
return props;
}
-/**
- * gst_props_add_to_list:
- * @entries: the existing list of entries
- * @entry: the new entry to add to the list
- *
- * Add a property to a list of properties.
- *
- * Returns: a pointer to a list with the new entry added.
- */
-static GList *
-gst_props_add_to_list (GList * entries, GstPropsEntry *entry)
+
+void
+gst_props_debug (GstProps *props)
{
- return g_list_prepend (entries, entry);
+ GList *propslist = props->properties;
+
+ while (propslist) {
+ GstPropsEntry *entry = (GstPropsEntry *)propslist->data;
+
+ gst_props_debug_entry (entry);
+
+ propslist = g_list_next (propslist);
+ }
}
/**
i = g_list_next (i);
}
- return gst_props_add_to_list (entries, newentry);
+ return g_list_prepend (entries, newentry);
}
/**
if (firstname == NULL)
return NULL;
- g_mutex_lock (_gst_props_chunk_lock);
- props = g_mem_chunk_alloc (_gst_props_chunk);
- g_mutex_unlock (_gst_props_chunk_lock);
-
- props->properties = NULL;
- props->refcount = 1;
+ props = gst_props_alloc ();
prop_name = firstname;
/* properties */
while (prop_name) {
GstPropsEntry *entry;
-
- g_mutex_lock (_gst_props_entries_chunk_lock);
- entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
-
+
+ entry = gst_props_alloc_entry ();
entry->propid = g_quark_from_string (prop_name);
GST_PROPS_ENTRY_FILL (entry, var_args);
g_mem_chunk_free (_gst_props_entries_chunk, subentry);
g_mutex_unlock (_gst_props_entries_chunk_lock);
}
+ else {
+ list_entry->data.list_data.entries =
+ g_list_reverse (list_entry->data.list_data.entries);
+ }
g_mutex_lock (_gst_props_entries_chunk_lock);
g_mem_chunk_free (_gst_props_entries_chunk, entry);
break;
default:
list_entry->data.list_data.entries =
- gst_props_add_to_list (list_entry->data.list_data.entries, entry);
+ g_list_prepend (list_entry->data.list_data.entries, entry);
break;
}
}
}
else {
- props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
+ gst_props_add_entry (props, entry);
}
if (!inlist)
prop_name = va_arg (var_args, gchar*);
void
gst_props_unref (GstProps *props)
{
- g_return_if_fail (props != NULL);
+ if (props == NULL)
+ return;
props->refcount--;
props->refcount++;
}
+
/**
* gst_props_destroy:
* @props: the props to destroy
{
GList *entries;
- g_return_if_fail (props != NULL);
+ if (props == NULL)
+ return;
entries = props->properties;
while (entries) {
- GstPropsEntry *entry = (GstPropsEntry *)entries->data;
-
- switch (entry->propstype) {
- case GST_PROPS_STRING_ID:
- g_free (entry->data.string_data.string);
- break;
- /* FIXME also free the lists */
- default:
- break;
- }
- g_mutex_lock (_gst_props_entries_chunk_lock);
- g_mem_chunk_free (_gst_props_entries_chunk, entry);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
-
+ gst_props_entry_destroy ((GstPropsEntry *)entries->data);
entries = g_list_next (entries);
}
g_list_free (props->properties);
g_mutex_unlock (_gst_props_chunk_lock);
}
+/*
+ * copy entries
+ */
+static GstPropsEntry*
+gst_props_entry_copy (GstPropsEntry *entry)
+{
+ GstPropsEntry *newentry;
+
+ newentry = gst_props_alloc_entry ();
+ memcpy (newentry, entry, sizeof (GstPropsEntry));
+ if (entry->propstype == GST_PROPS_LIST_ID) {
+ newentry->data.list_data.entries = gst_props_list_copy (entry->data.list_data.entries);
+ }
+ else if (entry->propstype == GST_PROPS_STRING_ID) {
+ newentry->data.string_data.string = g_strdup (entry->data.string_data.string);
+ }
+
+ return newentry;
+}
+
+static GList*
+gst_props_list_copy (GList *propslist)
+{
+ GList *new = NULL;
+
+ while (propslist) {
+ GstPropsEntry *entry = (GstPropsEntry *)propslist->data;
+
+ new = g_list_prepend (new, gst_props_entry_copy (entry));
+
+ propslist = g_list_next (propslist);
+ }
+ new = g_list_reverse (new);
+
+ return new;
+}
+
/**
* gst_props_copy:
* @props: the props to copy
GstProps *new;
GList *properties;
- g_return_val_if_fail (props != NULL, NULL);
-
- g_mutex_lock (_gst_props_chunk_lock);
- new = g_mem_chunk_alloc (_gst_props_chunk);
- g_mutex_unlock (_gst_props_chunk_lock);
-
- new->properties = NULL;
-
- properties = props->properties;
-
- while (properties) {
- GstPropsEntry *entry = (GstPropsEntry *)properties->data;
- GstPropsEntry *newentry;
-
- g_mutex_lock (_gst_props_entries_chunk_lock);
- newentry = g_mem_chunk_alloc (_gst_props_entries_chunk);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
-
- /* FIXME copy lists too */
- memcpy (newentry, entry, sizeof (GstPropsEntry));
+ if (props == NULL)
+ return NULL;
- new->properties = g_list_prepend (new->properties, newentry);
-
- properties = g_list_next (properties);
- }
- new->properties = g_list_reverse (new->properties);
+ new = gst_props_alloc ();
+ new->properties = gst_props_list_copy (props->properties);
+ new->fixed = props->fixed;
return new;
}
return NULL;
}
+gboolean
+gst_props_has_property (GstProps *props, const gchar *name)
+{
+ return (gst_props_get_entry_func (props, name) != NULL);
+}
+
/**
* gst_props_get_int:
* @props: the props to get the int value from
if (thisentry) {
return thisentry->data.int_data;
}
+ else {
+ g_warning ("props: property %s not found", name);
+ }
return 0;
}
if (thisentry) {
return thisentry->data.float_data;
}
+ else {
+ g_warning ("props: property %s not found", name);
+ }
return 0.0F;
}
if (thisentry) {
return thisentry->data.fourcc_data;
}
+ else {
+ g_warning ("props: property %s not found", name);
+ }
return 0;
}
if (thisentry) {
return thisentry->data.bool_data;
}
+ else {
+ g_warning ("props: property %s not found", name);
+ }
return 0;
}
if (thisentry) {
return thisentry->data.string_data.string;
}
+ else {
+ g_warning ("props: property %s not found", name);
+ }
return NULL;
}
while (merge_props) {
GstPropsEntry *entry = (GstPropsEntry *)merge_props->data;
- props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
+ gst_props_add_entry (props, entry);
merge_props = g_list_next (merge_props);
}
{
GST_DEBUG (GST_CAT_PROPERTIES,"compare: %s %s\n", g_quark_to_string (entry1->propid),
g_quark_to_string (entry2->propid));
- gst_props_debug_entry (entry1);
- gst_props_debug_entry (entry2);
+
+ if (entry2->propstype == GST_PROPS_LIST_ID && entry1->propstype != GST_PROPS_LIST_ID) {
+ return gst_props_entry_check_list_compatibility (entry1, entry2);
+ }
+
switch (entry1->propstype) {
case GST_PROPS_LIST_ID:
{
case GST_PROPS_INT_RANGE_ID:
return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
- case GST_PROPS_LIST_ID:
- return gst_props_entry_check_list_compatibility (entry1, entry2);
- default:
- return FALSE;
}
break;
case GST_PROPS_FLOAT_RANGE_ID:
case GST_PROPS_FLOAT_RANGE_ID:
return (entry2->data.float_range_data.min <= entry1->data.float_range_data.min &&
entry2->data.float_range_data.max >= entry1->data.float_range_data.max);
- case GST_PROPS_LIST_ID:
- return gst_props_entry_check_list_compatibility (entry1, entry2);
- default:
- return FALSE;
}
break;
case GST_PROPS_FOURCC_ID:
switch (entry2->propstype) {
/* b <---> a */
case GST_PROPS_FOURCC_ID:
+ GST_DEBUG(GST_CAT_PROPERTIES,"\"%4.4s\" <--> \"%4.4s\" ?\n",
+ &entry2->data.fourcc_data, &entry1->data.fourcc_data);
return (entry2->data.fourcc_data == entry1->data.fourcc_data);
- /* b <---> a,b,c */
- case GST_PROPS_LIST_ID:
- return gst_props_entry_check_list_compatibility (entry1, entry2);
- default:
- return FALSE;
}
break;
case GST_PROPS_INT_ID:
case GST_PROPS_INT_ID:
GST_DEBUG(GST_CAT_PROPERTIES,"%d == %d ?\n",entry1->data.int_data,entry2->data.int_data);
return (entry2->data.int_data == entry1->data.int_data);
- /* b <---> a,b,c */
- case GST_PROPS_LIST_ID:
- return gst_props_entry_check_list_compatibility (entry1, entry2);
- default:
- return FALSE;
}
break;
case GST_PROPS_FLOAT_ID:
/* b <---> a */
case GST_PROPS_FLOAT_ID:
return (entry2->data.float_data == entry1->data.float_data);
- /* b <---> a,b,c */
- case GST_PROPS_LIST_ID:
- return gst_props_entry_check_list_compatibility (entry1, entry2);
- default:
- return FALSE;
}
break;
case GST_PROPS_BOOL_ID:
/* t <---> t */
case GST_PROPS_BOOL_ID:
return (entry2->data.bool_data == entry1->data.bool_data);
- case GST_PROPS_LIST_ID:
- return gst_props_entry_check_list_compatibility (entry1, entry2);
- default:
- return FALSE;
}
case GST_PROPS_STRING_ID:
switch (entry2->propstype) {
/* t <---> t */
case GST_PROPS_STRING_ID:
return (!strcmp (entry2->data.string_data.string, entry1->data.string_data.string));
- case GST_PROPS_LIST_ID:
- return gst_props_entry_check_list_compatibility (entry1, entry2);
- default:
- return FALSE;
}
- default:
- break;
}
return FALSE;
entry2 = (GstPropsEntry *)sinklist->data;
while (entry1->propid < entry2->propid) {
- GST_DEBUG (GST_CAT_PROPERTIES,"source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
more++;
sourcelist = g_list_next (sourcelist);
if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
else goto end;
}
while (entry1->propid > entry2->propid) {
- GST_DEBUG (GST_CAT_PROPERTIES,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
missing++;
sinklist = g_list_next (sinklist);
if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
compatible = FALSE;
GST_DEBUG (GST_CAT_PROPERTIES, "%s are not compatible: \n",
g_quark_to_string (entry1->propid));
- gst_props_debug_entry (entry1);
- gst_props_debug_entry (entry2);
}
sourcelist = g_list_next (sourcelist);
GstPropsEntry *entry2;
entry2 = (GstPropsEntry *)sinklist->data;
missing++;
- GST_DEBUG (GST_CAT_PROPERTIES,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
}
end:
return compatible;
}
+static GstPropsEntry*
+gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
+{
+ GstPropsEntry *result = NULL;
+
+ /* try to move the ranges and lists first */
+ switch (entry2->propstype) {
+ case GST_PROPS_INT_RANGE_ID:
+ case GST_PROPS_FLOAT_RANGE_ID:
+ case GST_PROPS_LIST_ID:
+ {
+ GstPropsEntry *temp;
+
+ temp = entry1;
+ entry1 = entry2;
+ entry2 = temp;
+ }
+ }
+
+ switch (entry1->propstype) {
+ case GST_PROPS_LIST_ID:
+ {
+ GList *entrylist = entry1->data.list_data.entries;
+ GList *intersection = NULL;
+
+ while (entrylist) {
+ GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
+ GstPropsEntry *intersectentry;
+
+ intersectentry = gst_props_entry_intersect (entry2, entry);
+
+ if (intersectentry) {
+ if (intersectentry->propstype == GST_PROPS_LIST_ID) {
+ intersection = g_list_concat (intersection, intersectentry->data.list_data.entries);
+ /* set the list to NULL because the entries are concatenated to the above
+ * list and we don't want to free them */
+ intersectentry->data.list_data.entries = NULL;
+ gst_props_entry_destroy (intersectentry);
+ }
+ else {
+ intersection = g_list_prepend (intersection, intersectentry);
+ }
+ }
+ entrylist = g_list_next (entrylist);
+ }
+ if (intersection) {
+ /* check if the list only contains 1 element, if so, we can just copy it */
+ if (g_list_next (intersection) == NULL) {
+ result = (GstPropsEntry *) (intersection->data);
+ g_list_free (intersection);
+ }
+ /* else we need to create a new entry to hold the list */
+ else {
+ result = gst_props_alloc_entry ();
+ result->propid = entry1->propid;
+ result->propstype = GST_PROPS_LIST_ID;
+ result->data.list_data.entries = g_list_reverse (intersection);
+ }
+ }
+ return result;
+ }
+ case GST_PROPS_INT_RANGE_ID:
+ switch (entry2->propstype) {
+ /* a - b <---> a - c */
+ case GST_PROPS_INT_RANGE_ID:
+ {
+ gint lower = MAX (entry1->data.int_range_data.min, entry2->data.int_range_data.min);
+ gint upper = MIN (entry1->data.int_range_data.max, entry2->data.int_range_data.max);
+
+ if (lower <= upper) {
+ result = gst_props_alloc_entry ();
+ result->propid = entry1->propid;
+
+ if (lower == upper) {
+ result->propstype = GST_PROPS_INT_ID;
+ result->data.int_data = lower;
+ }
+ else {
+ result->propstype = GST_PROPS_INT_RANGE_ID;
+ result->data.int_range_data.min = lower;
+ result->data.int_range_data.max = upper;
+ }
+ }
+ break;
+ }
+ case GST_PROPS_INT_ID:
+ if (entry1->data.int_range_data.min <= entry2->data.int_data &&
+ entry1->data.int_range_data.max >= entry2->data.int_data) {
+ result = gst_props_entry_copy (entry2);
+ }
+ }
+ break;
+ case GST_PROPS_FLOAT_RANGE_ID:
+ switch (entry2->propstype) {
+ /* a - b <---> a - c */
+ case GST_PROPS_FLOAT_RANGE_ID:
+ {
+ gfloat lower = MAX (entry1->data.float_range_data.min, entry2->data.float_range_data.min);
+ gfloat upper = MIN (entry1->data.float_range_data.max, entry2->data.float_range_data.max);
+
+ if (lower <= upper) {
+ result = gst_props_alloc_entry ();
+ result->propid = entry1->propid;
+
+ if (lower == upper) {
+ result->propstype = GST_PROPS_FLOAT_ID;
+ result->data.float_data = lower;
+ }
+ else {
+ result->propstype = GST_PROPS_FLOAT_RANGE_ID;
+ result->data.float_range_data.min = lower;
+ result->data.float_range_data.max = upper;
+ }
+ }
+ break;
+ }
+ case GST_PROPS_FLOAT_ID:
+ if (entry1->data.float_range_data.min <= entry2->data.float_data &&
+ entry1->data.float_range_data.max >= entry2->data.float_data) {
+ result = gst_props_entry_copy (entry2);
+ }
+ }
+ break;
+ case GST_PROPS_FOURCC_ID:
+ switch (entry2->propstype) {
+ /* b <---> a */
+ case GST_PROPS_FOURCC_ID:
+ if (entry1->data.fourcc_data == entry2->data.fourcc_data)
+ result = gst_props_entry_copy (entry1);
+ }
+ break;
+ case GST_PROPS_INT_ID:
+ switch (entry2->propstype) {
+ /* b <---> a */
+ case GST_PROPS_INT_ID:
+ if (entry1->data.int_data == entry2->data.int_data)
+ result = gst_props_entry_copy (entry1);
+ }
+ break;
+ case GST_PROPS_FLOAT_ID:
+ switch (entry2->propstype) {
+ /* b <---> a */
+ case GST_PROPS_FLOAT_ID:
+ if (entry1->data.float_data == entry2->data.float_data)
+ result = gst_props_entry_copy (entry1);
+ }
+ break;
+ case GST_PROPS_BOOL_ID:
+ switch (entry2->propstype) {
+ /* t <---> t */
+ case GST_PROPS_BOOL_ID:
+ if (entry1->data.bool_data == entry2->data.bool_data)
+ result = gst_props_entry_copy (entry1);
+ }
+ case GST_PROPS_STRING_ID:
+ switch (entry2->propstype) {
+ /* t <---> t */
+ case GST_PROPS_STRING_ID:
+ if (!strcmp (entry1->data.string_data.string, entry2->data.string_data.string))
+ result = gst_props_entry_copy (entry1);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * gst_props_intersect:
+ * @props1: a property
+ * @props2: another property
+ *
+ * Calculates the intersection bewteen two GstProps.
+ *
+ * Returns: a GstProps with the intersection or NULL if the
+ * intersection is empty.
+ */
+GstProps*
+gst_props_intersect (GstProps *props1, GstProps *props2)
+{
+ GList *props1list;
+ GList *props2list;
+ GstProps *intersection;
+ GList *leftovers;
+ GstPropsEntry *iprops = NULL;
+
+ intersection = gst_props_alloc ();
+ intersection->fixed = TRUE;
+
+ g_return_val_if_fail (props1 != NULL, NULL);
+ g_return_val_if_fail (props2 != NULL, NULL);
+
+ props1list = props1->properties;
+ props2list = props2->properties;
+
+ while (props1list && props2list) {
+ GstPropsEntry *entry1;
+ GstPropsEntry *entry2;
+
+ entry1 = (GstPropsEntry *)props1list->data;
+ entry2 = (GstPropsEntry *)props2list->data;
+
+ while (entry1->propid < entry2->propid) {
+ GstPropsEntry *toadd;
+
+ GST_DEBUG (GST_CAT_PROPERTIES,"source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
+
+ toadd = gst_props_entry_copy (entry1);
+ if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
+ intersection->fixed = FALSE;
+
+ intersection->properties = g_list_prepend (intersection->properties, toadd);
+
+ props1list = g_list_next (props1list);
+ if (props1list)
+ entry1 = (GstPropsEntry *)props1list->data;
+ else
+ goto end;
+ }
+ while (entry1->propid > entry2->propid) {
+ GstPropsEntry *toadd;
+
+ toadd = gst_props_entry_copy (entry2);
+ if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
+ intersection->fixed = FALSE;
+
+ intersection->properties = g_list_prepend (intersection->properties, toadd);
+
+ props2list = g_list_next (props2list);
+ if (props2list)
+ entry2 = (GstPropsEntry *)props2list->data;
+ else
+ goto end;
+ }
+ /* at this point we are talking about the same property */
+ iprops = gst_props_entry_intersect (entry1, entry2);
+
+ if (iprops) {
+ if (GST_PROPS_ENTRY_IS_VARIABLE (iprops))
+ intersection->fixed = FALSE;
+ intersection->properties = g_list_prepend (intersection->properties, iprops);
+ }
+ else {
+ gst_props_unref (intersection);
+ return NULL;
+ }
+
+ props1list = g_list_next (props1list);
+ props2list = g_list_next (props2list);
+ }
+
+end:
+ /* at this point one of the lists could contain leftover properties */
+ if (props1list)
+ leftovers = props1list;
+ else if (props2list)
+ leftovers = props2list;
+ else
+ goto finish;
+
+ while (leftovers) {
+ GstPropsEntry *entry;
+
+ entry = (GstPropsEntry *) leftovers->data;
+ if (GST_PROPS_ENTRY_IS_VARIABLE (entry))
+ intersection->fixed = FALSE;
+ intersection->properties = g_list_prepend (intersection->properties, gst_props_entry_copy (entry));
+
+ leftovers = g_list_next (leftovers);
+ }
+
+finish:
+ intersection->properties = g_list_reverse (intersection->properties);
+
+ return intersection;
+}
+
+GList*
+gst_props_normalize (GstProps *props)
+{
+ GList *entries;
+ GList *result = NULL;
+
+ if (!props)
+ return NULL;
+
+ entries = props->properties;
+
+ while (entries) {
+ GstPropsEntry *entry = (GstPropsEntry *) entries->data;
+
+ if (entry->propstype == GST_PROPS_LIST_ID) {
+ GList *list_entries = entry->data.list_data.entries;
+
+ while (list_entries) {
+ GstPropsEntry *list_entry = (GstPropsEntry *) list_entries->data;
+ GstPropsEntry *new_entry;
+ GstProps *newprops;
+ GList *lentry;
+
+ newprops = gst_props_alloc ();
+ newprops->properties = gst_props_list_copy (props->properties);
+ lentry = g_list_find_custom (newprops->properties, GINT_TO_POINTER (list_entry->propid), props_find_func);
+ if (lentry) {
+ GList *new_list = NULL;
+
+ new_entry = (GstPropsEntry *) lentry->data;
+ memcpy (new_entry, list_entry, sizeof (GstPropsEntry));
+
+ new_list = gst_props_normalize (newprops);
+ result = g_list_concat (new_list, result);
+ }
+ else {
+ result = g_list_append (result, newprops);
+ }
+
+ list_entries = g_list_next (list_entries);
+ }
+ /* we break out of the loop because the other lists are
+ * unrolled in the recursive call */
+ break;
+ }
+ entries = g_list_next (entries);
+ }
+ if (!result) {
+ result = g_list_prepend (result, props);
+ }
+ else {
+ result = g_list_reverse (result);
+ gst_props_unref (props);
+ }
+ return result;
+}
+
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
static xmlNodePtr
gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
xmlNewProp (subtree, "value", entry->data.string_data.string);
break;
default:
+ g_warning ("trying to save unknown property type %d", entry->propstype);
break;
}
subtree = xmlNewChild (parent, NULL, "list", NULL);
xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
+ break;
default:
gst_props_save_thyself_func (entry, parent);
}
GstPropsEntry *entry;
gchar *prop;
- g_mutex_lock (_gst_props_entries_chunk_lock);
- entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+ entry = gst_props_alloc_entry ();
if (!strcmp(field->name, "int")) {
entry->propstype = GST_PROPS_INT_ID;
xmlNodePtr field = parent->xmlChildrenNode;
gchar *prop;
- g_mutex_lock (_gst_props_chunk_lock);
- props = g_mem_chunk_alloc (_gst_props_chunk);
- g_mutex_unlock (_gst_props_chunk_lock);
-
- props->properties = NULL;
- props->refcount = 1;
+ props = gst_props_alloc ();
while (field) {
if (!strcmp (field->name, "list")) {
GstPropsEntry *entry;
xmlNodePtr subfield = field->xmlChildrenNode;
- g_mutex_lock (_gst_props_entries_chunk_lock);
- entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
-
- entry->propstype = GST_PROPS_LIST_ID;
- entry->data.list_data.entries = NULL;
+ entry = gst_props_alloc_entry ();
prop = xmlGetProp (field, "name");
entry->propid = g_quark_from_string (prop);
g_free (prop);
+ entry->propstype = GST_PROPS_LIST_ID;
+ entry->data.list_data.entries = NULL;
while (subfield) {
GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
subfield = subfield->next;
}
entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
- props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
+ gst_props_add_entry (props, entry);
}
else {
GstPropsEntry *entry;
entry = gst_props_load_thyself_func (field);
if (entry)
- props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
+ gst_props_add_entry (props, entry);
}
field = field->next;
}
typedef enum {
GST_PROPS_END_ID = 0,
- GST_PROPS_LIST_ID,
GST_PROPS_INT_ID,
- GST_PROPS_INT_RANGE_ID,
GST_PROPS_FLOAT_ID,
- GST_PROPS_FLOAT_RANGE_ID,
GST_PROPS_FOURCC_ID,
GST_PROPS_BOOL_ID,
GST_PROPS_STRING_ID,
+
+ GST_PROPS_VAR_ID, /* after this marker start the variable properties */
+
+ GST_PROPS_LIST_ID,
+ GST_PROPS_FLOAT_RANGE_ID,
+ GST_PROPS_INT_RANGE_ID,
+
GST_PROPS_LAST_ID = GST_PROPS_END_ID + 16,
} GstPropsId;
#define GST_PROPS_BOOLEAN(a) GST_PROPS_BOOL_ID,(a)
#define GST_PROPS_STRING(a) GST_PROPS_STRING_ID,(a)
+#define GST_PROPS_INT_POSITIVE GST_PROPS_INT_RANGE(0,G_MAXINT)
+#define GST_PROPS_INT_NEGATIVE GST_PROPS_INT_RANGE(G_MININT,0)
+#define GST_PROPS_INT_ANY GST_PROPS_INT_RANGE(G_MININT,G_MAXINT)
+
struct _GstProps {
gint refcount;
GMutex *lock;
+ gboolean fixed;
GList *properties; /* real properties for this property */
};
void gst_props_ref (GstProps *props);
void gst_props_destroy (GstProps *props);
+void gst_props_debug (GstProps *props);
+
GstProps* gst_props_copy (GstProps *props);
GstProps* gst_props_copy_on_write (GstProps *props);
GstProps* gst_props_merge (GstProps *props, GstProps *tomerge);
gboolean gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops);
+GstProps* gst_props_intersect (GstProps *props1, GstProps *props2);
+GList* gst_props_normalize (GstProps *props);
GstProps* gst_props_set (GstProps *props, const gchar *name, ...);
+gboolean gst_props_has_property (GstProps *props, const gchar *name);
+
gint gst_props_get_int (GstProps *props, const gchar *name);
gfloat gst_props_get_float (GstProps *props, const gchar *name);
gulong gst_props_get_fourcc_int (GstProps *props, const gchar *name);
#include <gst/gstprops.h>
+#define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_ID)
+
typedef struct _GstPropsEntry GstPropsEntry;
struct _GstPropsEntry {
static void gst_queue_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
-static GstPadNegotiateReturn gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data);
-static GstPadNegotiateReturn gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
static GstBuffer * gst_queue_get (GstPad *pad);
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
}
+static GstPadConnectReturn
+gst_queue_connect (GstPad *pad, GstCaps *caps)
+{
+ GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
+ GstPad *otherpad;
+
+ if (pad == queue->srcpad)
+ otherpad = queue->sinkpad;
+ else
+ otherpad = queue->srcpad;
+
+ return gst_pad_proxy_connect (otherpad, caps);
+}
+
+static GstCaps*
+gst_queue_getcaps (GstPad *pad, GstCaps *caps)
+{
+ GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
+ GstPad *otherpad;
+
+ if (pad == queue->srcpad)
+ otherpad = queue->sinkpad;
+ else
+ otherpad = queue->srcpad;
+
+ return gst_pad_get_allowed_caps (otherpad);
+}
+
static void
gst_queue_init (GstQueue *queue)
{
GST_FLAG_SET (queue, GST_ELEMENT_EVENT_AWARE);
queue->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
- gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain));
+ gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_chain));
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
- gst_pad_set_negotiate_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_sink));
- gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_get_bufferpool));
+ gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_get_bufferpool));
+ gst_pad_set_connect_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
+ gst_pad_set_getcaps_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
- gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get));
+ gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_get));
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
- gst_pad_set_negotiate_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_src));
+ gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
+ gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
queue->leaky = GST_QUEUE_NO_LEAK;
queue->queue = NULL;
return gst_pad_get_bufferpool (queue->srcpad);
}
-static GstPadNegotiateReturn
-gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstQueue *queue;
-
- queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
-
- return gst_pad_negotiate_proxy (pad, queue->sinkpad, caps);
-}
-
-static GstPadNegotiateReturn
-gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstQueue *queue;
-
- queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
-
- return gst_pad_negotiate_proxy (pad, queue->srcpad, caps);
-}
-
static void
gst_queue_cleanup_buffers (gpointer data, const gpointer user_data)
{
gst_queue_locked_flush (queue);
}
else if (new_state == GST_STATE_PLAYING) {
- if (!GST_PAD_CONNECTED (queue->sinkpad)) {
+ if (!GST_PAD_IS_CONNECTED (queue->sinkpad)) {
/* FIXME can this be? */
if (queue->reader)
g_cond_signal (queue->not_empty);
gst_caps_get_name (caps));
typefind->caps = caps;
- gst_pad_set_caps (pad, caps);
+ if (!gst_pad_try_reconnect_filtered (pad, caps)) {
+ g_warning ("typefind: found type but peer didn't accept it");
+ }
{
int oldstate = GST_STATE(typefind);
return gst_pad_get_bufferpool (identity->srcpad);
}
-static GstPadNegotiateReturn
-gst_identity_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstIdentity *identity;
-
- identity = GST_IDENTITY (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, identity->sinkpad, caps);
-}
-
-static GstPadNegotiateReturn
-gst_identity_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstIdentity *identity;
-
- identity = GST_IDENTITY (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, identity->srcpad, caps);
-}
-
static void
gst_identity_init (GstIdentity *identity)
{
gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
gst_pad_set_chain_function (identity->sinkpad, GST_DEBUG_FUNCPTR (gst_identity_chain));
gst_pad_set_bufferpool_function (identity->sinkpad, gst_identity_get_bufferpool);
- gst_pad_set_negotiate_function (identity->sinkpad, gst_identity_negotiate_sink);
identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
- gst_pad_set_negotiate_function (identity->srcpad, gst_identity_negotiate_src);
identity->loop_based = FALSE;
identity->sleep_time = 0;
static void gst_queue_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
-static GstPadNegotiateReturn gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data);
-static GstPadNegotiateReturn gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
static GstBuffer * gst_queue_get (GstPad *pad);
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
}
+static GstPadConnectReturn
+gst_queue_connect (GstPad *pad, GstCaps *caps)
+{
+ GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
+ GstPad *otherpad;
+
+ if (pad == queue->srcpad)
+ otherpad = queue->sinkpad;
+ else
+ otherpad = queue->srcpad;
+
+ return gst_pad_proxy_connect (otherpad, caps);
+}
+
+static GstCaps*
+gst_queue_getcaps (GstPad *pad, GstCaps *caps)
+{
+ GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
+ GstPad *otherpad;
+
+ if (pad == queue->srcpad)
+ otherpad = queue->sinkpad;
+ else
+ otherpad = queue->srcpad;
+
+ return gst_pad_get_allowed_caps (otherpad);
+}
+
static void
gst_queue_init (GstQueue *queue)
{
GST_FLAG_SET (queue, GST_ELEMENT_EVENT_AWARE);
queue->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
- gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain));
+ gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_chain));
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
- gst_pad_set_negotiate_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_sink));
- gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_get_bufferpool));
+ gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_get_bufferpool));
+ gst_pad_set_connect_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
+ gst_pad_set_getcaps_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
- gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get));
+ gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_get));
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
- gst_pad_set_negotiate_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_src));
+ gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
+ gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
queue->leaky = GST_QUEUE_NO_LEAK;
queue->queue = NULL;
return gst_pad_get_bufferpool (queue->srcpad);
}
-static GstPadNegotiateReturn
-gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstQueue *queue;
-
- queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
-
- return gst_pad_negotiate_proxy (pad, queue->sinkpad, caps);
-}
-
-static GstPadNegotiateReturn
-gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstQueue *queue;
-
- queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
-
- return gst_pad_negotiate_proxy (pad, queue->srcpad, caps);
-}
-
static void
gst_queue_cleanup_buffers (gpointer data, const gpointer user_data)
{
gst_queue_locked_flush (queue);
}
else if (new_state == GST_STATE_PLAYING) {
- if (!GST_PAD_CONNECTED (queue->sinkpad)) {
+ if (!GST_PAD_IS_CONNECTED (queue->sinkpad)) {
/* FIXME can this be? */
if (queue->reader)
g_cond_signal (queue->not_empty);
return gst_pad_get_bufferpool (statistics->srcpad);
}
-static GstPadNegotiateReturn
-gst_statistics_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstStatistics *statistics;
-
- statistics = GST_STATISTICS (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, statistics->sinkpad, caps);
-}
-
-static GstPadNegotiateReturn
-gst_statistics_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
-{
- GstStatistics *statistics;
-
- statistics = GST_STATISTICS (gst_pad_get_parent (pad));
-
- return gst_pad_negotiate_proxy (pad, statistics->srcpad, caps);
-}
-
static void
gst_statistics_init (GstStatistics *statistics)
{
gst_element_add_pad (GST_ELEMENT (statistics), statistics->sinkpad);
gst_pad_set_chain_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_chain));
gst_pad_set_bufferpool_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_get_bufferpool));
- gst_pad_set_negotiate_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_sink));
statistics->srcpad = gst_pad_new ("src", GST_PAD_SRC);
gst_element_add_pad (GST_ELEMENT (statistics), statistics->srcpad);
- gst_pad_set_negotiate_function (statistics->srcpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_src));
statistics->timer = NULL;
statistics->last_timer = NULL;
static void gst_tee_chain (GstPad *pad, GstBuffer *buf);
-static GstPadNegotiateReturn gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
static GstElementClass *parent_class = NULL;
/*static guint gst_tee_signals[LAST_SIGNAL] = { 0 };*/
FALSE, G_PARAM_READWRITE));
-
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_tee_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_tee_get_property);
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_tee_request_new_pad);
}
+static gboolean
+gst_tee_sinkconnect (GstPad *pad, GstCaps *caps)
+{
+ GstTee *tee;
+ GList *pads;
+
+ tee = GST_TEE (gst_pad_get_parent (pad));
+
+ /* go through all the src pads */
+ pads = gst_element_get_pad_list (GST_ELEMENT (tee));
+
+ while (pads) {
+ GstPad *outpad = GST_PAD (pads->data);
+ pads = g_list_next (pads);
+
+ if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_IS_CONNECTED (outpad))
+ continue;
+
+ if (!(gst_pad_try_set_caps (outpad, caps))) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
static void
gst_tee_init (GstTee *tee)
{
tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
- gst_pad_set_negotiate_function (tee->sinkpad, GST_DEBUG_FUNCPTR(gst_tee_handle_negotiate_sink));
+ gst_pad_set_connect_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_sinkconnect));
tee->silent = FALSE;
}
GST_PAD_ELEMENT_PRIVATE (srcpad) = NULL;
if (GST_PAD_CAPS (tee->sinkpad)) {
- gst_pad_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
+ gst_pad_try_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
}
return srcpad;
GstEvent *event = GST_EVENT (GST_PAD_ELEMENT_PRIVATE (outpad));
GST_PAD_ELEMENT_PRIVATE (outpad) = NULL;
- if (GST_PAD_CONNECTED (outpad))
+ if (GST_PAD_IS_CONNECTED (outpad))
gst_pad_push (outpad, GST_BUFFER (event));
else
gst_event_free (event);
}
if (!tee->silent) {
- gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu) \n",
+ gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu)",
GST_DEBUG_PAD_NAME (outpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
}
- if (GST_PAD_CONNECTED (outpad))
+ if (GST_PAD_IS_CONNECTED (outpad))
gst_pad_push (outpad, buf);
else
gst_buffer_unref (buf);
return TRUE;
}
-static GstPadNegotiateReturn
-gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer* data)
-{
- GstCaps* tempcaps;
- gint i;
- GstTee* tee = GST_TEE (GST_OBJECT_PARENT (pad));
- GList *pads;
-
- if (*caps==NULL)
- return GST_PAD_NEGOTIATE_FAIL;
-
- /* go through all the src pads */
- pads = gst_element_get_pad_list (GST_ELEMENT (tee));
-
- while (pads) {
- GstPad *outpad = GST_PAD (pads->data);
- pads = g_list_next (pads);
-
- if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_CONNECTED (outpad))
- continue;
-
- if (!(gst_pad_set_caps (outpad, *caps))) {
- return GST_PAD_NEGOTIATE_FAIL;
- }
- }
- return GST_PAD_NEGOTIATE_AGREE;
-}