+2004-01-02 David Schleef <ds@schleef.org>
+
+ * gst/gstcaps.c: (_gst_structure_is_equal_foreach),
+ (gst_caps_is_equal_fixed): Add new function.
+ * gst/gstcaps.h: ditto.
+ * gst/gstpad.c: (gst_real_pad_class_init),
+ (gst_pad_link_call_link_functions), (gst_pad_try_set_caps),
+ (gst_pad_set_explicit_caps), (gst_pad_get_caps): In try_set_caps,
+ check new caps against existing caps -- if they're the same, return
+ OK without renegotiating. caps-nego-failed signal fixed so that
+ the marshaller isn't VOID__OBJECT. Also changed to G_TYPE_POINTER
+ to save an extra caps copy. Don't complete negotiation if a pad
+ link function returns DELAYED.
+
2004-01-02 Benjamin Otte <in7y118@public.uni-hamburg.de>
* gst/gstpad.c: (gst_pad_try_relink_filtered):
}
static gboolean
+_gst_structure_is_equal_foreach (GQuark field_id,
+ GValue *val2, gpointer data)
+{
+ GstStructure *struct1 = (GstStructure *) data;
+ const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
+
+ if (val1 == NULL) return FALSE;
+ if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean gst_caps_is_equal_fixed (const GstCaps *caps1, const GstCaps *caps2)
+{
+ GstStructure *struct1, *struct2;
+
+ g_return_val_if_fail (gst_caps_is_fixed(caps1), FALSE);
+ g_return_val_if_fail (gst_caps_is_fixed(caps2), FALSE);
+
+ struct1 = gst_caps_get_structure (caps1, 0);
+ struct2 = gst_caps_get_structure (caps2, 0);
+
+ if (struct1->name != struct2->name) {
+ return FALSE;
+ }
+ if (struct1->fields->len != struct2->fields->len) {
+ return FALSE;
+ }
+
+ return gst_structure_foreach (struct1, _gst_structure_is_equal_foreach,
+ struct2);
+}
+
+static gboolean
_gst_structure_field_has_compatible (GQuark field_id,
GValue *val2, gpointer data)
{
gst_real_pad_signals[REAL_CAPS_NEGO_FAILED] =
g_signal_new ("caps_nego_failed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstRealPadClass, caps_nego_failed), NULL, NULL,
- gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
- GST_TYPE_CAPS);
+ gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
gst_real_pad_signals[REAL_LINKED] =
g_signal_new ("linked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstRealPadClass, linked), NULL, NULL,
GST_DEBUG ("got reply %d from link function on pad %s:%s",
res, GST_DEBUG_PAD_NAME (link->srcpad));
- if (res == GST_PAD_LINK_REFUSED) {
+ if (GST_PAD_LINK_FAILED (res)) {
GST_CAT_INFO (GST_CAT_CAPS, "pad %s:%s doesn't accept caps",
GST_DEBUG_PAD_NAME (link->srcpad));
return FALSE;
GST_DEBUG ("got reply %d from link function on pad %s:%s",
res, GST_DEBUG_PAD_NAME (link->sinkpad));
- if (res == GST_PAD_LINK_REFUSED) {
+ if (GST_PAD_LINK_FAILED (res)) {
GST_CAT_INFO (GST_CAT_CAPS, "pad %s:%s doesn't accept caps",
GST_DEBUG_PAD_NAME (link->sinkpad));
return FALSE;
return GST_PAD_LINK_OK;
}
+ /* if the desired caps are already there, it's trivially ok */
+ if (GST_PAD_CAPS (pad) && gst_caps_is_equal_fixed (caps,
+ GST_PAD_CAPS (pad))) {
+ return GST_PAD_LINK_OK;
+ }
+
g_return_val_if_fail (GST_PAD_LINK_SRC (pad), GST_PAD_LINK_REFUSED);
g_return_val_if_fail (GST_PAD_LINK_SINK (pad), GST_PAD_LINK_REFUSED);
return caps;
} else if (GST_PAD_PAD_TEMPLATE (realpad)) {
GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (realpad);
+ const GstCaps *caps;
+
GST_CAT_DEBUG (GST_CAT_CAPS, "using pad template %p with caps %p",
templ, GST_PAD_TEMPLATE_CAPS (templ));
+
+ caps = GST_PAD_TEMPLATE_CAPS (templ);
+#if 0
+ /* FIXME we should enable something like this someday, but this is
+ * a bit buggy */
+ if (!gst_caps_is_fixed (caps)) {
+ g_warning("pad %s:%s (%p) has no getcaps function and the pad template returns non-fixed caps. Element is probably broken.\n",
+ GST_DEBUG_PAD_NAME (realpad), realpad);
+ }
+#endif
+
return gst_caps_copy (GST_PAD_TEMPLATE_CAPS (templ));
}
GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
#if 0
- /* FIXME this should be enabled some day */
+ /* FIXME enable */
g_warning("pad %s:%s (%p) has no pad template\n",
GST_DEBUG_PAD_NAME (realpad), realpad);
#endif