basetransform: cache transformed caps where appropriate
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Thu, 20 Oct 2011 13:02:44 +0000 (14:02 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 20 Oct 2011 14:54:27 +0000 (16:54 +0200)
Speeds up negotiation a fair bit on a contrived pipeline
with a dozen colorspace conversions.

Hopefully clears out the cache every time it ought to.

https://bugzilla.gnome.org/show_bug.cgi?id=662291

libs/gst/base/gstbasetransform.c

index 7ccfb04778850603a62e85f90c8cfe0ebcad3b1a..7561948ab5d817e5ff66ca60e10ba2fe09365d70 100644 (file)
@@ -282,6 +282,9 @@ struct _GstBaseTransformPrivate
 
   GstClockTime last_stop_out;
   GList *delayed_events;
+
+  GstCaps *cached_peer_caps[2];
+  GstCaps *cached_transformed_caps[2];
 };
 
 static GstElementClass *parent_class = NULL;
@@ -369,6 +372,24 @@ gst_base_transform_drop_delayed_events (GstBaseTransform * trans)
   GST_OBJECT_UNLOCK (trans);
 }
 
+static void
+gst_base_transform_clear_transformed_caps_cache (GstBaseTransform * trans)
+{
+  struct _GstBaseTransformPrivate *priv = trans->priv;
+  int n;
+
+  for (n = 0; n < 2; ++n) {
+    if (priv->cached_peer_caps[n]) {
+      gst_caps_unref (priv->cached_peer_caps[n]);
+      priv->cached_peer_caps[n] = NULL;
+    }
+    if (priv->cached_transformed_caps[n]) {
+      gst_caps_unref (priv->cached_transformed_caps[n]);
+      priv->cached_transformed_caps[n] = NULL;
+    }
+  }
+}
+
 static void
 gst_base_transform_finalize (GObject * object)
 {
@@ -380,6 +401,8 @@ gst_base_transform_finalize (GObject * object)
   gst_caps_replace (&trans->priv->sink_suggest, NULL);
   g_mutex_free (trans->transform_lock);
 
+  gst_base_transform_clear_transformed_caps_cache (trans);
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -674,13 +697,36 @@ gst_base_transform_getcaps (GstPad * pad)
   GstPad *otherpad;
   const GstCaps *templ;
   GstCaps *peercaps, *caps, *temp;
+  gboolean samecaps;
+  int cache_index;
 
   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
 
   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
+  cache_index = (pad == trans->srcpad) ? 0 : 1;
 
   /* we can do what the peer can */
   peercaps = gst_pad_peer_get_caps_reffed (otherpad);
+  GST_OBJECT_LOCK (trans);
+  samecaps = (peercaps && trans->priv->cached_peer_caps[cache_index]
+      && gst_caps_is_equal (peercaps,
+          trans->priv->cached_peer_caps[cache_index]));
+  if (!samecaps) {
+    if (trans->priv->cached_peer_caps[cache_index]) {
+      gst_caps_unref (trans->priv->cached_peer_caps[cache_index]);
+      trans->priv->cached_peer_caps[cache_index] = NULL;
+    }
+    if (trans->priv->cached_transformed_caps[cache_index]) {
+      gst_caps_unref (trans->priv->cached_transformed_caps[cache_index]);
+      trans->priv->cached_transformed_caps[cache_index] = NULL;
+    }
+  } else {
+    caps = gst_caps_ref (trans->priv->cached_transformed_caps[cache_index]);
+    GST_OBJECT_UNLOCK (trans);
+    return caps;
+  }
+  GST_OBJECT_UNLOCK (trans);
+
   if (peercaps) {
     GST_DEBUG_OBJECT (pad, "peer caps  %" GST_PTR_FORMAT, peercaps);
 
@@ -726,6 +772,15 @@ gst_base_transform_getcaps (GstPad * pad)
 done:
   GST_DEBUG_OBJECT (trans, "returning  %" GST_PTR_FORMAT, caps);
 
+  GST_OBJECT_LOCK (trans);
+  if (peercaps) {
+    trans->priv->cached_peer_caps[cache_index] = gst_caps_ref (peercaps);
+  }
+  if (caps) {
+    trans->priv->cached_transformed_caps[cache_index] = gst_caps_ref (caps);
+  }
+  GST_OBJECT_UNLOCK (trans);
+
   if (peercaps)
     gst_caps_unref (peercaps);
 
@@ -2616,6 +2671,10 @@ gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
+  GST_OBJECT_LOCK (trans);
+  gst_base_transform_clear_transformed_caps_cache (trans);
+  GST_OBJECT_UNLOCK (trans);
+
   if (active) {
     if (trans->priv->pad_mode == GST_ACTIVATE_NONE && bclass->start)
       result &= bclass->start (trans);
@@ -2987,6 +3046,7 @@ gst_base_transform_reconfigure (GstBaseTransform * trans)
   GST_OBJECT_LOCK (trans);
   GST_DEBUG_OBJECT (trans, "marking reconfigure");
   trans->priv->reconfigure = TRUE;
+  gst_base_transform_clear_transformed_caps_cache (trans);
   gst_caps_replace (&trans->priv->sink_alloc, NULL);
   GST_OBJECT_UNLOCK (trans);
 }