gst: Add a filter caps parameter to all get_caps() functions
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 10 May 2011 15:56:33 +0000 (17:56 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 16 May 2011 13:33:10 +0000 (15:33 +0200)
This is used to pass the possible caps and preferences to
the pad and to allow better negotiation decisions.

docs/random/porting-to-0.11.txt
gst/gstghostpad.c
gst/gstpad.c
gst/gstpad.h
gst/gstutils.c
gst/gstutils.h

index 0fe0348..e0c1571 100644 (file)
@@ -84,6 +84,10 @@ The 0.11 porting guide
     Removed GST_PAD_CAPS() use gst_pad_get_current_caps() to get a handle to the
     currently configured caps.
 
+    GstPadGetCapsFunction, gst_pad_get_caps(), gst_pad_peer_get_caps(),
+    gst_pad_proxy_getcaps() now takes a GstCaps* parameter to inform
+    the other side about the possible caps and preferences.
+
 * GstMiniObject
     A miniobject is now a simple refcounted structure holding the information
     common to buffers, events, messages, queries and caps.
index 62beec7..b33a241 100644 (file)
@@ -188,7 +188,7 @@ gst_proxy_pad_do_checkgetrange (GstPad * pad)
 }
 
 static GstCaps *
-gst_proxy_pad_do_getcaps (GstPad * pad)
+gst_proxy_pad_do_getcaps (GstPad * pad, GstCaps * filter)
 {
   GstPad *target = gst_proxy_pad_get_target (pad);
   GstCaps *res;
@@ -196,7 +196,7 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
 
   if (target) {
     /* if we have a real target, proxy the call */
-    res = gst_pad_get_caps (target);
+    res = gst_pad_get_caps (target, filter);
 
     GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
         GST_DEBUG_PAD_NAME (target), res);
@@ -209,7 +209,7 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
 
       filt = GST_PAD_TEMPLATE_CAPS (templ);
       if (filt) {
-        tmp = gst_caps_intersect (filt, res);
+        tmp = gst_caps_intersect_full (res, filt, GST_CAPS_INTERSECT_FIRST);
         gst_caps_unref (res);
         res = tmp;
         GST_DEBUG_OBJECT (pad,
@@ -224,6 +224,15 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
           "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
           res);
       res = gst_caps_ref (res);
+
+      if (filter) {
+        GstCaps *intersection =
+            gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
+
+        gst_caps_unref (res);
+        res = intersection;
+      }
+
       goto done;
     }
 
index 3b6942e..22cfc46 100644 (file)
@@ -124,7 +124,7 @@ static void gst_pad_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
 static GstFlowReturn handle_pad_block (GstPad * pad);
-static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad);
+static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter);
 static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ);
 static gboolean gst_pad_activate_default (GstPad * pad);
 static gboolean gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps);
@@ -1796,8 +1796,8 @@ gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink,
 
   /* Doing the expensive caps checking takes priority over only checking the template caps */
   if (flags & GST_PAD_LINK_CHECK_CAPS) {
-    srccaps = gst_pad_get_caps_unlocked (src);
-    sinkcaps = gst_pad_get_caps_unlocked (sink);
+    srccaps = gst_pad_get_caps_unlocked (src, NULL);
+    sinkcaps = gst_pad_get_caps_unlocked (sink, NULL);
   } else {
     /* If one of the two pads doesn't have a template, consider the intersection
      * as valid.*/
@@ -2188,7 +2188,7 @@ gst_pad_get_pad_template (GstPad * pad)
 /* should be called with the pad LOCK held */
 /* refs the caps, so caller is responsible for getting it unreffed */
 static GstCaps *
-gst_pad_get_caps_unlocked (GstPad * pad)
+gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter)
 {
   GstCaps *result = NULL;
   GstPadTemplate *templ;
@@ -2200,11 +2200,12 @@ gst_pad_get_caps_unlocked (GstPad * pad)
 
   if (!fixed_caps && GST_PAD_GETCAPSFUNC (pad)) {
     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "dispatching to pad getcaps function");
+        "dispatching to pad getcaps function with "
+        "filter %" GST_PTR_FORMAT, filter);
 
     GST_OBJECT_FLAG_SET (pad, GST_PAD_IN_GETCAPS);
     GST_OBJECT_UNLOCK (pad);
