Index: gst/adder/gstadder.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst/adder/gstadder.c,v
retrieving revision 1.100
diff -u -p -u -p -r1.100 gstadder.c
--- gst/adder/gstadder.c	29 Jun 2008 13:45:27 -0000	1.100
+++ gst/adder/gstadder.c	29 Jun 2008 13:47:38 -0000
@@ -118,6 +118,7 @@ static void gst_adder_class_init (GstAdd
 
 static void gst_adder_init (GstAdder * adder);
 
+static void gst_adder_dispose (GObject * object);
 static void gst_adder_finalize (GObject * object);
 
 static gboolean gst_adder_setcaps (GstPad * pad, GstCaps * caps);
@@ -196,26 +197,106 @@ gst_adder_sink_getcaps (GstPad * pad)
   GstCaps *result, *peercaps, *sinkcaps;
 
   adder = GST_ADDER (GST_PAD_PARENT (pad));
+  GST_INFO ("getcaps for %s:%s [", GST_DEBUG_PAD_NAME (pad));
 
-  GST_OBJECT_LOCK (adder);
-  /* get the downstream possible caps */
-  peercaps = gst_pad_peer_get_caps (adder->srcpad);
-  /* get the allowed caps on this sinkpad, we use the fixed caps function so
-   * that it does not call recursively in this function. */
-  sinkcaps = gst_pad_get_fixed_caps_func (pad);
-  if (peercaps) {
-    /* if the peer has caps, intersect */
-    GST_DEBUG_OBJECT (adder, "intersecting peer and template caps");
-    result = gst_caps_intersect (peercaps, sinkcaps);
-    gst_caps_unref (peercaps);
-    gst_caps_unref (sinkcaps);
-  } else {
-    /* the peer has no caps (or there is no peer), just use the allowed caps
-     * of this sinkpad. */
-    GST_DEBUG_OBJECT (adder, "no peer caps, using sinkcaps");
-    result = sinkcaps;
+  if (adder->sinkcaps) {
+    result = gst_caps_copy (adder->sinkcaps);
+    GST_INFO ("getcaps for %s:%s ] = cached caps", GST_DEBUG_PAD_NAME (pad));
+  }
+  else {
+    GST_OBJECT_LOCK (adder);
+
+    /* get the downstream possible caps */
+    peercaps = gst_pad_peer_get_caps (adder->srcpad);
+    /* get the allowed caps on this sinkpad, we use the fixed caps function so
+     * that it does not call recursively in this function. */
+    sinkcaps = gst_pad_get_fixed_caps_func (pad);
+    if (peercaps) {
+      /* if the peer has caps, intersect */
+      GST_DEBUG_OBJECT (adder, "intersecting peer and template caps");
+      result = gst_caps_intersect (peercaps, sinkcaps);
+      gst_caps_unref (peercaps);
+      gst_caps_unref (sinkcaps);
+      GST_INFO ("getcaps for %s:%s ] = intersected caps", GST_DEBUG_PAD_NAME (pad));
+    } else {
+      /* the peer has no caps (or there is no peer), just use the allowed caps
+       * of this sinkpad. */
+      GST_DEBUG_OBJECT (adder, "no peer caps, using template caps");
+      result = sinkcaps;
+      GST_INFO ("getcaps for %s:%s ] = template caps", GST_DEBUG_PAD_NAME (pad));
+    }
+    adder->sinkcaps = gst_caps_copy (result);
+    gst_caps_replace (&adder->srccaps, NULL);
+
+    GST_OBJECT_UNLOCK (adder);
+  }
+
+  return result;
+}
+
+static GstCaps *
+gst_adder_src_getcaps (GstPad * pad)
+{
+  GstAdder *adder;
+  GstCaps *result, *peercaps = NULL, *srccaps;
+
+  adder = GST_ADDER (GST_PAD_PARENT (pad));
+  GST_INFO ("getcaps for %s:%s [", GST_DEBUG_PAD_NAME (pad));
+
+  if (adder->srccaps) {
+    result = gst_caps_copy (adder->srccaps);
+    GST_INFO ("getcaps for %s:%s ] = cached caps", GST_DEBUG_PAD_NAME (pad));
+  }
+  else {
+    GstIterator *it;
+    gpointer item;
+    gboolean done=FALSE;
+
+    /* get first srcpad */
+    it = gst_element_iterate_sink_pads (GST_ELEMENT(adder));
+    while (!done) {
+      switch (gst_iterator_next (it, &item)) {
+        case GST_ITERATOR_OK:
+          /* get the upstream possible caps of first pads that has some */
+          if ((peercaps = gst_pad_peer_get_caps (GST_PAD(item))))
+            done = TRUE;
+          gst_object_unref (item);
+          break;
+        case GST_ITERATOR_RESYNC:
+          gst_iterator_resync (it);
+          break;
+        case GST_ITERATOR_ERROR:
+        case GST_ITERATOR_DONE:
+          done = TRUE;
+          break;
+      }
+    }
+    gst_iterator_free (it);
+  
+    GST_OBJECT_LOCK (adder);
+    
+    /* get the allowed caps on this sinkpad, we use the fixed caps function so
+     * that it does not call recursively in this function. */
+    srccaps = gst_pad_get_fixed_caps_func (pad);
+    if (peercaps) {
+      /* if the peer has caps, intersect */
+      GST_DEBUG_OBJECT (adder, "intersecting peer and template caps");
+      result = gst_caps_intersect (peercaps, srccaps);
+      gst_caps_unref (peercaps);
+      gst_caps_unref (srccaps);
+      GST_INFO ("getcaps for %s:%s ] = intersected caps", GST_DEBUG_PAD_NAME (pad));
+    } else {
+      /* the peer has no caps (or there is no peer), just use the allowed caps
+       * of this sinkpad. */
+      GST_DEBUG_OBJECT (adder, "no peer caps, using srccaps");
+      result = srccaps;
+      GST_INFO ("getcaps for %s:%s ] = template caps", GST_DEBUG_PAD_NAME (pad));
+    }  
+    adder->srccaps = gst_caps_copy (result);
+    gst_caps_replace (&adder->sinkcaps, NULL);
+
+    GST_OBJECT_UNLOCK (adder);
   }
-  GST_OBJECT_UNLOCK (adder);
 
   return result;
 }
@@ -705,6 +786,7 @@ gst_adder_class_init (GstAdderClass * kl
 
   gobject_class = (GObjectClass *) klass;
 
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_adder_dispose);
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_adder_finalize);
 
   gstelement_class = (GstElementClass *) klass;
