From 09d83e589ab24becbe9171407e8b5a865f7d898d Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Fri, 25 Feb 2011 08:50:12 -0300 Subject: [PATCH] gstcaps: new API : gst_caps_intersect_full 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 | 2 + gst/gstcaps.c | 120 +++++++++++++++++++++++++++++----- gst/gstcaps.h | 34 ++++++++++ win32/common/libgstreamer.def | 2 + 4 files changed, 143 insertions(+), 15 deletions(-) diff --git a/gst/gst.c b/gst/gst.c index cf27a6662d..adf22396be 100644 --- 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"); diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 0ac7a7e100..5d8912c4d3 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -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 diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 47d10326d6..398fa3fcbf 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -43,6 +43,37 @@ typedef enum { GST_CAPS_FLAGS_ANY = (1 << 0) } 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: * @@ -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, diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index a679ce5269..c6da075d50 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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