-    result = GST_PAD_GETCAPSFUNC (pad) (pad);
+    result = GST_PAD_GETCAPSFUNC (pad) (pad, filter);
     GST_OBJECT_LOCK (pad);
     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_GETCAPS);
 
@@ -2234,29 +2235,80 @@ gst_pad_get_caps_unlocked (GstPad * pad)
           result = temp;
         }
       }
+      if (filter) {
+        if (!gst_caps_is_subset (result, filter)) {
+          GstCaps *temp;
+
+          GST_CAT_ERROR_OBJECT (GST_CAT_CAPS, pad,
+              "pad returned caps %" GST_PTR_FORMAT
+              " which are not a real subset of the filter caps %"
+              GST_PTR_FORMAT, result, filter);
+          g_warning ("pad %s:%s returned caps which are not a real "
+              "subset of the filter caps", GST_DEBUG_PAD_NAME (pad));
+          /* FIXME: Order? But shouldn't happen anyway... */
+          temp =
+              gst_caps_intersect_full (filter, result,
+              GST_CAPS_INTERSECT_FIRST);
+          gst_caps_unref (result);
+          result = temp;
+        }
+      }
 #endif
       goto done;
     }
   }
   if (fixed_caps && (result = get_pad_caps (pad))) {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "using pad caps %p %" GST_PTR_FORMAT, result, result);
-    result = gst_caps_ref (result);
+    if (filter) {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+          "using pad caps %p %" GST_PTR_FORMAT " with filter %p %"
+          GST_PTR_FORMAT, result, result, filter, filter);
+      result =
+          gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
+          result);
+    } else {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+          "using pad caps %p %" GST_PTR_FORMAT, result, result);
+      result = gst_caps_ref (result);
+    }
     goto done;
   }
   if ((templ = GST_PAD_PAD_TEMPLATE (pad))) {
     result = GST_PAD_TEMPLATE_CAPS (templ);
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
-        result);
 
-    result = gst_caps_ref (result);
+    if (filter) {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+          "using pad template %p with caps %p %" GST_PTR_FORMAT
+          " and filter %p %" GST_PTR_FORMAT, templ, result, result, filter,
+          filter);
+      result =
+          gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
+          result);
+    } else {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+          "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
+          result);
+      result = gst_caps_ref (result);
+    }
+
     goto done;
   }
   if (!fixed_caps && (result = get_pad_caps (pad))) {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "using pad caps %p %" GST_PTR_FORMAT, result, result);
-    result = gst_caps_ref (result);
+    if (filter) {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+          "using pad caps %p %" GST_PTR_FORMAT " with filter %p %"
+          GST_PTR_FORMAT, result, result, filter, filter);
+      result =
+          gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
+          result);
+    } else {
+      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+          "using pad caps %p %" GST_PTR_FORMAT, result, result);
+      result = gst_caps_ref (result);
+    }
+
     goto done;
   }
 
@@ -2319,6 +2371,7 @@ gst_pad_get_current_caps (GstPad * pad)
 /**
  * gst_pad_get_caps:
  * @pad: a  #GstPad to get the capabilities of.
+ * @filter: suggested #GstCaps.
  *
  * Gets the capabilities this pad can produce or consume.
  * Note that this method doesn't necessarily return the caps set by
@@ -2327,23 +2380,30 @@ gst_pad_get_current_caps (GstPad * pad)
  * the pad's get_caps function;
  * this returns the pad template caps if not explicitly set.
  *
+ * When called on sinkpads @filter contains the caps that
+ * upstream could produce in the order preferred by upstream. When
+ * called on srcpads @filter contains the caps accepted by
+ * downstream in the preffered order. @filter might be %NULL but
+ * if it is not %NULL the returned caps will be a subset of @filter.
+ *
  * Note that this function does not return writable #GstCaps, use
  * gst_caps_make_writable() before modifying the caps.
  *
  * Returns: the caps of the pad with incremented ref-count.
  */
 GstCaps *
