* <title>Creating caps</title>
* <programlisting>
* GstCaps *caps;
- * caps = gst_caps_new_simple ("video/x-raw-yuv",
- * "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
+ * caps = gst_caps_new_simple ("video/x-raw",
+ * "format", G_TYPE_STRING, "I420",
* "framerate", GST_TYPE_FRACTION, 25, 1,
* "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
* "width", G_TYPE_INT, 320,
#define DEBUG_REFCOUNT
+typedef struct _GstCapsImpl
+{
+ GstCaps caps;
+
+ GPtrArray *array;
+} GstCapsImpl;
-#define GST_CAPS_ARRAY(c) ((GPtrArray *)((c)->priv))
+#define GST_CAPS_ARRAY(c) (((GstCapsImpl *)(c))->array)
#define GST_CAPS_LEN(c) (GST_CAPS_ARRAY(c)->len)
/* same as gst_caps_is_any () */
#define CAPS_IS_ANY(caps) \
- (GST_CAPS_FLAGS(caps) & GST_CAPS_FLAGS_ANY)
+ (GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY)
/* same as gst_caps_is_empty () */
#define CAPS_IS_EMPTY(caps) \
const gchar * string);
GType _gst_caps_type = 0;
+GstCaps *_gst_caps_any;
+GstCaps *_gst_caps_none;
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstCaps, gst_caps);
void
-_gst_caps_initialize (void)
+_priv_gst_caps_initialize (void)
{
- _gst_caps_type = gst_mini_object_register ("GstCaps");
+ _gst_caps_type = gst_caps_get_type ();
+
+ _gst_caps_any = gst_caps_new_any ();
+ _gst_caps_none = gst_caps_new_empty ();
g_value_register_transform_func (_gst_caps_type,
G_TYPE_STRING, gst_caps_transform_to_string);
* in practise
* GST_CAPS_ARRAY (caps) = g_ptr_array_sized_new (32);
*/
- caps->priv = g_ptr_array_new ();
+ GST_CAPS_ARRAY (caps) = g_ptr_array_new ();
}
/**
{
GstCaps *caps;
- caps = g_slice_new (GstCaps);
+ caps = (GstCaps *) g_slice_new (GstCapsImpl);
- gst_caps_init (caps, sizeof (GstCaps));
+ gst_caps_init (caps, sizeof (GstCapsImpl));
#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;
{
GstCaps *caps = gst_caps_new_empty ();
- GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAGS_ANY);
+ GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAG_ANY);
+
+ return caps;
+}
+
+/**
+ * gst_caps_new_empty_simple:
+ * @media_type: the media type of the structure
+ *
+ * Creates a new #GstCaps that contains one #GstStructure with name
+ * @media_type.
+ * Caller is responsible for unreffing the returned caps.
+ *
+ * Returns: (transfer full): the new #GstCaps
+ */
+GstCaps *
+gst_caps_new_empty_simple (const char *media_type)
+{
+ GstCaps *caps;
+ GstStructure *structure;
+
+ caps = gst_caps_new_empty ();
+ structure = gst_structure_new_empty (media_type);
+ if (structure)
+ gst_caps_append_structure_unchecked (caps, structure);
return caps;
}
return caps;
}
-GType
-gst_static_caps_get_type (void)
-{
- static GType staticcaps_type = 0;
-
- if (G_UNLIKELY (staticcaps_type == 0)) {
- staticcaps_type = g_pointer_type_register_static ("GstStaticCaps");
- }
- return staticcaps_type;
-}
-
+G_DEFINE_POINTER_TYPE (GstStaticCaps, gst_static_caps);
/**
* gst_static_caps_get:
GstCaps *
gst_static_caps_get (GstStaticCaps * static_caps)
{
- GstCaps *caps;
+ GstCaps **caps;
g_return_val_if_fail (static_caps != NULL, NULL);
- caps = (GstCaps *) static_caps;
+ caps = &static_caps->caps;
/* refcount is 0 when we need to convert */
- if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) == 0)) {
+ if (G_UNLIKELY (*caps == NULL)) {
const char *string;
- GstCaps temp;
G_LOCK (static_caps_lock);
/* check if other thread already updated */
- if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) > 0))
+ if (G_UNLIKELY (*caps != NULL))
goto done;
string = static_caps->string;
if (G_UNLIKELY (string == NULL))
goto no_string;
- GST_CAT_LOG (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. */
- gst_caps_init (&temp, sizeof (GstCaps));
+ *caps = gst_caps_from_string (string);
/* convert to string */
- if (G_UNLIKELY (!gst_caps_from_string_inplace (&temp, string)))
+ if (G_UNLIKELY (*caps == NULL))
g_critical ("Could not convert static caps \"%s\"", string);
- gst_caps_init (caps, sizeof (GstCaps));
- /* now copy stuff over to the real caps. */
- GST_CAPS_FLAGS (caps) = GST_CAPS_FLAGS (&temp);
- caps->priv = GST_CAPS_ARRAY (&temp);
-
- GST_CAT_LOG (GST_CAT_CAPS, "created %p", static_caps);
+ GST_CAT_TRACE (GST_CAT_CAPS, "created %p from string %s", static_caps,
+ string);
done:
G_UNLOCK (static_caps_lock);
}
/* ref the caps, makes it not writable */
- gst_caps_ref (caps);
+ if (G_LIKELY (*caps != NULL))
+ gst_caps_ref (*caps);
- return caps;
+ return *caps;
/* ERRORS */
no_string:
/**
* gst_static_caps_cleanup:
- * @static_caps: the #GstStaticCaps to convert
+ * @static_caps: the #GstStaticCaps to clean
*
- * Clean up the caps contained in @static_caps when the refcount is 0.
+ * Clean up the cached caps contained in @static_caps.
*/
void
gst_static_caps_cleanup (GstStaticCaps * static_caps)
{
- GstCaps *caps = (GstCaps *) static_caps;
-
- /* FIXME: this is not threadsafe */
- if (GST_CAPS_REFCOUNT_VALUE (caps) == 1) {
- GstStructure *structure;
- guint i, clen;
-
- clen = GST_CAPS_LEN (caps);
-
- for (i = 0; i < clen; i++) {
- structure = (GstStructure *) gst_caps_get_structure (caps, i);
- gst_structure_set_parent_refcount (structure, NULL);
- gst_structure_free (structure);
- }
- g_ptr_array_free (GST_CAPS_ARRAY (caps), TRUE);
- GST_CAPS_REFCOUNT (caps) = 0;
- }
+ G_LOCK (static_caps_lock);
+ gst_caps_replace (&static_caps->caps, NULL);
+ G_UNLOCK (static_caps_lock);
}
/* manipulation */
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);
if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) {
/* FIXME: this leaks */
- GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAGS_ANY;
+ GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY;
for (i = GST_CAPS_LEN (caps2) - 1; i >= 0; i--) {
structure = gst_caps_remove_and_get_structure (caps2, i);
gst_structure_free (structure);
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);
if (G_UNLIKELY (CAPS_IS_ANY (caps1))) {
for (i = GST_CAPS_LEN (caps2) - 1; i >= 0; i--) {
gst_structure_free (structure);
}
} else if (G_UNLIKELY (CAPS_IS_ANY (caps2))) {
- GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAGS_ANY;
+ GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY;
for (i = GST_CAPS_LEN (caps1) - 1; i >= 0; i--) {
structure = gst_caps_remove_and_get_structure (caps1, i);
gst_structure_free (structure);
/**
* 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
type = va_arg (varargs, GType);
- if (G_UNLIKELY (type == G_TYPE_DATE)) {
- g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
- type = GST_TYPE_DATE;
- }
G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err);
if (G_UNLIKELY (err)) {
g_critical ("%s", err);
*
* Returns: %TRUE if @structure is a subset of @caps
*
- * Since: 0.10.35
+ * Since: 0.10.36
*/
gboolean
gst_caps_is_subset_structure (const GstCaps * caps,
return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1);
}
+/**
+ * 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)
+{
+ 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 */
+
+ /* NULL <-> NULL is allowed here */
+ if (G_UNLIKELY (caps1 == caps2))
+ return TRUE;
+
+ /* 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;
+
+ if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
+ return FALSE;
+
+ for (i = 0; i < GST_CAPS_LEN (caps1); i++) {
+ if (!gst_structure_is_equal (gst_caps_get_structure_unchecked (caps1, i),
+ gst_caps_get_structure_unchecked (caps2, i)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* intersect operation */
/**
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 */
j = MIN (i, len1 - 1);
/* caps2 index stays 0 until i reaches GST_CAPS_LEN (caps1), then it counts
* up from 1 to GST_CAPS_LEN (caps2) - 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 */
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;
/**
* 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
if (struct1->name != struct2->name)
return NULL;
- dest = gst_structure_id_empty_new (struct1->name);
+ dest = gst_structure_new_id_empty (struct1->name);
for (i = 0; i < struct1->fields->len; i++) {
GValue dest_value = { 0 };
return TRUE;
}
+/**
+ * gst_caps_fixate:
+ * @caps: a #GstCaps to fixate
+ *
+ * Modifies the given @caps inplace into a representation with only fixed
+ * values. First the caps will be truncated and then the first structure will be
+ * fixated with gst_structure_fixate(). @caps should be writable.
+ */
+void
+gst_caps_fixate (GstCaps * caps)
+{
+ GstStructure *s;
+
+ g_return_if_fail (GST_IS_CAPS (caps));
+ g_return_if_fail (IS_WRITABLE (caps));
+
+ /* default fixation */
+ gst_caps_truncate (caps);
+ s = gst_caps_get_structure (caps, 0);
+ gst_structure_fixate (s);
+}
+
/* utility */
/**
gchar *s;
if (strcmp ("ANY", string) == 0) {
- GST_CAPS_FLAGS (caps) = GST_CAPS_FLAGS_ANY;
+ GST_CAPS_FLAGS (caps) = GST_CAPS_FLAG_ANY;
return TRUE;
}
if (strcmp ("EMPTY", string) == 0) {
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)));
}