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
124 gst_caps_unref (GstCaps *caps)
129 g_return_if_fail (caps != NULL);
131 GST_CAPS_LOCK (caps);
133 zero = (caps->refcount == 0);
135 GST_CAPS_UNLOCK (caps);
138 gst_caps_unref (next);
141 gst_caps_destroy (caps);
146 * @caps: the caps to ref
148 * Increase the refcount of this caps structure
151 gst_caps_ref (GstCaps *caps)
153 g_return_if_fail (caps != NULL);
155 GST_CAPS_LOCK (caps);
157 GST_CAPS_UNLOCK (caps);
162 * @caps: the caps to copy
166 * Returns: a copy of the GstCaps structure.
169 gst_caps_copy (GstCaps *caps)
171 GstCaps *new = caps;;
173 g_return_val_if_fail (caps != NULL, NULL);
175 GST_CAPS_LOCK (caps);
178 (gst_type_find_by_id (caps->id))->mime,
179 gst_props_copy (caps->properties));
180 GST_CAPS_UNLOCK (caps);
186 * gst_caps_copy_on_write:
187 * @caps: the caps to copy
189 * Copies the caps if the refcount is greater than 1
191 * Returns: a pointer to a GstCaps strcuture that can
192 * be safely written to
195 gst_caps_copy_on_write (GstCaps *caps)
200 g_return_val_if_fail (caps != NULL, NULL);
202 GST_CAPS_LOCK (caps);
203 needcopy = (caps->refcount > 1);
204 GST_CAPS_UNLOCK (caps);
207 new = gst_caps_copy (caps);
208 gst_caps_unref (caps);
216 * @caps: the caps to get the name from
218 * Get the name of a GstCaps structure.
220 * Returns: the name of the caps
223 gst_caps_get_name (GstCaps *caps)
225 g_return_val_if_fail (caps != NULL, NULL);
227 return (const gchar *)caps->name;
232 * @caps: the caps to set the name to
233 * @name: the name to set
235 * Set the name of a caps.
238 gst_caps_set_name (GstCaps *caps, const gchar *name)
240 g_return_if_fail (caps != NULL);
245 caps->name = g_strdup (name);
250 * @caps: the caps to get the mime type from
252 * Get the mime type of the caps as a string.
254 * Returns: the mime type of the caps
257 gst_caps_get_mime (GstCaps *caps)
261 g_return_val_if_fail (caps != NULL, NULL);
263 type = gst_type_find_by_id (caps->id);
268 return "unknown/unknown";
273 * @caps: the caps to set the mime type to
274 * @mime: the mime type to attach to the caps
276 * Set the mime type of the caps as a string.
279 gst_caps_set_mime (GstCaps *caps, const gchar *mime)
281 g_return_if_fail (caps != NULL);
282 g_return_if_fail (mime != NULL);
284 caps->id = get_type_for_mime (mime);
288 * gst_caps_get_type_id:
289 * @caps: the caps to get the type id from
291 * Get the type id of the caps.
293 * Returns: the type id of the caps
296 gst_caps_get_type_id (GstCaps *caps)
298 g_return_val_if_fail (caps != NULL, 0);
304 * gst_caps_set_type_id:
305 * @caps: the caps to set the type id to
306 * @type_id: the type id to set
308 * Set the type id of the caps.
311 gst_caps_set_type_id (GstCaps *caps, guint16 type_id)
313 g_return_if_fail (caps != NULL);
319 * gst_caps_set_props:
320 * @caps: the caps to attach the properties to
321 * @props: the properties to attach
323 * Set the properties to the given caps.
325 * Returns: the new caps structure
328 gst_caps_set_props (GstCaps *caps, GstProps *props)
330 g_return_val_if_fail (caps != NULL, caps);
331 g_return_val_if_fail (props != NULL, caps);
332 g_return_val_if_fail (caps->properties == NULL, caps);
334 caps->properties = props;
340 * gst_caps_get_props:
341 * @caps: the caps to get the properties from
343 * Get the properties of the given caps.
345 * Returns: the properties of the caps
348 gst_caps_get_props (GstCaps *caps)
350 g_return_val_if_fail (caps != NULL, NULL);
352 return caps->properties;
358 * @capstoadd: the capability to append
360 * Appends a capability to the existing capability.
362 * Returns: the new capability
365 gst_caps_append (GstCaps *caps, GstCaps *capstoadd)
367 GstCaps *orig = caps;
369 g_return_val_if_fail (caps != capstoadd, caps);
377 caps->next = capstoadd;
385 * @capstoadd: a capabilty to prepend
387 * prepend the capability to the list of capabilities
389 * Returns: the new capability
392 gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd)
394 GstCaps *orig = capstoadd;
396 g_return_val_if_fail (caps != capstoadd, caps);
398 if (capstoadd == NULL)
401 while (capstoadd->next) {
402 capstoadd = capstoadd->next;
404 capstoadd->next = caps;
410 * gst_caps_get_by_name:
412 * @name: the name of the capability to get
414 * Get the capability with the given name from this
415 * chain of capabilities.
417 * Returns: the first capability in the chain with the
421 gst_caps_get_by_name (GstCaps *caps, const gchar *name)
423 g_return_val_if_fail (caps != NULL, NULL);
424 g_return_val_if_fail (name != NULL, NULL);
427 if (!strcmp (caps->name, name))
436 gst_caps_check_compatibility_func (GstCaps *fromcaps, GstCaps *tocaps)
438 if (fromcaps->id != tocaps->id) {
439 GST_DEBUG (0,"gstcaps: mime types differ (%s to %s)\n",
440 gst_type_find_by_id (fromcaps->id)->mime,
441 gst_type_find_by_id (tocaps->id)->mime);
445 if (tocaps->properties) {
446 if (fromcaps->properties) {
447 return gst_props_check_compatibility (fromcaps->properties, tocaps->properties);
450 GST_DEBUG (0,"gstcaps: no source caps\n");
455 // assume it accepts everything
456 GST_DEBUG (0,"gstcaps: no caps\n");
462 * gst_caps_check_compatibility:
463 * @fromcaps: a capabilty
464 * @tocaps: a capabilty
466 * Checks whether two capabilities are compatible.
468 * Returns: TRUE if compatible, FALSE otherwise
471 gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
473 if (fromcaps == NULL) {
474 if (tocaps == NULL) {
475 GST_DEBUG (0,"gstcaps: no caps\n");
479 GST_DEBUG (0,"gstcaps: no src but destination caps\n");
484 if (tocaps == NULL) {
485 GST_DEBUG (0,"gstcaps: src caps and no dest caps\n");
491 GstCaps *destcaps = tocaps;
494 if (gst_caps_check_compatibility_func (fromcaps, destcaps))
497 destcaps = destcaps->next;
499 fromcaps = fromcaps->next;
505 * gst_caps_save_thyself:
506 * @caps: a capabilty to save
507 * @parent: the parent XML node pointer
509 * Save the capability into an XML representation.
511 * Returns: a new XML node pointer
514 gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
517 xmlNodePtr subsubtree;
520 subtree = xmlNewChild (parent, NULL, "capscomp", NULL);
522 xmlNewChild (subtree, NULL, "name", caps->name);
523 xmlNewChild (subtree, NULL, "type", gst_type_find_by_id (caps->id)->mime);
524 if (caps->properties) {
525 subsubtree = xmlNewChild (subtree, NULL, "properties", NULL);
527 gst_props_save_thyself (caps->properties, subsubtree);
537 * gst_caps_load_thyself:
538 * @parent: the parent XML node pointer
540 * Load a new caps from the XML representation.
542 * Returns: a new capability
545 gst_caps_load_thyself (xmlNodePtr parent)
547 GstCaps *result = NULL;
548 xmlNodePtr field = parent->xmlChildrenNode;
551 if (!strcmp (field->name, "capscomp")) {
552 xmlNodePtr subfield = field->xmlChildrenNode;
556 g_mutex_lock (_gst_caps_chunk_lock);
557 caps = g_mem_chunk_alloc0 (_gst_caps_chunk);
558 g_mutex_unlock (_gst_caps_chunk_lock);
561 caps->lock = g_mutex_new ();
565 if (!strcmp (subfield->name, "name")) {
566 caps->name = xmlNodeGetContent (subfield);
568 if (!strcmp (subfield->name, "type")) {
569 content = xmlNodeGetContent (subfield);
570 caps->id = get_type_for_mime (content);
573 else if (!strcmp (subfield->name, "properties")) {
574 caps->properties = gst_props_load_thyself (subfield);
577 subfield = subfield->next;
579 result = gst_caps_append (result, caps);