-gst_pad_get_caps (GstPad * pad)
+gst_pad_get_caps (GstPad * pad, GstCaps * filter)
 {
   GstCaps *result = NULL;
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
 
   GST_OBJECT_LOCK (pad);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
 
-  result = gst_pad_get_caps_unlocked (pad);
+  result = gst_pad_get_caps_unlocked (pad, filter);
 
   GST_OBJECT_UNLOCK (pad);
 
@@ -2354,20 +2414,28 @@ gst_pad_get_caps (GstPad * pad)
 /**
  * gst_pad_peer_get_caps:
  * @pad: a  #GstPad to get the capabilities of.
+ * @filter: a #GstCaps filter.
  *
  * Gets the capabilities of the peer connected to this pad. Similar to
  * gst_pad_get_caps().
  *
+ * When called on srcpads @filter contains the caps that
+ * upstream could produce in the order preferred by upstream. When
+ * called on sinkpads @filter contains the caps accepted by
+ * downstream in the preffered order. @filter might be %NULL but
+ * if it is not %NULL the returned caps will be a subset of @filter.
+ *
  * Returns: the caps of the peer pad with incremented ref-count. This function
  * returns %NULL when there is no peer pad.
  */
 GstCaps *
-gst_pad_peer_get_caps (GstPad * pad)
+gst_pad_peer_get_caps (GstPad * pad, GstCaps * filter)
 {
   GstPad *peerpad;
   GstCaps *result = NULL;
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
 
   GST_OBJECT_LOCK (pad);
 
@@ -2380,7 +2448,7 @@ gst_pad_peer_get_caps (GstPad * pad)
   gst_object_ref (peerpad);
   GST_OBJECT_UNLOCK (pad);
 
-  result = gst_pad_get_caps (peerpad);
+  result = gst_pad_get_caps (peerpad, filter);
 
   gst_object_unref (peerpad);
 
@@ -2503,7 +2571,7 @@ gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
 
   GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps);
 
-  allowed = gst_pad_get_caps (pad);
+  allowed = gst_pad_get_caps (pad, NULL);
   if (!allowed)
     goto nothing_allowed;
 
@@ -2826,9 +2894,9 @@ gst_pad_get_allowed_caps (GstPad * pad)
 
   gst_object_ref (peer);
   GST_OBJECT_UNLOCK (pad);
-  mycaps = gst_pad_get_caps (pad);
+  mycaps = gst_pad_get_caps (pad, NULL);
 
-  peercaps = gst_pad_get_caps (peer);
+  peercaps = gst_pad_get_caps (peer, NULL);
   gst_object_unref (peer);
 
   caps = gst_caps_intersect (mycaps, peercaps);
index 412c130..475e141 100644 (file)
@@ -420,6 +420,13 @@ typedef void                       (*GstPadUnlinkFunction)         (GstPad *pad);
 /**
  * GstPadGetCapsFunction:
  * @pad: the #GstPad to get the capabilities of.
+ * @filter: filter #GstCaps.
+ *
+ * When called on sinkpads @filter contains the caps that
+ * upstream could produce in the order preferred by upstream. When
+ * called on srcpads @filter contains the caps accepted by
+ * downstream in the preffered order. @filter might be %NULL but if
+ * it is not %NULL only a subset of @filter must be returned.
  *
  * Returns a copy of the capabilities of the specified pad. By default this
  * function will return the pad template capabilities, but can optionally
@@ -427,7 +434,7 @@ typedef void                        (*GstPadUnlinkFunction)         (GstPad *pad);
  *
  * Returns: a newly allocated copy #GstCaps of the pad.
  */
-typedef GstCaps*               (*GstPadGetCapsFunction)        (GstPad *pad);
+typedef GstCaps*               (*GstPadGetCapsFunction)        (GstPad *pad, GstCaps *filter);
 
 /**
  * GstPadSetCapsFunction:
@@ -845,12 +852,12 @@ G_CONST_RETURN GstCaps*   gst_pad_get_pad_template_caps           (GstPad *pad);
 /* capsnego function for linked/unlinked pads */
 GstCaps *              gst_pad_get_current_caps                (GstPad * pad);
 gboolean               gst_pad_has_current_caps                (GstPad * pad);
-GstCaps *              gst_pad_get_caps                        (GstPad * pad);
+GstCaps *              gst_pad_get_caps                        (GstPad * pad, GstCaps *filter);
 void                   gst_pad_fixate_caps                     (GstPad * pad, GstCaps *caps);
 gboolean               gst_pad_accept_caps                     (GstPad * pad, GstCaps *caps);
 gboolean               gst_pad_set_caps                        (GstPad * pad, GstCaps *caps);
 
-GstCaps *              gst_pad_peer_get_caps                   (GstPad * pad);
+GstCaps *              gst_pad_peer_get_caps                   (GstPad * pad, GstCaps *filter);
 gboolean               gst_pad_peer_accept_caps                (GstPad * pad, GstCaps *caps);
 
 /* capsnego for linked pads */
index 73522ba..38c0c48 100644 (file)
@@ -1140,7 +1140,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
           gboolean compatible;
 
           /* Now check if the two pads' caps are compatible */
-          temp = gst_pad_get_caps (pad);
+          temp = gst_pad_get_caps (pad, NULL);
           if (caps) {
             intersection = gst_caps_intersect (temp, caps);
             gst_caps_unref (temp);
@@ -1148,7 +1148,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
             intersection = temp;
           }
 
-          temp = gst_pad_get_caps (current);
+          temp = gst_pad_get_caps (current, NULL);
           compatible = gst_caps_can_intersect (temp, intersection);
           gst_caps_unref (temp);
           gst_caps_unref (intersection);
@@ -1198,7 +1198,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
   /* try to create a new one */
   /* requesting is a little crazy, we need a template. Let's create one */
   /* FIXME: why not gst_pad_get_pad_template (pad); */
-  templcaps = gst_pad_get_caps (pad);
+  templcaps = gst_pad_get_caps (pad, NULL);
 
   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
@@ -2691,16 +2691,15 @@ gst_buffer_join (GstBuffer * buf1, GstBuffer * buf2)
   return result;
 }
 
