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
This commit is contained in:
Edward Hervey 2011-02-25 08:50:12 -03:00 committed by Thiago Santos
parent f9558b163f
commit 09d83e589a
4 changed files with 143 additions and 15 deletions

View file

@ -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_parse_flags_get_type ());
g_type_class_ref (gst_search_mode_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_progress_type_get_type ());
g_type_class_ref (gst_caps_intersect_mode_get_type ());
gst_structure_get_type (); gst_structure_get_type ();
_gst_value_initialize (); _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_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_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_progress_type_get_type ()));
g_type_class_unref (g_type_class_peek (gst_caps_intersect_mode_get_type ()));
gst_deinitialized = TRUE; gst_deinitialized = TRUE;
GST_INFO ("deinitialized GStreamer"); GST_INFO ("deinitialized GStreamer");

View file

@ -1416,18 +1416,8 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
return FALSE; return FALSE;
} }
/** static GstCaps *
* gst_caps_intersect: gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
* @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)
{ {
guint64 i; /* index can be up to 2 * G_MAX_UINT */ guint64 i; /* index can be up to 2 * G_MAX_UINT */
guint j, k, len1, len2; guint j, k, len1, len2;
@ -1437,9 +1427,6 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
GstCaps *dest; GstCaps *dest;
GstStructure *istruct; 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 */ /* caps are exactly the same pointers, just copy one caps */
if (G_UNLIKELY (caps1 == caps2)) if (G_UNLIKELY (caps1 == caps2))
return gst_caps_copy (caps1); return gst_caps_copy (caps1);
@ -1500,6 +1487,109 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
return dest; 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 */ /* subtract operation */
typedef struct typedef struct

View file

@ -43,6 +43,37 @@ typedef enum {
GST_CAPS_FLAGS_ANY = (1 << 0) GST_CAPS_FLAGS_ANY = (1 << 0)
} GstCapsFlags; } 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: * GST_CAPS_ANY:
* *
@ -237,6 +268,9 @@ gboolean gst_caps_can_intersect (const GstCaps * caps1,
/* operations */ /* operations */
GstCaps * gst_caps_intersect (const GstCaps *caps1, GstCaps * gst_caps_intersect (const GstCaps *caps1,
const GstCaps *caps2); const GstCaps *caps2);
GstCaps * gst_caps_intersect_full (const GstCaps *caps1,
const GstCaps *caps2,
GstCapsIntersectMode mode);
GstCaps * gst_caps_subtract (const GstCaps *minuend, GstCaps * gst_caps_subtract (const GstCaps *minuend,
const GstCaps *subtrahend); const GstCaps *subtrahend);
GstCaps * gst_caps_union (const GstCaps *caps1, GstCaps * gst_caps_union (const GstCaps *caps1,

View file

@ -162,6 +162,8 @@ EXPORTS
gst_caps_get_structure gst_caps_get_structure
gst_caps_get_type gst_caps_get_type
gst_caps_intersect gst_caps_intersect
gst_caps_intersect_full
gst_caps_intersect_mode_get_type
gst_caps_is_always_compatible gst_caps_is_always_compatible
gst_caps_is_any gst_caps_is_any
gst_caps_is_empty gst_caps_is_empty