Index: plugins/elements/gsttee.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/plugins/elements/gsttee.c,v
retrieving revision 1.86
diff -u -p -u -p -r1.86 gsttee.c
--- plugins/elements/gsttee.c	20 Jun 2008 10:14:53 -0000	1.86
+++ plugins/elements/gsttee.c	29 Jun 2008 13:38:41 -0000
@@ -138,11 +138,20 @@ gst_tee_base_init (gpointer g_class)
 }
 
 static void
-gst_tee_finalize (GObject * object)
+gst_tee_dispose (GObject * object)
 {
-  GstTee *tee;
+  GstTee *tee = GST_TEE (object);
+  
+  gst_caps_replace (&tee->sinkcaps, NULL);
+  gst_caps_replace (&tee->srccaps, NULL);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
 
-  tee = GST_TEE (object);
+static void
+gst_tee_finalize (GObject * object)
+{
+  GstTee *tee = GST_TEE (object);
 
   g_free (tee->last_message);
 
@@ -158,6 +167,7 @@ gst_tee_class_init (GstTeeClass * klass)
   gobject_class = G_OBJECT_CLASS (klass);
   gstelement_class = GST_ELEMENT_CLASS (klass);
 
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_tee_dispose);
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_tee_finalize);
   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_tee_set_property);
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_tee_get_property);
@@ -194,6 +204,118 @@ gst_tee_class_init (GstTeeClass * klass)
   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_tee_release_pad);
 }
 
+/* we can only accept caps that we and upstream can handle. */
+static GstCaps *
+gst_tee_src_getcaps (GstPad * pad)
+{
+  GstTee *tee;
+  GstCaps *result, *peercaps, *srccaps;
+
+  tee = GST_TEE (GST_PAD_PARENT (pad));
+  GST_INFO ("getcaps for %s:%s [", GST_DEBUG_PAD_NAME (pad));
+
+  if (tee->srccaps) {
+    result = gst_caps_copy (tee->srccaps);
+    GST_INFO ("getcaps for %s:%s ] = cached caps", GST_DEBUG_PAD_NAME (pad));
+  }
+  else {
+    GST_OBJECT_LOCK (tee);
+    
+    /* get the upstream possible caps */
+    peercaps = gst_pad_peer_get_caps (tee->sinkpad);
+    /* 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 (tee, "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 srcpad. */
+      GST_DEBUG_OBJECT (tee, "no peer caps, using template caps");
+      result = srccaps;
+      GST_INFO ("getcaps for %s:%s ] = template caps", GST_DEBUG_PAD_NAME (pad));
+    }
+    tee->srccaps = gst_caps_copy (result);
+    gst_caps_replace (&tee->sinkcaps, NULL);
+    
+    GST_OBJECT_UNLOCK (tee);
+  }
+
+  return result;
+}
+
+static GstCaps *
+gst_tee_sink_getcaps (GstPad * pad)
+{
+  GstTee *tee;
+  GstCaps *result, *peercaps = NULL, *sinkcaps;
+
+  tee = GST_TEE (GST_PAD_PARENT (pad));
+  GST_INFO ("getcaps for %s:%s [", GST_DEBUG_PAD_NAME (pad));
+
+  if (tee->sinkcaps) {
+    result = gst_caps_copy (tee->sinkcaps);
+    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_src_pads (GST_ELEMENT(tee));
+    while (!done) {
+      switch (gst_iterator_next (it, &item)) {
+        case GST_ITERATOR_OK:
+          /* get the downstream 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 (tee);
+    
+    /* 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 (tee, "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 (tee, "no peer caps, using sinkcaps");
+      result = sinkcaps;
+      GST_INFO ("getcaps for %s:%s ] = template caps", GST_DEBUG_PAD_NAME (pad));
+    }  
+    tee->sinkcaps = gst_caps_copy (result);
+    gst_caps_replace (&tee->srccaps, NULL);
+
+    GST_OBJECT_UNLOCK (tee);
+  }
+
+  return result;
+}
+
 static void
 gst_tee_init (GstTee * tee, GstTeeClass * g_class)
 {
@@ -203,7 +325,7 @@ gst_tee_init (GstTee * tee, GstTeeClass 
   gst_pad_set_setcaps_function (tee->sinkpad,
       GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));
   gst_pad_set_getcaps_function (tee->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+      GST_DEBUG_FUNCPTR (gst_tee_sink_getcaps));
   gst_pad_set_bufferalloc_function (tee->sinkpad,
       GST_DEBUG_FUNCPTR (gst_tee_buffer_alloc));
   gst_pad_set_activatepush_function (tee->sinkpad,
@@ -264,7 +386,7 @@ gst_tee_request_new_pad (GstElement * el
   gst_pad_set_setcaps_function (srcpad,
       GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));
   gst_pad_set_getcaps_function (srcpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+      GST_DEBUG_FUNCPTR (gst_tee_src_getcaps));
   gst_pad_set_activatepull_function (srcpad,
       GST_DEBUG_FUNCPTR (gst_tee_src_activate_pull));
   gst_pad_set_checkgetrange_function (srcpad,
Index: plugins/elements/gsttee.h
===================================================================
RCS file: /cvs/gstreamer/gstreamer/plugins/elements/gsttee.h,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 gsttee.h
--- plugins/elements/gsttee.h	9 Feb 2007 13:45:27 -0000	1.18
+++ plugins/elements/gsttee.h	29 Jun 2008 13:38:41 -0000
@@ -78,6 +78,9 @@ struct _GstTee {
   GstActivateMode sink_mode;
   GstTeePullMode  pull_mode;
   GstPad         *pull_pad;
+  
+  /* cache caps for faster capsnego */
+  GstCaps        *srccaps, *sinkcaps;
 };
 
 struct _GstTeeClass {