-
 static gboolean
-getcaps_fold_func (const GValue * vpad, GValue * ret, GstPad * orig)
+getcaps_fold_func (const GValue * vpad, GValue * ret, GstCaps * filter)
 {
   GstPad *pad = g_value_get_object (vpad);
   gboolean empty = FALSE;
   GstCaps *peercaps, *existing;
 
   existing = g_value_get_pointer (ret);
-  peercaps = gst_pad_peer_get_caps (pad);
+  peercaps = gst_pad_peer_get_caps (pad, filter);
   if (G_LIKELY (peercaps)) {
     GstCaps *intersection = gst_caps_intersect (existing, peercaps);
 
@@ -2716,6 +2715,7 @@ getcaps_fold_func (const GValue * vpad, GValue * ret, GstPad * orig)
 /**
  * gst_pad_proxy_getcaps:
  * @pad: a #GstPad to proxy.
+ * @filter: a #GstCaps filter.
  *
  * Calls gst_pad_get_allowed_caps() for every other pad belonging to the
  * same element as @pad, and returns the intersection of the results.
@@ -2729,7 +2729,7 @@ getcaps_fold_func (const GValue * vpad, GValue * ret, GstPad * orig)
  * Returns: (transfer full): the intersection of the other pads' allowed caps.
  */
 GstCaps *
-gst_pad_proxy_getcaps (GstPad * pad)
+gst_pad_proxy_getcaps (GstPad * pad, GstCaps * filter)
 {
   GstElement *element;
   GstCaps *caps, *intersected;
@@ -2760,7 +2760,7 @@ gst_pad_proxy_getcaps (GstPad * pad)
   while (1) {
     res =
         gst_iterator_fold (iter, (GstIteratorFoldFunction) getcaps_fold_func,
-        &ret, pad);
+        &ret, filter);
     switch (res) {
       case GST_ITERATOR_RESYNC:
         /* unref any value stored */
index dec9e98..ce0f8bc 100644 (file)
@@ -907,7 +907,7 @@ void                        gst_element_class_install_std_props (GstElementClass * klass,
 
 /* pad functions */
 void                   gst_pad_use_fixed_caps          (GstPad *pad);
-GstCaps*               gst_pad_proxy_getcaps           (GstPad * pad);
+GstCaps*               gst_pad_proxy_getcaps           (GstPad * pad, GstCaps * filter);
 gboolean               gst_pad_proxy_setcaps           (GstPad * pad, GstCaps * caps);
 
 GstElement*            gst_pad_get_parent_element      (GstPad *pad);