gstcaps: new API : gst_caps_intersect_full
authorEdward Hervey <bilboed@bilboed.com>
Fri, 25 Feb 2011 11:50:12 +0000 (08:50 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>
Thu, 24 Mar 2011 14:14:18 +0000 (11:14 -0300)
Just like gst_caps_intersect, but adds a new parameter 'mode'
that allows selecting the intersection algorithm to use.

Currently we have GST_CAPS_INTERSECT_MODE_ZIG_ZAG (default) and
GST_CAPS_INTERSECT_MODE_FIRST.

API: gst_caps_intersect_full
API: GstCapsIntersectMode
API: GST_CAPS_INTERSECT_MODE_ZIG_ZAG
API: GST_CAPS_INTERSECT_MODE_FIRST

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

gst/gst.c
gst/gstcaps.c
gst/gstcaps.h
win32/common/libgstreamer.def

index cf27a66..adf2239 100644 (file)
--- a/gst/gst.c
+++ b/gst/gst.c
@@ -747,6 +747,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   g_type_class_ref (gst_parse_flags_get_type ());
   g_type_class_ref (gst_search_mode_get_type ());
   g_type_class_ref (gst_progress_type_get_type ());
+  g_type_class_ref (gst_caps_intersect_mode_get_type ());
 
   gst_structure_get_type ();
   _gst_value_initialize ();
@@ -1112,6 +1113,7 @@ gst_deinit (void)
   g_type_class_unref (g_type_class_peek (gst_parse_error_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_param_spec_fraction_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_progress_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_caps_intersect_mode_get_type ()));
 
   gst_deinitialized = TRUE;
   GST_INFO ("deinitialized GStreamer");
index 0ac7a7e..5d8912c 100644 (file)
@@ -1416,18 +1416,8 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
   return FALSE;
 }
 
-/**
- * gst_caps_intersect:
- * @caps1: a #GstCaps to intersect
- * @caps2: a #GstCaps to intersect
- *
- * Creates a new #GstCaps that contains all the formats that are common
- * to both @caps1 and @caps2.
- *
- * Returns: the new #GstCaps
- */
-GstCaps *
-gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
+static GstCaps *
+gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
 {
   guint64 i;                    /* index can be up to 2 * G_MAX_UINT */
   guint j, k, len1, len2;
@@ -1437,9 +1427,6 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
   GstCaps *dest;
   GstStructure *istruct;
 
-  g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
-  g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
-
   /* caps are exactly the same pointers, just copy one caps */
   if (G_UNLIKELY (caps1 == caps2))
     return gst_caps_copy (caps1);
@@ -1500,6 +1487,109 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
   return dest;
 }
 
+/**
+ * gst_caps_intersect_first:
+ * @caps1: a #GstCaps to intersect
+ * @caps2: a #GstCaps to intersect
+ *
+ * Creates a new #GstCaps that contains all the formats that are common
+ * to both @caps1 and @caps2.
+ *
+ * Unlike @gst_caps_intersect, the returned caps will be ordered in a similar
+ * fashion as @caps1.
+ *
+ * Returns: the new #GstCaps
+ */
+static GstCaps *
+gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2)
+{
+  guint64 i;                    /* index can be up to 2 * G_MAX_UINT */
+  guint j, len1, len2;
+
+  GstStructure *struct1;
+  GstStructure *struct2;
+  GstCaps *dest;
+  GstStructure *istruct;
+
+  /* caps are exactly the same pointers, just copy one caps */
+  if (G_UNLIKELY (caps1 == caps2))
+    return gst_caps_copy (caps1);
+
+  /* empty caps on either side, return empty */
+  if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
+    return gst_caps_new_empty ();
+
+  /* one of the caps is any, just copy the other caps */
+  if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
+    return gst_caps_copy (caps2);
+  if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
+    return gst_caps_copy (caps1);
+
+  dest = gst_caps_new_empty ();
+
+  len1 = caps1->structs->len;
+  len2 = caps2->structs->len;
+  for (i = 0; i < len1; i++) {
+    struct1 = gst_caps_get_structure_unchecked (caps1, i);
+    for (j = 0; j < len2; j++) {
+      struct2 = gst_caps_get_structure_unchecked (caps2, j);
+      istruct = gst_caps_structure_intersect (struct1, struct2);
+      if (istruct)
+        gst_caps_append_structure (dest, istruct);
+    }
+  }
+
+  return dest;
+}
+
+/**
+ * gst_caps_intersect_full:
+ * @caps1: a #GstCaps to intersect
+ * @caps2: a #GstCaps to intersect
+ * @mode: The intersection algorithm/mode to use
+ *
+ * Creates a new #GstCaps that contains all the formats that are common
+ * to both @caps1 and @caps2, the order is defined by the #GstCapsIntersectMode
+ * used.
+ *
+ * Returns: the new #GstCaps
+ * Since: 0.10.33
+ */
+GstCaps *
+gst_caps_intersect_full (const GstCaps * caps1, const GstCaps * caps2,
+    GstCapsIntersectMode mode)
+{
+  g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
+  g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
+
+  switch (mode) {
+    case GST_CAPS_INTERSECT_FIRST:
+      return gst_caps_intersect_first (caps1, caps2);
+    default:
+      g_warning ("Unknown caps intersect mode: %d", mode);
+      /* fallthrough */
+    case GST_CAPS_INTERSECT_ZIG_ZAG:
+      return gst_caps_intersect_zig_zag (caps1, caps2);
+  }
+}
+
+/**
+ * gst_caps_intersect:
+ * @caps1: a #GstCaps to intersect
+ * @caps2: a #GstCaps to intersect
+ *
+ * Creates a new #GstCaps that contains all the formats that are common
+ * to both @caps1 and @caps2. Defaults to %GST_CAPS_INTERSECT_ZIG_ZAG mode.
+ *
+ * Returns: the new #GstCaps
+ */
+GstCaps *
+gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
+{
+  return gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG);
+}
+
+
 /* subtract operation */
 
 typedef struct