@@ -735,7 +817,7 @@ gst_adder_init (GstAdder * adder)
   gst_object_unref (template);
 
   gst_pad_set_getcaps_function (adder->srcpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+      GST_DEBUG_FUNCPTR (gst_adder_src_getcaps));
   gst_pad_set_setcaps_function (adder->srcpad,
       GST_DEBUG_FUNCPTR (gst_adder_setcaps));
   gst_pad_set_query_function (adder->srcpad,
@@ -755,6 +837,17 @@ gst_adder_init (GstAdder * adder)
 }
 
 static void
+gst_adder_dispose (GObject * object)
+{
+  GstAdder *adder = GST_ADDER (object);
+
+  gst_caps_replace (&adder->sinkcaps, NULL);
+  gst_caps_replace (&adder->srccaps, NULL);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
 gst_adder_finalize (GObject * object)
 {
   GstAdder *adder = GST_ADDER (object);
Index: gst/adder/gstadder.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst/adder/gstadder.h,v
retrieving revision 1.24
diff -u -p -u -p -r1.24 gstadder.h
--- gst/adder/gstadder.h	8 May 2007 19:24:01 -0000	1.24
+++ gst/adder/gstadder.h	29 Jun 2008 13:47:38 -0000
@@ -87,6 +87,9 @@ struct _GstAdder {
   gboolean        segment_pending;
   guint64         segment_position;
   gdouble         segment_rate;
+
+  /* cache caps for faster capsnego */
+  GstCaps        *srccaps, *sinkcaps;
 };
 
 struct _GstAdderClass {
