caps->type = GST_TYPE_CAPS;
caps->refcount = 1;
- caps->flags = 0;
+ caps->flags = GST_CAPS_FLAGS_NONE;
caps->structs = g_ptr_array_new ();
/* the 32 has been determined by logging caps sizes in _gst_caps_free
* but g_ptr_array uses 16 anyway if it expands once, so this does not help
*/
#ifdef DEBUG_REFCOUNT
- GST_CAT_LOG (GST_CAT_CAPS, "created caps %p", caps);
+ GST_CAT_TRACE (GST_CAT_CAPS, "created caps %p", caps);
#endif
return caps;
#endif
#ifdef DEBUG_REFCOUNT
- GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps);
+ GST_CAT_TRACE (GST_CAT_CAPS, "freeing caps %p", caps);
#endif
g_slice_free (GstCaps, caps);
}
* gst_caps_unref:
* @caps: (transfer full): the #GstCaps to unref
*
- * Unref a #GstCaps and and free all its structures and the
+ * Unref a #GstCaps and free all its structures and the
* structures' values when the refcount reaches 0.
*/
void
if (G_UNLIKELY (string == NULL))
goto no_string;
- GST_CAT_LOG (GST_CAT_CAPS, "creating %p", static_caps);
+ GST_CAT_TRACE (GST_CAT_CAPS, "creating %p", static_caps);
/* we construct the caps on the stack, then copy over the struct into our
* real caps, refcount last. We do this because we must leave the refcount
* of the result caps to 0 so that other threads don't run away with the
* caps while we are constructing it. */
temp.type = GST_TYPE_CAPS;
- temp.flags = 0;
+ temp.flags = GST_CAPS_FLAGS_NONE;
temp.structs = g_ptr_array_new ();
/* initialize the caps to a refcount of 1 so the caps can be writable for
/* and bump the refcount so other threads can now read */
g_atomic_int_set (&caps->refcount, 1);
- GST_CAT_LOG (GST_CAT_CAPS, "created %p", static_caps);
+ GST_CAT_TRACE (GST_CAT_CAPS, "created %p", static_caps);
done:
G_UNLOCK (static_caps_lock);
}
return gst_caps_remove_and_get_structure (caps, index);
}
-static gboolean
-gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2,
- gpointer data)
-{
- GstStructure *struct1 = (GstStructure *) data;
- const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
-
- if (G_UNLIKELY (val1 == NULL))
- return FALSE;
- if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
- gpointer user_data)
-{
- GstStructure *subtract_from = user_data;
- GValue subtraction = { 0, };
- const GValue *other;
-
- if (!(other = gst_structure_id_get_value (subtract_from, field_id)))
- /* field is missing in one set */
- return FALSE;
-
- /* equal values are subset */
- if (gst_value_compare (other, value) == GST_VALUE_EQUAL)
- return TRUE;
-
- /*
- * 1 - [1,2] = empty
- * -> !subset
- *
- * [1,2] - 1 = 2
- * -> 1 - [1,2] = empty
- * -> subset
- *
- * [1,3] - [1,2] = 3
- * -> [1,2] - [1,3] = empty
- * -> subset
- *
- * {1,2} - {1,3} = 2
- * -> {1,3} - {1,2} = 3
- * -> !subset
- *
- * First caps subtraction needs to return a non-empty set, second
- * subtractions needs to give en empty set.
- */
- if (gst_value_subtract (&subtraction, other, value)) {
- g_value_unset (&subtraction);
- /* !empty result, swapping must be empty */
- if (!gst_value_subtract (&subtraction, value, other))
- return TRUE;
-
- g_value_unset (&subtraction);
- }
- return FALSE;
-}
-
-static gboolean
-gst_caps_structure_is_subset (const GstStructure * minuend,
- const GstStructure * subtrahend)
-{
- if ((minuend->name != subtrahend->name) ||
- (gst_structure_n_fields (minuend) !=
- gst_structure_n_fields (subtrahend))) {
- return FALSE;
- }
-
- return gst_structure_foreach ((GstStructure *) subtrahend,
- gst_caps_structure_is_subset_field, (gpointer) minuend);
-}
-
/**
* gst_caps_append:
* @caps1: the #GstCaps that will be appended to
g_return_if_fail (GST_IS_CAPS (caps1));
g_return_if_fail (GST_IS_CAPS (caps2));
g_return_if_fail (IS_WRITABLE (caps1));
- g_return_if_fail (IS_WRITABLE (caps2));
+
+ caps2 = gst_caps_make_writable (caps2);
#ifdef USE_POISONING
CAPS_POISON (caps2);
g_return_if_fail (GST_IS_CAPS (caps1));
g_return_if_fail (GST_IS_CAPS (caps2));
g_return_if_fail (IS_WRITABLE (caps1));
- g_return_if_fail (IS_WRITABLE (caps2));
+
+ caps2 = gst_caps_make_writable (caps2);
#ifdef USE_POISONING
CAPS_POISON (caps2);
/**
* gst_caps_merge_structure:
- * @caps: the #GstCaps that will the the new structure
+ * @caps: the #GstCaps that will the new structure
* @structure: (transfer full): the #GstStructure to merge
*
* Appends @structure to @caps if its not already expressed by @caps. The
for (i = caps->structs->len - 1; i >= 0; i--) {
structure1 = gst_caps_get_structure_unchecked (caps, i);
/* if structure is a subset of structure1, then skip it */
- if (gst_caps_structure_is_subset (structure1, structure)) {
+ if (gst_structure_is_subset (structure, structure1)) {
unique = FALSE;
break;
}
g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
type = GST_TYPE_DATE;
}
-#if GLIB_CHECK_VERSION(2,23,3)
G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err);
-#else
- g_value_init (&value, type);
- G_VALUE_COLLECT (&value, varargs, 0, &err);
-#endif
if (G_UNLIKELY (err)) {
g_critical ("%s", err);
return;
struct1 = gst_caps_get_structure_unchecked (caps1, 0);
struct2 = gst_caps_get_structure_unchecked (caps2, 0);
- if (struct1->name != struct2->name) {
- return FALSE;
- }
- if (struct1->fields->len != struct2->fields->len) {
- return FALSE;
- }
-
- return gst_structure_foreach (struct1, gst_structure_is_equal_foreach,
- struct2);
+ return gst_structure_is_equal (struct1, struct2);
}
/**
gboolean
gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
{
- GstCaps *caps;
- gboolean ret;
+ GstStructure *s1, *s2;
+ gboolean ret = TRUE;
+ gint i, j;
g_return_val_if_fail (subset != NULL, FALSE);
g_return_val_if_fail (superset != NULL, FALSE);
if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset))
return FALSE;
- caps = gst_caps_subtract (subset, superset);
- ret = CAPS_IS_EMPTY_SIMPLE (caps);
- gst_caps_unref (caps);
+ for (i = subset->structs->len - 1; i >= 0; i--) {
+ for (j = superset->structs->len - 1; j >= 0; j--) {
+ s1 = gst_caps_get_structure_unchecked (subset, i);
+ s2 = gst_caps_get_structure_unchecked (superset, j);
+ if (gst_structure_is_subset (s1, s2)) {
+ /* If we found a superset, continue with the next
+ * subset structure */
+ break;
+ }
+ }
+ /* If we found no superset for this subset structure
+ * we return FALSE immediately */
+ if (j == -1) {
+ ret = FALSE;
+ break;
+ }
+ }
+
return ret;
}
/**
+ * gst_caps_is_subset_structure:
+ * @caps: a #GstCaps
+ * @structure: a potential #GstStructure subset of @caps
+ *
+ * Checks if @structure is a subset of @caps. See gst_caps_is_subset()
+ * for more information.
+ *
+ * Returns: %TRUE if @structure is a subset of @caps
+ *
+ * Since: 0.10.36
+ */
+gboolean
+gst_caps_is_subset_structure (const GstCaps * caps,
+ const GstStructure * structure)
+{
+ GstStructure *s;
+ gint i;
+
+ g_return_val_if_fail (caps != NULL, FALSE);
+ g_return_val_if_fail (structure != NULL, FALSE);
+
+ if (CAPS_IS_ANY (caps))
+ return TRUE;
+ if (CAPS_IS_EMPTY (caps))
+ return FALSE;
+
+ for (i = caps->structs->len - 1; i >= 0; i--) {
+ s = gst_caps_get_structure_unchecked (caps, i);
+ if (gst_structure_is_subset (structure, s)) {
+ /* If we found a superset return TRUE */
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
* gst_caps_is_equal:
* @caps1: a #GstCaps
* @caps2: another #GstCaps
return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1);
}
-/* intersect operation */
-
-typedef struct
-{
- GstStructure *dest;
- const GstStructure *intersect;
-}
-IntersectData;
-
-static gboolean
-gst_caps_structure_intersect_field1 (GQuark id, const GValue * val1,
- gpointer data)
-{
- IntersectData *idata = (IntersectData *) data;
- const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
- if (G_UNLIKELY (val2 == NULL)) {
- gst_structure_id_set_value (idata->dest, id, val1);
- } else {
- GValue dest_value = { 0 };
- if (gst_value_intersect (&dest_value, val1, val2)) {
- gst_structure_id_set_value (idata->dest, id, &dest_value);
- g_value_unset (&dest_value);
- } else {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static gboolean
-gst_caps_structure_intersect_field2 (GQuark id, const GValue * val1,
- gpointer data)
-{
- IntersectData *idata = (IntersectData *) data;
- const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
- if (G_UNLIKELY (val2 == NULL)) {
- gst_structure_id_set_value (idata->dest, id, val1);
- }
- return TRUE;
-}
-
-static GstStructure *
-gst_caps_structure_intersect (const GstStructure * struct1,
- const GstStructure * struct2)
+/**
+ * gst_caps_is_strictly_equal:
+ * @caps1: a #GstCaps
+ * @caps2: another #GstCaps
+ *
+ * Checks if the given caps are exactly the same set of caps.
+ *
+ * This function deals correctly with passing NULL for any of the caps.
+ *
+ * Returns: TRUE if both caps are strictly equal.
+ *
+ * Since: 0.10.36
+ */
+gboolean
+gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
{
- IntersectData data;
-
- g_assert (struct1 != NULL);
- g_assert (struct2 != NULL);
-
- if (G_UNLIKELY (struct1->name != struct2->name))
- return NULL;
-
- /* copy fields from struct1 which we have not in struct2 to target
- * intersect if we have the field in both */
- data.dest = gst_structure_id_empty_new (struct1->name);
- data.intersect = struct2;
- if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
- gst_caps_structure_intersect_field1, &data)))
- goto error;
-
- /* copy fields from struct2 which we have not in struct1 to target */
- data.intersect = struct1;
- if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2,
- gst_caps_structure_intersect_field2, &data)))
- goto error;
+ int i;
+ /* FIXME 0.11: NULL pointers are no valid Caps but indicate an error
+ * So there should be an assertion that caps1 and caps2 != NULL */
- return data.dest;
+ /* NULL <-> NULL is allowed here */
+ if (G_UNLIKELY (caps1 == caps2))
+ return TRUE;
-error:
- gst_structure_free (data.dest);
- return NULL;
-}
+ /* one of them NULL => they are different (can't be both NULL because
+ * we checked that above) */
+ if (G_UNLIKELY (caps1 == NULL || caps2 == NULL))
+ return FALSE;
-static gboolean
-gst_caps_structure_can_intersect_field (GQuark id, const GValue * val1,
- gpointer data)
-{
- GstStructure *other = (GstStructure *) data;
- const GValue *val2 = gst_structure_id_get_value (other, id);
+ if (caps1->structs->len != caps2->structs->len)
+ return FALSE;
- if (G_LIKELY (val2)) {
- if (!gst_value_can_intersect (val1, val2)) {
+ for (i = 0; i < caps1->structs->len; i++) {
+ if (!gst_structure_is_equal (gst_caps_get_structure_unchecked (caps1, i),
+ gst_caps_get_structure_unchecked (caps2, i)))
return FALSE;
- } else {
- gint eq = gst_value_compare (val1, val2);
-
- if (eq == GST_VALUE_UNORDERED) {
- /* we need to try interseting */
- GValue dest_value = { 0 };
- if (gst_value_intersect (&dest_value, val1, val2)) {
- g_value_unset (&dest_value);
- } else {
- return FALSE;
- }
- } else if (eq != GST_VALUE_EQUAL) {
- return FALSE;
- }
- }
}
- return TRUE;
-}
-
-static gboolean
-gst_caps_structure_can_intersect (const GstStructure * struct1,
- const GstStructure * struct2)
-{
- g_assert (struct1 != NULL);
- g_assert (struct2 != NULL);
-
- if (G_UNLIKELY (struct1->name != struct2->name))
- return FALSE;
-
- /* tries to intersect if we have the field in both */
- if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
- gst_caps_structure_can_intersect_field, (gpointer) struct2)))
- return FALSE;
return TRUE;
}
+/* intersect operation */
+
/**
* gst_caps_can_intersect:
* @caps1: a #GstCaps to intersect
j = MIN (i, len1 - 1);
/* subset index stays 0 until i reaches superset->structs->len, then it
* counts up from 1 to subset->structs->len - 1 */
- k = MAX (0, i - j);
+ k = (i > j) ? (i - j) : 0; /* MAX (0, i - j) */
/* now run the diagonal line, end condition is the left or bottom
* border */
struct1 = gst_caps_get_structure_unchecked (caps1, j);
struct2 = gst_caps_get_structure_unchecked (caps2, k);
- if (gst_caps_structure_can_intersect (struct1, struct2)) {
+ if (gst_structure_can_intersect (struct1, struct2)) {
return TRUE;
}
/* move down left */
j = MIN (i, len1 - 1);
/* caps2 index stays 0 until i reaches caps1->structs->len, then it counts
* up from 1 to caps2->structs->len - 1 */
- k = MAX (0, i - j);
+ k = (i > j) ? (i - j) : 0; /* MAX (0, i - j) */
/* now run the diagonal line, end condition is the left or bottom
* border */
struct1 = gst_caps_get_structure_unchecked (caps1, j);
struct2 = gst_caps_get_structure_unchecked (caps2, k);
- istruct = gst_caps_structure_intersect (struct1, struct2);
+ istruct = gst_structure_intersect (struct1, struct2);
- gst_caps_append_structure (dest, istruct);
+ gst_caps_merge_structure (dest, istruct);
/* move down left */
k++;
if (G_UNLIKELY (j == 0))
static GstCaps *
gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2)
{
- guint64 i; /* index can be up to 2 * G_MAX_UINT */
+ guint i;
guint j, len1, len2;
GstStructure *struct1;
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);
+ istruct = gst_structure_intersect (struct1, struct2);
if (istruct)
- gst_caps_append_structure (dest, istruct);
+ gst_caps_merge_structure (dest, istruct);
}
}
/**
* gst_caps_subtract:
- * @minuend: #GstCaps to substract from
- * @subtrahend: #GstCaps to substract
+ * @minuend: #GstCaps to subtract from
+ * @subtrahend: #GstCaps to subtract
*
* Subtracts the @subtrahend from the @minuend.
* <note>This function does not work reliably if optional properties for caps
g_return_if_fail (G_VALUE_HOLDS (dest_value, G_TYPE_STRING)
|| G_VALUE_HOLDS (dest_value, G_TYPE_POINTER));
- dest_value->data[0].v_pointer =
- gst_caps_to_string (src_value->data[0].v_pointer);
+ g_value_take_string (dest_value,
+ gst_caps_to_string (gst_value_get_caps (src_value)));
}
static GstCaps *