gst/gstcaps.c: Move the poisoning to allow a NULL structure
[platform/upstream/gstreamer.git] / gst / gstcaps.c
1 /* GStreamer
2  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <string.h>
24
25 #include <gst/gst.h>
26
27 #define CAPS_POISON(caps) do{ \
28   GstCaps *_newcaps = gst_caps_copy (caps); \
29   gst_caps_free(caps); \
30   caps = _newcaps; \
31 } while (0)
32 #define STRUCTURE_POISON(structure) do{ \
33   GstStructure *_newstruct = gst_structure_copy (structure); \
34   gst_structure_free(structure); \
35   structure = _newstruct; \
36 } while (0)
37
38
39 static void _gst_caps_transform_to_string (const GValue *src_value,
40     GValue *dest_value);
41 static void _gst_caps_value_init (GValue *value);
42 static void _gst_caps_value_free (GValue *value);
43 static void _gst_caps_value_copy (const GValue *src, GValue *dest);
44 static gpointer _gst_caps_value_peek_pointer (const GValue *value);
45 static gboolean _gst_caps_from_string_inplace (GstCaps *caps,
46     const gchar *string);
47
48
49 GType _gst_caps_type;
50
51 void _gst_caps_initialize (void)
52 {
53   static const GTypeValueTable type_value_table = {
54     _gst_caps_value_init,
55     _gst_caps_value_free,
56     _gst_caps_value_copy,
57     _gst_caps_value_peek_pointer,
58     NULL,
59     NULL,
60     NULL,
61     NULL,
62   };
63   static const GTypeInfo caps2_info = {
64     0,
65     NULL,
66     NULL,
67     NULL,
68     NULL,
69     NULL,
70     0,
71     0,
72     NULL,
73     &type_value_table,
74   };
75
76   _gst_caps_type = g_type_register_static (G_TYPE_BOXED, "GstCaps",
77       &caps2_info, 0);
78
79   g_value_register_transform_func (_gst_caps_type, G_TYPE_STRING,
80       _gst_caps_transform_to_string);
81 }
82
83 GType gst_caps_get_type (void)
84 {
85   return _gst_caps_type;
86 }
87
88 /* creation/deletion */
89 GstCaps *gst_caps_new_empty (void)
90 {
91   GstCaps *caps = g_new0(GstCaps, 1);
92
93   caps->type = _gst_caps_type;
94   caps->structs = g_ptr_array_new();
95
96   return caps;
97 }
98
99 GstCaps *gst_caps_new_any (void)
100 {
101   GstCaps *caps = g_new0(GstCaps, 1);
102
103   caps->type = _gst_caps_type;
104   caps->structs = g_ptr_array_new();
105   caps->flags = GST_CAPS_FLAGS_ANY;
106
107   return caps;
108 }
109
110 GstCaps *gst_caps_new_simple (const char *media_type, const char *fieldname,
111     ...)
112 {
113   GstCaps *caps;
114   GstStructure *structure;
115   va_list var_args;
116
117   caps = g_new0(GstCaps, 1);
118   caps->type = _gst_caps_type;
119   caps->structs = g_ptr_array_new();
120
121   va_start (var_args, fieldname);
122   structure = gst_structure_new_valist (media_type, fieldname, var_args);
123   va_end (var_args);
124
125   gst_caps_append_structure (caps, structure);
126   
127   return caps;
128 }
129
130 GstCaps *gst_caps_new_full (GstStructure *struct1, ...)
131 {
132   GstCaps *caps;
133   va_list var_args;
134
135   va_start (var_args, struct1);
136   caps = gst_caps_new_full_valist (struct1, var_args);
137   va_end (var_args);
138
139   return caps;
140 }
141
142 GstCaps *gst_caps_new_full_valist (GstStructure *structure,
143     va_list var_args)
144 {
145   GstCaps *caps;
146
147   caps = g_new0(GstCaps, 1);
148   caps->type = _gst_caps_type;
149   caps->structs = g_ptr_array_new();
150
151   while(structure){
152     gst_caps_append_structure (caps, structure);
153     structure = va_arg (var_args, GstStructure *);
154   }
155
156   return caps;
157 }
158
159 GstCaps *gst_caps_copy (const GstCaps *caps)
160 {
161   GstCaps *newcaps;
162   GstStructure *structure;
163   int i;
164
165   g_return_val_if_fail(caps != NULL, NULL);
166
167   newcaps = g_new0(GstCaps, 1);
168   newcaps->type = _gst_caps_type;
169   newcaps->flags = caps->flags;
170   newcaps->structs = g_ptr_array_new();
171
172   for(i=0;i<caps->structs->len;i++){
173     structure = gst_caps_get_structure (caps, i);
174     gst_caps_append_structure (newcaps, gst_structure_copy(structure));
175   }
176
177   return newcaps;
178 }
179
180 void gst_caps_free (GstCaps *caps)
181 {
182   GstStructure *structure;
183   int i;
184   
185   g_return_if_fail(caps != NULL);
186
187   for(i=0;i<caps->structs->len;i++){
188     structure = gst_caps_get_structure (caps, i);
189     gst_structure_free (structure);
190   }
191   g_ptr_array_free(caps->structs, TRUE);
192 #ifdef USE_POISONING
193   memset (caps, 0xff, sizeof(GstCaps));
194 #endif
195   g_free(caps);
196 }
197
198 const GstCaps *gst_static_caps_get (GstStaticCaps *static_caps)
199 {
200   GstCaps *caps = (GstCaps *)static_caps;
201   gboolean ret;
202
203   if (caps->type == 0) {
204     caps->type = _gst_caps_type;
205     caps->structs = g_ptr_array_new();
206     ret = _gst_caps_from_string_inplace (caps, static_caps->string);
207
208     if (!ret) {
209       g_critical ("Could not convert static caps \"%s\"", static_caps->string);
210     }
211   }
212
213   return caps;
214 }
215
216 /* manipulation */
217 void gst_caps_append (GstCaps *caps1, GstCaps *caps2)
218 {
219   GstStructure *structure;
220   int i;
221
222   g_return_if_fail (caps1 != NULL);
223   g_return_if_fail (caps2 != NULL);
224
225 #ifdef USE_POISONING
226   CAPS_POISON (caps2);
227 #endif
228   for(i=0;i<caps2->structs->len;i++){
229     structure = gst_caps_get_structure (caps2, i);
230     gst_caps_append_structure (caps1, structure);
231   }
232   g_ptr_array_free(caps2->structs, TRUE);
233 #ifdef USE_POISONING
234   memset (caps2, 0xff, sizeof(GstCaps));
235 #endif
236   g_free(caps2);
237 }
238
239 void gst_caps_append_structure (GstCaps *caps, GstStructure *structure)
240 {
241   g_return_if_fail(caps != NULL);
242
243   if (structure){
244 #ifdef USE_POISONING
245     STRUCTURE_POISON (structure);
246 #endif
247     g_ptr_array_add (caps->structs, structure);
248   }
249 }
250
251 GstCaps *gst_caps_split_one (GstCaps *caps)
252 {
253   /* FIXME */
254   g_critical ("unimplemented");
255
256   return NULL;
257 }
258
259 int gst_caps_get_size (const GstCaps *caps)
260 {
261   g_return_val_if_fail (caps != NULL, 0);
262
263   return caps->structs->len;
264 }
265
266 GstStructure *gst_caps_get_structure (const GstCaps *caps, int index)
267 {
268   g_return_val_if_fail (caps != NULL, NULL);
269   g_return_val_if_fail (index >= 0, NULL);
270   g_return_val_if_fail (index < caps->structs->len, NULL);
271
272   return g_ptr_array_index(caps->structs, index);
273 }
274
275 GstCaps *gst_caps_copy_1 (const GstCaps *caps)
276 {
277   GstCaps *newcaps;
278   GstStructure *structure;
279
280   g_return_val_if_fail(caps != NULL, NULL);
281
282   newcaps = g_new0(GstCaps, 1);
283   newcaps->type = _gst_caps_type;
284   newcaps->flags = caps->flags;
285   newcaps->structs = g_ptr_array_new();
286
287   if (caps->structs->len > 0){
288     structure = gst_caps_get_structure (caps, 0);
289     gst_caps_append_structure (newcaps, gst_structure_copy(structure));
290   }
291
292   return newcaps;
293 }
294
295 void gst_caps_set_simple (GstCaps *caps, char *field, ...)
296 {
297   GstStructure *structure;
298   va_list var_args;
299
300   g_return_if_fail (caps != NULL);
301   g_return_if_fail (caps->structs->len == 1);
302
303   structure = gst_caps_get_structure (caps, 0);
304
305   va_start (var_args, field);
306   gst_structure_set_valist (structure, field, var_args);
307   va_end(var_args);
308 }
309
310 void gst_caps_set_simple_valist (GstCaps *caps, char *field, va_list varargs)
311 {
312   GstStructure *structure;
313
314   g_return_if_fail (caps != NULL);
315   g_return_if_fail (caps->structs->len != 1);
316
317   structure = gst_caps_get_structure (caps, 0);
318
319   gst_structure_set_valist (structure, field, varargs);
320 }
321
322 /* tests */
323 gboolean gst_caps_is_any (const GstCaps *caps)
324 {
325   g_return_val_if_fail(caps != NULL, FALSE);
326
327   return (caps->flags & GST_CAPS_FLAGS_ANY);
328 }
329
330 gboolean gst_caps_is_empty (const GstCaps *caps)
331 {
332   g_return_val_if_fail(caps != NULL, FALSE);
333
334   if (caps->flags & GST_CAPS_FLAGS_ANY) return FALSE;
335
336   return (caps->structs == NULL) || (caps->structs->len == 0);
337 }
338
339 gboolean gst_caps_is_chained (const GstCaps *caps)
340 {
341   g_return_val_if_fail(caps != NULL, FALSE);
342
343   return (caps->structs->len > 1);
344 }
345
346 static gboolean
347 _gst_caps_is_fixed_foreach (GQuark field_id, GValue *value, gpointer unused)
348 {
349   GType type = G_VALUE_TYPE (value);
350   if (G_TYPE_IS_FUNDAMENTAL (type)) return TRUE;
351   if (type == GST_TYPE_FOURCC) return TRUE;
352   return FALSE;
353 }
354
355 gboolean gst_caps_is_fixed (const GstCaps *caps)
356 {
357   GstStructure *structure;
358
359   g_return_val_if_fail(caps != NULL, FALSE);
360
361   if (caps->structs->len != 1) return FALSE;
362
363   structure = gst_caps_get_structure (caps, 0);
364
365   return gst_structure_foreach (structure, _gst_caps_is_fixed_foreach, NULL);
366 }
367
368 static gboolean
369 _gst_structure_is_equal_foreach (GQuark field_id, 
370     GValue *val2, gpointer data)
371 {
372   GstStructure *struct1 = (GstStructure *) data;
373   const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
374
375   if (val1 == NULL) return FALSE;
376   if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
377     return TRUE;
378   }
379
380   return FALSE;
381 }
382
383 gboolean gst_caps_is_equal_fixed (const GstCaps *caps1, const GstCaps *caps2)
384 {
385   GstStructure *struct1, *struct2;
386
387   g_return_val_if_fail (gst_caps_is_fixed(caps1), FALSE);
388   g_return_val_if_fail (gst_caps_is_fixed(caps2), FALSE);
389
390   struct1 = gst_caps_get_structure (caps1, 0);
391   struct2 = gst_caps_get_structure (caps2, 0);
392
393   if (struct1->name != struct2->name) {
394     return FALSE;
395   }
396   if (struct1->fields->len != struct2->fields->len) {
397     return FALSE;
398   }
399
400   return gst_structure_foreach (struct1, _gst_structure_is_equal_foreach,
401       struct2);
402 }
403
404 static gboolean
405 _gst_structure_field_has_compatible (GQuark field_id, 
406     GValue *val2, gpointer data)
407 {
408   GValue dest = { 0 };
409   GstStructure *struct1 = (GstStructure *) data;
410   const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
411
412   if (val1 == NULL) return FALSE;
413   if (gst_value_intersect (&dest, val1, val2)) {
414     g_value_unset (&dest);
415     return TRUE;
416   }
417
418   return FALSE;
419 }
420
421 static gboolean
422 _gst_cap_is_always_compatible (const GstStructure *struct1,
423     const GstStructure *struct2)
424 {
425   if(struct1->name != struct2->name){
426     return FALSE;
427   }
428
429   /* the reversed order is important */
430   return gst_structure_foreach ((GstStructure *) struct2, 
431       _gst_structure_field_has_compatible, (gpointer) struct1);
432 }
433
434 static gboolean
435 _gst_caps_cap_is_always_compatible (const GstStructure *struct1,
436     const GstCaps *caps2)
437 {
438   int i;
439
440   for(i=0;i<caps2->structs->len;i++){
441     GstStructure *struct2 = gst_caps_get_structure (caps2, i);
442
443     if (_gst_cap_is_always_compatible (struct1, struct2)) {
444       return TRUE;
445     }
446   }
447
448   return FALSE;
449 }
450
451 gboolean
452 gst_caps_is_always_compatible (const GstCaps *caps1, const GstCaps *caps2)
453 {
454   int i;
455
456   g_return_val_if_fail (caps1 != NULL, FALSE);
457   g_return_val_if_fail (caps2 != NULL, FALSE);
458   /* FIXME: is this right ? */
459   g_return_val_if_fail (!gst_caps_is_empty (caps1), FALSE);
460   g_return_val_if_fail (!gst_caps_is_empty (caps2), FALSE);
461   
462   if (gst_caps_is_any (caps2))
463     return TRUE;
464   if (gst_caps_is_any (caps1))
465     return FALSE;
466   
467   for(i=0;i<caps1->structs->len;i++) {
468     GstStructure *struct1 = gst_caps_get_structure (caps1, i);
469
470     if (_gst_caps_cap_is_always_compatible(struct1, caps2) == FALSE){
471       return FALSE;
472     }
473
474   }
475
476   return FALSE;
477 }
478
479 typedef struct {
480   GstStructure *dest;
481   const GstStructure *intersect;
482   gboolean first_run;
483 } IntersectData;
484
485 static gboolean
486 gst_caps_structure_intersect_field (GQuark id, GValue *val1, gpointer data)
487 {
488   IntersectData *idata = (IntersectData *) data;
489   GValue dest_value = { 0 };
490   const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
491
492   if (val2 == NULL) {
493     gst_structure_id_set_value (idata->dest, id, val1);
494   } else if (idata->first_run) {
495     if (gst_value_intersect (&dest_value, val1, val2)) {
496       gst_structure_id_set_value (idata->dest, id, &dest_value);
497       g_value_unset (&dest_value);
498     } else {
499       return FALSE;
500     }
501   }
502   
503   return TRUE;
504 }
505
506 static GstStructure *gst_caps_structure_intersect (const GstStructure *struct1,
507     const GstStructure *struct2)
508 {
509   IntersectData data;
510
511   g_return_val_if_fail(struct1 != NULL, NULL);
512   g_return_val_if_fail(struct2 != NULL, NULL);
513
514   if (struct1->name != struct2->name) return NULL;
515
516   data.dest = gst_structure_id_empty_new (struct1->name);
517   data.intersect = struct2;
518   data.first_run = TRUE;
519   if (!gst_structure_foreach ((GstStructure *) struct1, 
520         gst_caps_structure_intersect_field, &data))
521     goto error;
522   
523   data.intersect = struct1;
524   data.first_run = FALSE;
525   if (!gst_structure_foreach ((GstStructure *) struct2, 
526         gst_caps_structure_intersect_field, &data))
527     goto error;
528
529   return data.dest;
530
531 error:
532   gst_structure_free (data.dest);
533   return NULL;
534 }
535
536 #if 0
537 static GstStructure *gst_caps_structure_union (const GstStructure *struct1,
538     const GstStructure *struct2)
539 {
540   int i;
541   GstStructure *dest;
542   const GstStructureField *field1;
543   const GstStructureField *field2;
544   int ret;
545
546   /* FIXME this doesn't actually work */
547
548   if (struct1->name != struct2->name) return NULL;
549
550   dest = gst_structure_id_empty_new (struct1->name);
551
552   for(i=0;i<struct1->fields->len;i++){
553     GValue dest_value = { 0 };
554
555     field1 = GST_STRUCTURE_FIELD (struct1, i);
556     field2 = gst_structure_id_get_field (struct2, field1->name);
557
558     if (field2 == NULL) {
559       continue;
560     } else {
561       if (gst_value_union (&dest_value, &field1->value, &field2->value)) {
562         gst_structure_set_value (dest, g_quark_to_string(field1->name),
563             &dest_value);
564       } else {
565         ret = gst_value_compare (&field1->value, &field2->value);
566       }
567     }
568   }
569
570   return dest;
571 }
572 #endif
573
574 /* operations */
575 GstCaps *gst_caps_intersect (const GstCaps *caps1, const GstCaps *caps2)
576 {
577   int i,j;
578   GstStructure *struct1;
579   GstStructure *struct2;
580   GstCaps *dest;
581   //GstCaps *caps;
582
583   g_return_val_if_fail (caps1 != NULL, NULL);
584   g_return_val_if_fail (caps2 != NULL, NULL);
585
586   if (gst_caps_is_empty (caps1) || gst_caps_is_empty (caps2)){
587     return gst_caps_new_empty ();
588   }
589   if (gst_caps_is_any (caps1)) return gst_caps_copy (caps2);
590   if (gst_caps_is_any (caps2)) return gst_caps_copy (caps1);
591
592   dest = gst_caps_new_empty();
593   for(i=0;i<caps1->structs->len;i++){
594     struct1 = gst_caps_get_structure (caps1, i);
595     for(j=0;j<caps2->structs->len;j++){
596       GstStructure *istruct;
597
598       struct2 = gst_caps_get_structure (caps2, j);
599       istruct = gst_caps_structure_intersect (struct1, struct2);
600
601       gst_caps_append_structure(dest, istruct);
602     }
603   }
604
605 #if 0
606   caps = gst_caps_simplify (dest);
607   gst_caps_free (dest);
608
609   return caps;
610 #else
611   return dest;
612 #endif
613 }
614
615 GstCaps *gst_caps_union (const GstCaps *caps1, const GstCaps *caps2)
616 {
617   GstCaps *dest1;
618   GstCaps *dest2;
619
620   dest1 = gst_caps_copy (caps1);
621   dest2 = gst_caps_copy (caps2);
622   gst_caps_append (dest1, dest2);
623
624
625   /* FIXME: need a simplify function */
626
627   return dest1;
628 }
629
630 typedef struct _NormalizeForeach {
631   GstCaps *caps;
632   GstStructure *structure;
633 } NormalizeForeach;
634
635 static gboolean
636 _gst_caps_normalize_foreach (GQuark field_id, GValue *value, gpointer ptr)
637 {
638   NormalizeForeach *nf = (NormalizeForeach *) ptr;
639   GValue val = { 0 };
640   int i;
641
642   if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
643     for (i=1; i<gst_value_list_get_size (value); i++) {
644       const GValue *v = gst_value_list_get_value (value, i);
645       GstStructure *structure = gst_structure_copy (nf->structure);
646
647       gst_structure_id_set_value (structure, field_id, v);
648       gst_caps_append_structure (nf->caps, structure);
649     }
650
651     gst_value_init_and_copy (&val, gst_value_list_get_value (value, 0));
652     gst_structure_id_set_value (nf->structure, field_id, &val);
653     g_value_unset (&val);
654
655     return FALSE;
656   }
657   return TRUE;
658 }
659
660 GstCaps *gst_caps_normalize (const GstCaps *caps)
661 {
662   NormalizeForeach nf;
663   GstCaps *newcaps;
664   int i;
665
666   g_return_val_if_fail(caps != NULL, NULL);
667
668   newcaps = gst_caps_copy (caps);
669   nf.caps = newcaps;
670
671   for(i=0;i<newcaps->structs->len;i++){
672     nf.structure = gst_caps_get_structure (newcaps, i);
673
674     while (!gst_structure_foreach (nf.structure, _gst_caps_normalize_foreach,
675           &nf));
676   }
677
678   return newcaps;
679 }
680
681 static gboolean
682 simplify_foreach (GQuark field_id, GValue *value, gpointer user_data)
683 {
684   GstStructure *s2 = (GstStructure *) user_data;
685   const GValue *v2;
686
687   v2 = gst_structure_id_get_value (s2, field_id);
688   if (v2 == NULL) return FALSE;
689
690   if (gst_value_compare (value, v2) == GST_VALUE_EQUAL) return TRUE;
691   return FALSE;
692 }
693
694 static gboolean
695 gst_caps_structure_simplify (GstStructure *struct1, const GstStructure *struct2)
696 {
697   /* FIXME this is just a simple compare.  Better would be to merge
698    * the two structures */
699   if (struct1->name != struct2->name) return FALSE;
700   if (struct1->fields->len != struct2->fields->len) return FALSE;
701
702   return gst_structure_foreach (struct1, simplify_foreach, (void *)struct2);
703 }
704
705 GstCaps *gst_caps_simplify (const GstCaps *caps)
706 {
707   int i;
708   int j;
709   GstCaps *newcaps;
710   GstStructure *structure;
711   GstStructure *struct2;
712
713   if (gst_caps_get_size (caps) < 2) {
714     return gst_caps_copy (caps);
715   }
716
717   newcaps = gst_caps_new_empty ();
718
719   for(i=0;i<gst_caps_get_size (caps);i++){
720     structure = gst_caps_get_structure (caps, i);
721
722     for(j=0;j<gst_caps_get_size (newcaps);j++){
723       struct2 = gst_caps_get_structure (caps, i);
724       if (gst_caps_structure_simplify (struct2, structure)) {
725         break;
726       }
727     }
728     if (j==gst_caps_get_size (newcaps)) {
729       gst_caps_append_structure (newcaps, gst_structure_copy(structure));
730     }
731   }
732
733   return newcaps;
734 }
735
736 #ifndef GST_DISABLE_LOADSAVE
737 xmlNodePtr gst_caps_save_thyself (const GstCaps *caps, xmlNodePtr parent)
738 {
739
740   return 0;
741 }
742
743 GstCaps *gst_caps_load_thyself (xmlNodePtr parent)
744 {
745
746   return NULL;
747 }
748 #endif
749
750 /* utility */
751 void gst_caps_replace (GstCaps **caps, GstCaps *newcaps)
752 {
753 #ifdef USE_POISONING
754   if (newcaps) CAPS_POISON (newcaps);
755 #endif
756   if (*caps) gst_caps_free(*caps);
757   *caps = newcaps;
758 }
759
760 gchar *gst_caps_to_string (const GstCaps *caps)
761 {
762   int i;
763   GstStructure *structure;
764   GString *s;
765
766   /* FIXME does this leak? */
767
768   if (caps == NULL) {
769     return g_strdup("NULL");
770   }
771   if(gst_caps_is_any(caps)){
772     return g_strdup("ANY");
773   }
774   if(gst_caps_is_empty(caps)){
775     return g_strdup("EMPTY");
776   }
777   s = g_string_new("");
778   structure = gst_caps_get_structure (caps, 0);
779   g_string_append(s, gst_structure_to_string(structure));
780
781   for(i=1;i<caps->structs->len;i++){
782     structure = gst_caps_get_structure (caps, i);
783
784     g_string_append(s, "; ");
785     g_string_append(s, gst_structure_to_string(structure));
786   }
787
788   return g_string_free(s, FALSE);
789 }
790
791 static gboolean _gst_caps_from_string_inplace (GstCaps *caps,
792     const gchar *string)
793 {
794   GstStructure *structure;
795   gchar *s;
796
797   if (strcmp("ANY", string)==0) {
798     caps->flags = GST_CAPS_FLAGS_ANY;
799     return TRUE;
800   }
801   if (strcmp("NONE", string)==0) {
802     return TRUE;
803   }
804
805   structure = gst_structure_from_string(string, &s);
806   if (structure == NULL) {
807     return FALSE;
808   }
809   gst_caps_append_structure (caps, structure);
810
811   while (*s == ';') {
812     s++;
813     while (g_ascii_isspace(*s))s++;
814     structure = gst_structure_from_string(s, &s);
815     if (structure == NULL) {
816       return FALSE;
817     }
818     gst_caps_append_structure (caps, structure);
819     while (g_ascii_isspace(*s))s++;
820   }
821
822   if (*s != 0){
823     return FALSE;
824   }
825
826   return TRUE;
827 }
828
829 GstCaps *gst_caps_from_string (const gchar *string)
830 {
831   GstCaps *caps;
832
833   caps = gst_caps_new_empty();
834   if (_gst_caps_from_string_inplace (caps, string)) {
835     return caps;
836   } else {
837     gst_caps_free (caps);
838     return NULL;
839   }
840 }
841
842 static void _gst_caps_transform_to_string (const GValue *src_value,
843     GValue *dest_value)
844 {
845   g_return_if_fail (src_value != NULL);
846   g_return_if_fail (dest_value != NULL);
847
848   dest_value->data[0].v_pointer =
849     gst_caps_to_string (src_value->data[0].v_pointer);
850 }
851
852 static void _gst_caps_value_init (GValue *value)
853 {
854   value->data[0].v_pointer = gst_caps_new_empty();
855 }
856
857 static void _gst_caps_value_free (GValue *value)
858 {
859   if (value->data[0].v_pointer) gst_caps_free (value->data[0].v_pointer);
860 }
861
862 static void _gst_caps_value_copy (const GValue *src, GValue *dest)
863 {
864   if (dest->data[0].v_pointer) {
865     gst_caps_free (dest->data[0].v_pointer);
866   }
867   if (src->data[0].v_pointer) {
868     dest->data[0].v_pointer = gst_caps_copy (src->data[0].v_pointer);
869   } else {
870     dest->data[0].v_pointer = NULL;
871   }
872 }
873
874 static gpointer _gst_caps_value_peek_pointer (const GValue *value)
875 {
876   return value->data[0].v_pointer;
877 }
878
879 /* fixate utility functions */
880
881 gboolean gst_caps_structure_fixate_field_nearest_int (GstStructure *structure,
882     const char *field_name, int target)
883 {
884   const GValue *value;
885
886   g_return_val_if_fail(gst_structure_has_field (structure, field_name), FALSE);
887
888   value = gst_structure_get_value (structure, field_name);
889
890   if (G_VALUE_TYPE (value) == G_TYPE_INT) {
891     /* already fixed */
892     return FALSE;
893   } else if (G_VALUE_TYPE (value) == GST_TYPE_INT_RANGE) {
894     int x;
895     x = gst_value_get_int_range_min (value);
896     if (target < x) target = x;
897     x = gst_value_get_int_range_max (value);
898     if (target > x) target = x;
899     gst_structure_set (structure, field_name, G_TYPE_INT, target, NULL);
900     return TRUE;
901   } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
902     const GValue *list_value;
903     int i, n;
904     int best = 0;
905     int best_index = -1;
906
907     n = gst_value_list_get_size (value);
908     for(i=0;i<n;i++){
909       list_value = gst_value_list_get_value (value, i);
910       if (G_VALUE_TYPE (list_value) == G_TYPE_INT) {
911         int x = g_value_get_int (list_value);
912         if (best_index == -1 || (ABS(target-x) < ABS(best-x))) {
913           best_index = i;
914           best = x;
915         }
916       }
917     }
918     if(best_index != -1) {
919       gst_structure_set (structure, field_name, G_TYPE_INT, best, NULL);
920       return TRUE;
921     }
922     return FALSE;
923   }
924
925   return FALSE;
926 }
927
928 gboolean gst_caps_structure_fixate_field_nearest_double (GstStructure
929     *structure, const char *field_name, double target)
930 {
931   const GValue *value;
932
933   g_return_val_if_fail(gst_structure_has_field (structure, field_name), FALSE);
934
935   value = gst_structure_get_value (structure, field_name);
936
937   if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE) {
938     /* already fixed */
939     return FALSE;
940   } else if (G_VALUE_TYPE (value) == GST_TYPE_DOUBLE_RANGE) {
941     double x;
942     x = gst_value_get_double_range_min (value);
943     if (target < x) target = x;
944     x = gst_value_get_double_range_max (value);
945     if (target > x) target = x;
946     gst_structure_set (structure, field_name, G_TYPE_DOUBLE, target, NULL);
947     return TRUE;
948   } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
949     const GValue *list_value;
950     int i, n;
951     double best = 0;
952     int best_index = -1;
953
954     n = gst_value_list_get_size (value);
955     for(i=0;i<n;i++){
956       list_value = gst_value_list_get_value (value, i);
957       if (G_VALUE_TYPE (list_value) == G_TYPE_DOUBLE) {
958         double x = g_value_get_double (list_value);
959         if (best_index == -1 || (ABS(target-x) < ABS(best-x))) {
960           best_index = i;
961           best = x;
962         }
963       }
964     }
965     if(best_index != -1) {
966       gst_structure_set (structure, field_name, G_TYPE_DOUBLE, best, NULL);
967       return TRUE;
968     }
969     return FALSE;
970   }
971
972   return FALSE;
973
974 }
975