Added a plain X videosink, the videosink uses capsnego. adjusted the v4lsrc so that...
[platform/upstream/gstreamer.git] / gst / gstcaps.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstcaps.c: Element capabilities subsystem
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 //#define GST_DEBUG_ENABLED
24 #include "gst_private.h"
25
26 #include "gstcaps.h"
27 #include "gsttype.h"
28
29 #include "gstpropsprivate.h"
30
31 static GMemChunk *_gst_caps_chunk;
32 static GMutex *_gst_caps_chunk_lock;
33
34 void
35 _gst_caps_initialize (void)
36 {
37   _gst_caps_chunk = g_mem_chunk_new ("GstCaps",
38                   sizeof (GstCaps), sizeof (GstCaps) * 256,
39                   G_ALLOC_AND_FREE);
40   _gst_caps_chunk_lock = g_mutex_new ();
41 }
42
43 static guint16
44 get_type_for_mime (const gchar *mime)
45 {
46   guint16 typeid;
47
48   typeid = gst_type_find_by_mime (mime);
49   if (typeid == 0) {
50      GstTypeFactory factory; // = g_new0 (GstTypeFactory, 1);
51
52      factory.mime = g_strdup (mime);
53      factory.exts = NULL;
54      factory.typefindfunc = NULL;
55
56      typeid = gst_type_register (&factory);
57   }
58   return typeid;
59 }
60
61 /**
62  * gst_caps_new:
63  * @name: the name of this capability
64  * @mime: the mime type to attach to the capability
65  *
66  * Create a new capability with the given mime type.
67  *
68  * Returns: a new capability
69  */
70 GstCaps*
71 gst_caps_new (const gchar *name, const gchar *mime)
72 {
73   GstCaps *caps;
74
75   g_return_val_if_fail (mime != NULL, NULL);
76
77   g_mutex_lock (_gst_caps_chunk_lock);
78   caps = g_mem_chunk_alloc (_gst_caps_chunk);
79   g_mutex_unlock (_gst_caps_chunk_lock);
80
81   caps->name = g_strdup (name);
82   caps->id = get_type_for_mime (mime);
83   caps->properties = NULL;
84   caps->next = NULL;
85   caps->refcount = 1;
86   caps->lock = g_mutex_new ();
87
88   return caps;
89 }
90
91 /**
92  * gst_caps_new_with_props:
93  * @name: the name of this capability
94  * @mime: the mime type to attach to the capability
95  * @props: the properties for this capability
96  *
97  * Create a new capability with the given mime type and the given properties.
98  *
99  * Returns: a new capability
100  */
101 GstCaps*
102 gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props)
103 {
104   GstCaps *caps;
105
106   caps = gst_caps_new (name, mime);
107   caps->properties = props;
108
109   return caps;
110 }
111
112 /**
113  * gst_caps_register:
114  * @factory: the factory to register
115  *
116  * Register the factory.
117  *
118  * Returns: the registered capability
119  */
120 GstCaps*
121 gst_caps_register (GstCapsFactory *factory)
122 {
123   guint dummy;
124
125   return gst_caps_register_count (factory, &dummy);
126 }
127
128 /**
129  * gst_caps_register_count:
130  * @factory: the factory to register
131  * @counter: count how many entries were consumed
132  *
133  * Register the factory.
134  *
135  * Returns: the registered capability
136  */
137 GstCaps*
138 gst_caps_register_count (GstCapsFactory *factory, guint *counter)
139 {
140   GstCapsFactoryEntry tag;
141   gint i = 0;
142   gchar *name;
143   GstCaps *caps;
144
145   g_return_val_if_fail (factory != NULL, NULL);
146
147   tag = (*factory)[i++];
148   g_return_val_if_fail (tag != NULL, NULL);
149
150   name = tag;
151
152   tag = (*factory)[i++];
153   g_return_val_if_fail (tag != NULL, NULL);
154
155   caps = gst_caps_new_with_props (name, (gchar *)tag,
156                    gst_props_register_count (&(*factory)[i], counter));
157
158   *counter += 2;
159
160   return caps;
161 }
162
163 /**
164  * gst_caps_destroy:
165  * @caps: the caps to destroy
166  *
167  * Frees the memory used by this caps structure and all
168  * the chained caps and properties.
169  */
170 void
171 gst_caps_destroy (GstCaps *caps)
172 {
173   GstCaps *next;
174
175   g_return_if_fail (caps != NULL);
176
177   GST_CAPS_LOCK (caps);
178   next = caps->next;
179   g_free (caps->name);
180   g_free (caps);
181   GST_CAPS_UNLOCK (caps);
182
183   if (next) 
184     gst_caps_unref (next);
185 }
186
187 /**
188  * gst_caps_unref:
189  * @caps: the caps to unref
190  *
191  * Decrease the refcount of this caps structure, 
192  * destroying it when the refcount is 0
193  */
194 void
195 gst_caps_unref (GstCaps *caps)
196 {
197   gboolean zero;
198   GstCaps *next;
199
200   g_return_if_fail (caps != NULL);
201
202   GST_CAPS_LOCK (caps);
203   caps->refcount--;
204   zero = (caps->refcount == 0);
205   next = caps->next;
206   GST_CAPS_UNLOCK (caps);
207
208   if (next)
209     gst_caps_unref (next);
210
211   if (zero)
212     gst_caps_destroy (caps);
213 }
214
215 /**
216  * gst_caps_ref:
217  * @caps: the caps to ref
218  *
219  * Increase the refcount of this caps structure
220  */
221 void
222 gst_caps_ref (GstCaps *caps)
223 {
224   g_return_if_fail (caps != NULL);
225
226   GST_CAPS_LOCK (caps);
227   caps->refcount++;
228   GST_CAPS_UNLOCK (caps);
229 }
230
231 /**
232  * gst_caps_copy:
233  * @caps: the caps to copy
234  *
235  * Copies the caps.
236  *
237  * Returns: a copy of the GstCaps structure.
238  */
239 GstCaps*
240 gst_caps_copy (GstCaps *caps)
241 {
242   GstCaps *new = caps;;
243
244   g_return_val_if_fail (caps != NULL, NULL);
245
246   GST_CAPS_LOCK (caps);
247   new = gst_caps_new_with_props (
248                   caps->name,
249                   (gst_type_find_by_id (caps->id))->mime,
250                   gst_props_copy (caps->properties));
251   GST_CAPS_UNLOCK (caps);
252
253   return new;
254 }
255
256 /**
257  * gst_caps_copy_on_write:
258  * @caps: the caps to copy
259  *
260  * Copies the caps if the refcount is greater than 1
261  *
262  * Returns: a pointer to a GstCaps strcuture that can
263  * be safely written to
264  */
265 GstCaps*
266 gst_caps_copy_on_write (GstCaps *caps)
267 {
268   GstCaps *new = caps;
269   gboolean needcopy;
270
271   g_return_val_if_fail (caps != NULL, NULL);
272
273   GST_CAPS_LOCK (caps);
274   needcopy = (caps->refcount > 1);
275   GST_CAPS_UNLOCK (caps);
276
277   if (needcopy) {
278     new = gst_caps_copy (caps);
279     gst_caps_unref (caps);
280   }
281
282   return new;
283 }
284
285 /**
286  * gst_caps_get_name:
287  * @caps: the caps to get the name from
288  *
289  * Get the name of a GstCaps structure.
290  *
291  * Returns: the name of the caps
292  */
293 const gchar*
294 gst_caps_get_name (GstCaps *caps)
295 {
296   g_return_val_if_fail (caps != NULL, NULL);
297
298   return (const gchar *)caps->name;
299 }
300
301 /**
302  * gst_caps_set_name:
303  * @caps: the caps to set the name to
304  * @name: the name to set
305  *
306  * Set the name of a caps.
307  */
308 void
309 gst_caps_set_name (GstCaps *caps, const gchar *name)
310 {
311   g_return_if_fail (caps != NULL);
312
313   if (caps->name)
314     g_free (caps->name);
315
316   caps->name = g_strdup (name);
317 }
318
319 /**
320  * gst_caps_get_mime:
321  * @caps: the caps to get the mime type from
322  *
323  * Get the mime type of the caps as a string.
324  *
325  * Returns: the mime type of the caps
326  */
327 const gchar*
328 gst_caps_get_mime (GstCaps *caps)
329 {
330   GstType *type;
331
332   g_return_val_if_fail (caps != NULL, NULL);
333
334   type = gst_type_find_by_id (caps->id);
335
336   if (type)
337     return type->mime;
338   else
339     return "unknown/unknown";
340 }
341
342 /**
343  * gst_caps_set_mime:
344  * @caps: the caps to set the mime type to
345  * @mime: the mime type to attach to the caps
346  *
347  * Set the mime type of the caps as a string.
348  */
349 void
350 gst_caps_set_mime (GstCaps *caps, const gchar *mime)
351 {
352   g_return_if_fail (caps != NULL);
353   g_return_if_fail (mime != NULL);
354
355   caps->id = get_type_for_mime (mime);
356 }
357
358 /**
359  * gst_caps_get_type_id:
360  * @caps: the caps to get the type id from
361  *
362  * Get the type id of the caps.
363  *
364  * Returns: the type id of the caps
365  */
366 guint16
367 gst_caps_get_type_id (GstCaps *caps)
368 {
369   g_return_val_if_fail (caps != NULL, 0);
370
371   return caps->id;
372 }
373
374 /**
375  * gst_caps_set_type_id:
376  * @caps: the caps to set the type id to
377  * @type_id: the type id to set
378  *
379  * Set the type id of the caps.
380  */
381 void
382 gst_caps_set_type_id (GstCaps *caps, guint16 type_id)
383 {
384   g_return_if_fail (caps != NULL);
385
386   caps->id = type_id;
387 }
388
389 /**
390  * gst_caps_set_props:
391  * @caps: the caps to attach the properties to
392  * @props: the properties to attach
393  *
394  * Set the properties to the given caps.
395  *
396  * Returns: the new caps structure
397  */
398 GstCaps*
399 gst_caps_set_props (GstCaps *caps, GstProps *props)
400 {
401   g_return_val_if_fail (caps != NULL, caps);
402   g_return_val_if_fail (props != NULL, caps);
403   g_return_val_if_fail (caps->properties == NULL, caps);
404
405   caps->properties = props;
406
407   return caps;
408 }
409
410 /**
411  * gst_caps_get_props:
412  * @caps: the caps to get the properties from
413  *
414  * Get the properties of the given caps.
415  *
416  * Returns: the properties of the caps
417  */
418 GstProps*
419 gst_caps_get_props (GstCaps *caps)
420 {
421   g_return_val_if_fail (caps != NULL, NULL);
422
423   return caps->properties;
424 }
425
426 /**
427  * gst_caps_append:
428  * @caps: a capabilty
429  * @capstoadd: the capability to append
430  *
431  * Appends a capability to the existing capability.
432  *
433  * Returns: the new capability
434  */
435 GstCaps*
436 gst_caps_append (GstCaps *caps, GstCaps *capstoadd)
437 {
438   GstCaps *orig = caps;
439   
440   g_return_val_if_fail (caps != capstoadd, caps);
441
442   if (caps == NULL)
443     return capstoadd;
444   
445   while (caps->next) {
446     caps = caps->next;
447   }
448   caps->next = capstoadd;
449
450   return orig;
451 }
452
453 /**
454  * gst_caps_prepend:
455  * @caps: a capabilty
456  * @capstoadd: a capabilty to prepend
457  *
458  * prepend the capability to the list of capabilities
459  *
460  * Returns: the new capability
461  */
462 GstCaps*
463 gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd)
464 {
465   GstCaps *orig = capstoadd;
466   
467   g_return_val_if_fail (caps != capstoadd, caps);
468
469   if (capstoadd == NULL)
470     return caps;
471
472   while (capstoadd->next) {
473     capstoadd = capstoadd->next;
474   }
475   capstoadd->next = caps;
476
477   return orig;
478 }
479
480 /**
481  * gst_caps_get_by_name:
482  * @caps: a capabilty
483  * @name: the name of the capability to get
484  *
485  * Get the capability with the given name from this
486  * chain of capabilities.
487  *
488  * Returns: the first capability in the chain with the 
489  * given name
490  */
491 GstCaps*
492 gst_caps_get_by_name (GstCaps *caps, const gchar *name)
493 {
494   g_return_val_if_fail (caps != NULL, NULL);
495   g_return_val_if_fail (name != NULL, NULL);
496    
497   while (caps) {
498     if (!strcmp (caps->name, name)) 
499       return caps;
500     caps = caps->next;
501   }
502
503   return NULL;
504 }
505                                                                                                                    
506 static gboolean
507 gst_caps_check_compatibility_func (GstCaps *fromcaps, GstCaps *tocaps)
508 {
509   if (fromcaps->id != tocaps->id) {
510     GST_DEBUG (0,"gstcaps: mime types differ (%d to %d)\n",
511                fromcaps->id, tocaps->id);
512     return FALSE;
513   }
514
515   if (tocaps->properties) {
516     if (fromcaps->properties) {
517       return gst_props_check_compatibility (fromcaps->properties, tocaps->properties);
518     }
519     else {
520       GST_DEBUG (0,"gstcaps: no source caps\n");
521       return FALSE;
522     }
523   }
524   else {
525     // assume it accepts everything
526     GST_DEBUG (0,"gstcaps: no caps\n");
527     return TRUE;
528   }
529 }
530
531 /**
532  * gst_caps_check_compatibility:
533  * @fromcaps: a capabilty
534  * @tocaps: a capabilty
535  *
536  * Checks whether two capabilities are compatible.
537  *
538  * Returns: TRUE if compatible, FALSE otherwise
539  */
540 gboolean
541 gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
542 {
543   if (fromcaps == NULL) {
544     if (tocaps == NULL) {
545       GST_DEBUG (0,"gstcaps: no caps\n");
546       return TRUE;
547     }
548     else {
549       GST_DEBUG (0,"gstcaps: no src but destination caps\n");
550       return FALSE;
551     }
552   }
553   else {
554     if (tocaps == NULL) {
555       GST_DEBUG (0,"gstcaps: src caps and no dest caps\n");
556       return TRUE;
557     }
558   }
559
560   while (fromcaps) {
561     GstCaps *destcaps = tocaps;
562
563     while (destcaps) {
564       if (gst_caps_check_compatibility_func (fromcaps, destcaps))
565         return TRUE;
566
567       destcaps =  destcaps->next;
568     }
569     fromcaps =  fromcaps->next;
570   }
571   return FALSE;
572 }
573
574 /**
575  * gst_caps_save_thyself:
576  * @caps: a capabilty to save
577  * @parent: the parent XML node pointer
578  *
579  * Save the capability into an XML representation.
580  *
581  * Returns: a new XML node pointer
582  */
583 xmlNodePtr
584 gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
585 {
586   xmlNodePtr subtree;
587   xmlNodePtr subsubtree;
588
589   while (caps) {
590     subtree = xmlNewChild (parent, NULL, "capscomp", NULL);
591
592     xmlNewChild (subtree, NULL, "name", caps->name);
593     xmlNewChild (subtree, NULL, "type", gst_type_find_by_id (caps->id)->mime);
594     if (caps->properties) {
595       subsubtree = xmlNewChild (subtree, NULL, "properties", NULL);
596
597       gst_props_save_thyself (caps->properties, subsubtree);
598     }
599
600     caps = caps->next;
601   }
602
603   return parent;
604 }
605
606 /**
607  * gst_caps_load_thyself:
608  * @parent: the parent XML node pointer
609  *
610  * Load a new caps from the XML representation.
611  *
612  * Returns: a new capability
613  */
614 GstCaps*
615 gst_caps_load_thyself (xmlNodePtr parent)
616 {
617   GstCaps *result = NULL;
618   xmlNodePtr field = parent->xmlChildrenNode;
619
620   while (field) {
621     if (!strcmp (field->name, "capscomp")) {
622       xmlNodePtr subfield = field->xmlChildrenNode;
623       GstCaps *caps;
624       gchar *content;
625
626       g_mutex_lock (_gst_caps_chunk_lock);
627       caps = g_mem_chunk_alloc0 (_gst_caps_chunk);
628       g_mutex_unlock (_gst_caps_chunk_lock);
629
630       caps->refcount = 1;
631       caps->lock = g_mutex_new ();
632       caps->next = NULL;
633         
634       while (subfield) {
635         if (!strcmp (subfield->name, "name")) {
636           caps->name = xmlNodeGetContent (subfield);
637         }
638         if (!strcmp (subfield->name, "type")) {
639           content = xmlNodeGetContent (subfield);
640           caps->id = get_type_for_mime (content);
641           g_free (content);
642         }
643         else if (!strcmp (subfield->name, "properties")) {
644           caps->properties = gst_props_load_thyself (subfield);
645         }
646         
647         subfield = subfield->next;
648       }
649       result = gst_caps_append (result, caps);
650     }
651     field = field->next;
652   }
653
654   return result;
655 }
656
657
658