index 47d1032..398fa3f 100644 (file)
@@ -44,6 +44,37 @@ typedef enum {
 } GstCapsFlags;
 
 /**
+ * GstCapsIntersectMode:
+ * @GST_CAPS_INTERSECT_ZIG_ZAG  : Zig-zags over both caps.
+ * @GST_CAPS_INTERSECT_FIRST    : Keeps the first caps order.
+ *
+ * Modes of caps intersection
+ * 
+ * #GST_CAPS_INTERSECT_ZIG_ZAG tries to preserve overall order of both caps
+ * by iterating on the caps' structures as the following matrix shows:
+ *          caps1
+ *       +-------------
+ *       | 1  2  4  7
+ * caps2 | 3  5  8 10
+ *       | 6  9 11 12
+ *
+ * Used when there is no explicit precedence of one caps over the other. e.g.
+ * tee's sink pad getcaps function, it will probe its src pad peers' for their
+ * caps and intersect them with this mode.
+ *
+ * #GST_CAPS_INTERSECT_FIRST is useful when an element wants to preserve
+ * another element's caps priority order when intersecting with its own caps.
+ * Example: If caps1 is [A, B, C] and caps2 is [E, B, D, A], the result
+ * would be [A, B], maintaining the first caps priority on the intersection.
+ *
+ * Since: 0.10.33
+ */
+typedef enum {
+  GST_CAPS_INTERSECT_ZIG_ZAG            =  0,
+  GST_CAPS_INTERSECT_FIRST              =  1
+} GstCapsIntersectMode;
+
+/**
  * GST_CAPS_ANY:
  *
  * Means that the element/pad can output 'anything'. Useful for elements
@@ -237,6 +268,9 @@ gboolean          gst_caps_can_intersect           (const GstCaps * caps1,
 /* operations */
 GstCaps *         gst_caps_intersect               (const GstCaps *caps1,
                                                    const GstCaps *caps2);
+GstCaps *         gst_caps_intersect_full          (const GstCaps *caps1,
+                                                   const GstCaps *caps2,
+                                                    GstCapsIntersectMode mode);
 GstCaps *         gst_caps_subtract               (const GstCaps *minuend,
                                                    const GstCaps *subtrahend);
 GstCaps *         gst_caps_union                   (const GstCaps *caps1,
index a679ce5..c6da075 100644 (file)
@@ -162,6 +162,8 @@ EXPORTS
        gst_caps_get_structure
        gst_caps_get_type
        gst_caps_intersect
+       gst_caps_intersect_full
+       gst_caps_intersect_mode_get_type
        gst_caps_is_always_compatible
        gst_caps_is_any
        gst_caps_is_empty