2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstcaps.c: Element capabilities subsystem
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 //#define GST_DEBUG_ENABLED
24 #include "gst_private.h"
29 #include "gstpropsprivate.h"
31 static GMemChunk *_gst_caps_chunk;
32 static GMutex *_gst_caps_chunk_lock;
35 _gst_caps_initialize (void)
37 _gst_caps_chunk = g_mem_chunk_new ("GstCaps",
38 sizeof (GstCaps), sizeof (GstCaps) * 256,
40 _gst_caps_chunk_lock = g_mutex_new ();
44 get_type_for_mime (const gchar *mime)
48 typeid = gst_type_find_by_mime (mime);
50 GstTypeFactory factory; // = g_new0 (GstTypeFactory, 1);
52 factory.mime = g_strdup (mime);
54 factory.typefindfunc = NULL;
56 typeid = gst_type_register (&factory);
63 * @name: the name of this capability
64 * @mime: the mime type to attach to the capability
65 * @props: the properties to add to this capability
67 * Create a new capability with the given mime typei and properties.
69 * Returns: a new capability
72 gst_caps_new (const gchar *name, const gchar *mime, GstProps *props)
76 g_return_val_if_fail (mime != NULL, NULL);
78 g_mutex_lock (_gst_caps_chunk_lock);
79 caps = g_mem_chunk_alloc (_gst_caps_chunk);
80 g_mutex_unlock (_gst_caps_chunk_lock);
82 caps->name = g_strdup (name);
83 caps->id = get_type_for_mime (mime);
84 caps->properties = props;
87 caps->lock = g_mutex_new ();
94 * @caps: the caps to destroy
96 * Frees the memory used by this caps structure and all
97 * the chained caps and properties.
100 gst_caps_destroy (GstCaps *caps)
104 g_return_if_fail (caps != NULL);
106 GST_CAPS_LOCK (caps);
110 GST_CAPS_UNLOCK (caps);
113 gst_caps_unref (next);
118 * @caps: the caps to unref
120 * Decrease the refcount of this caps structure,
121 * destroying it when the refcount is 0
123 * Returns: caps or NULL if the refcount reached 0
126 gst_caps_unref (GstCaps *caps)
131 g_return_val_if_fail (caps != NULL, NULL);
132 g_return_val_if_fail (caps->refcount > 0, NULL);
134 GST_CAPS_LOCK (caps);
136 zero = (caps->refcount == 0);
138 GST_CAPS_UNLOCK (caps);
141 *next = gst_caps_unref (*next);
144 gst_caps_destroy (caps);
152 * @caps: the caps to ref
154 * Increase the refcount of this caps structure
156 * Returns: the caps with the refcount incremented
159 gst_caps_ref (GstCaps *caps)
161 g_return_val_if_fail (caps != NULL, NULL);
163 GST_CAPS_LOCK (caps);
165 GST_CAPS_UNLOCK (caps);
172 * @caps: the caps to copy
176 * Returns: a copy of the GstCaps structure.
179 gst_caps_copy (GstCaps *caps)
181 GstCaps *new = caps;;
183 g_return_val_if_fail (caps != NULL, NULL);
185 GST_CAPS_LOCK (caps);
188 (gst_type_find_by_id (caps->id))->mime,
189 gst_props_copy (caps->properties));
190 GST_CAPS_UNLOCK (caps);
196 * gst_caps_copy_on_write:
197 * @caps: the caps to copy
199 * Copies the caps if the refcount is greater than 1
201 * Returns: a pointer to a GstCaps strcuture that can
202 * be safely written to
205 gst_caps_copy_on_write (GstCaps *caps)
210 g_return_val_if_fail (caps != NULL, NULL);
212 GST_CAPS_LOCK (caps);
213 needcopy = (caps->refcount > 1);
214 GST_CAPS_UNLOCK (caps);
217 new = gst_caps_copy (caps);
218 gst_caps_unref (caps);
226 * @caps: the caps to get the name from
228 * Get the name of a GstCaps structure.
230 * Returns: the name of the caps
233 gst_caps_get_name (GstCaps *caps)
235 g_return_val_if_fail (caps != NULL, NULL);
237 return (const gchar *)caps->name;
242 * @caps: the caps to set the name to
243 * @name: the name to set
245 * Set the name of a caps.
248 gst_caps_set_name (GstCaps *caps, const gchar *name)
250 g_return_if_fail (caps != NULL);
255 caps->name = g_strdup (name);
260 * @caps: the caps to get the mime type from
262 * Get the mime type of the caps as a string.
264 * Returns: the mime type of the caps
267 gst_caps_get_mime (GstCaps *caps)
271 g_return_val_if_fail (caps != NULL, NULL);
273 type = gst_type_find_by_id (caps->id);
278 return "unknown/unknown";
283 * @caps: the caps to set the mime type to
284 * @mime: the mime type to attach to the caps
286 * Set the mime type of the caps as a string.
289 gst_caps_set_mime (GstCaps *caps, const gchar *mime)
291 g_return_if_fail (caps != NULL);
292 g_return_if_fail (mime != NULL);
294 caps->id = get_type_for_mime (mime);
298 * gst_caps_get_type_id:
299 * @caps: the caps to get the type id from
301 * Get the type id of the caps.
303 * Returns: the type id of the caps
306 gst_caps_get_type_id (GstCaps *caps)
308 g_return_val_if_fail (caps != NULL, 0);
314 * gst_caps_set_type_id:
315 * @caps: the caps to set the type id to
316 * @type_id: the type id to set
318 * Set the type id of the caps.
321 gst_caps_set_type_id (GstCaps *caps, guint16 type_id)
323 g_return_if_fail (caps != NULL);
329 * gst_caps_set_props:
330 * @caps: the caps to attach the properties to
331 * @props: the properties to attach
333 * Set the properties to the given caps.
335 * Returns: the new caps structure
338 gst_caps_set_props (GstCaps *caps, GstProps *props)
340 g_return_val_if_fail (caps != NULL, caps);
341 g_return_val_if_fail (props != NULL, caps);
342 g_return_val_if_fail (caps->properties == NULL, caps);
344 caps->properties = props;
350 * gst_caps_get_props:
351 * @caps: the caps to get the properties from
353 * Get the properties of the given caps.
355 * Returns: the properties of the caps
358 gst_caps_get_props (GstCaps *caps)
360 g_return_val_if_fail (caps != NULL, NULL);
362 return caps->properties;
368 * @...: more capabilities
370 * chains the given capabilities
372 * Returns: the new capability
375 gst_caps_chain (GstCaps *caps, ...)
377 GstCaps *orig = caps;
380 va_start (var_args, caps);
385 toadd = va_arg (var_args, GstCaps*);
386 gst_caps_append (caps, toadd);
398 * @capstoadd: the capability to append
400 * Appends a capability to the existing capability.
402 * Returns: the new capability
405 gst_caps_append (GstCaps *caps, GstCaps *capstoadd)
407 GstCaps *orig = caps;
409 g_return_val_if_fail (caps != capstoadd, caps);
417 caps->next = capstoadd;
425 * @capstoadd: a capabilty to prepend
427 * prepend the capability to the list of capabilities
429 * Returns: the new capability
432 gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd)
434 GstCaps *orig = capstoadd;
436 g_return_val_if_fail (caps != capstoadd, caps);
438 if (capstoadd == NULL)
441 while (capstoadd->next) {
442 capstoadd = capstoadd->next;
444 capstoadd->next = caps;
450 * gst_caps_get_by_name:
452 * @name: the name of the capability to get
454 * Get the capability with the given name from this
455 * chain of capabilities.
457 * Returns: the first capability in the chain with the
461 gst_caps_get_by_name (GstCaps *caps, const gchar *name)
463 g_return_val_if_fail (caps != NULL, NULL);
464 g_return_val_if_fail (name != NULL, NULL);
467 if (!strcmp (caps->name, name))
476 gst_caps_check_compatibility_func (GstCaps *fromcaps, GstCaps *tocaps)
478 if (fromcaps->id != tocaps->id) {
479 GST_DEBUG (GST_CAT_CAPS,"mime types differ (%s to %s)\n",
480 gst_type_find_by_id (fromcaps->id)->mime,
481 gst_type_find_by_id (tocaps->id)->mime);
485 if (tocaps->properties) {
486 if (fromcaps->properties) {
487 return gst_props_check_compatibility (fromcaps->properties, tocaps->properties);
490 GST_DEBUG (GST_CAT_CAPS,"no source caps\n");
495 // assume it accepts everything
496 GST_DEBUG (GST_CAT_CAPS,"no caps\n");
502 * gst_caps_check_compatibility:
503 * @fromcaps: a capabilty
504 * @tocaps: a capabilty
506 * Checks whether two capabilities are compatible.
508 * Returns: TRUE if compatible, FALSE otherwise
511 gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
513 if (fromcaps == NULL) {
514 if (tocaps == NULL) {
515 GST_DEBUG (GST_CAT_CAPS,"no caps\n");
519 GST_DEBUG (GST_CAT_CAPS,"no source but destination caps\n");
524 if (tocaps == NULL) {
525 GST_DEBUG (GST_CAT_CAPS,"source caps and no destination caps\n");
531 GstCaps *destcaps = tocaps;
534 if (gst_caps_check_compatibility_func (fromcaps, destcaps))
537 destcaps = destcaps->next;
539 fromcaps = fromcaps->next;
545 * gst_caps_save_thyself:
546 * @caps: a capabilty to save
547 * @parent: the parent XML node pointer
549 * Save the capability into an XML representation.
551 * Returns: a new XML node pointer
554 gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
557 xmlNodePtr subsubtree;
560 subtree = xmlNewChild (parent, NULL, "capscomp", NULL);
562 xmlNewChild (subtree, NULL, "name", caps->name);
563 xmlNewChild (subtree, NULL, "type", gst_type_find_by_id (caps->id)->mime);
564 if (caps->properties) {
565 subsubtree = xmlNewChild (subtree, NULL, "properties", NULL);
567 gst_props_save_thyself (caps->properties, subsubtree);
577 * gst_caps_load_thyself:
578 * @parent: the parent XML node pointer
580 * Load a new caps from the XML representation.
582 * Returns: a new capability
585 gst_caps_load_thyself (xmlNodePtr parent)
587 GstCaps *result = NULL;
588 xmlNodePtr field = parent->xmlChildrenNode;
591 if (!strcmp (field->name, "capscomp")) {
592 xmlNodePtr subfield = field->xmlChildrenNode;
596 g_mutex_lock (_gst_caps_chunk_lock);
597 caps = g_mem_chunk_alloc0 (_gst_caps_chunk);
598 g_mutex_unlock (_gst_caps_chunk_lock);
601 caps->lock = g_mutex_new ();
605 if (!strcmp (subfield->name, "name")) {
606 caps->name = xmlNodeGetContent (subfield);
608 if (!strcmp (subfield->name, "type")) {
609 content = xmlNodeGetContent (subfield);
610 caps->id = get_type_for_mime (content);
613 else if (!strcmp (subfield->name, "properties")) {
614 caps->properties = gst_props_load_thyself (subfield);
617 subfield = subfield->next;
619 result = gst_caps_append (result, caps);