2 * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
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.
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.
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.
27 #define CAPS_POISON(caps) do{ \
28 GstCaps *_newcaps = gst_caps_copy (caps); \
29 gst_caps_free(caps); \
32 #define STRUCTURE_POISON(structure) do{ \
33 GstStructure *_newstruct = gst_structure_copy (structure); \
34 gst_structure_free(structure); \
35 structure = _newstruct; \
39 static void _gst_caps_transform_to_string (const GValue *src_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,
51 void _gst_caps_initialize (void)
53 static const GTypeValueTable type_value_table = {
57 _gst_caps_value_peek_pointer,
63 static const GTypeInfo caps2_info = {
76 _gst_caps_type = g_type_register_static (G_TYPE_BOXED, "GstCaps",
79 g_value_register_transform_func (_gst_caps_type, G_TYPE_STRING,
80 _gst_caps_transform_to_string);
83 GType gst_caps_get_type (void)
85 return _gst_caps_type;
88 /* creation/deletion */
89 GstCaps *gst_caps_new_empty (void)
91 GstCaps *caps = g_new0(GstCaps, 1);
93 caps->type = _gst_caps_type;
94 caps->structs = g_ptr_array_new();
99 GstCaps *gst_caps_new_any (void)
101 GstCaps *caps = g_new0(GstCaps, 1);
103 caps->type = _gst_caps_type;
104 caps->structs = g_ptr_array_new();
105 caps->flags = GST_CAPS_FLAGS_ANY;
110 GstCaps *gst_caps_new_simple (const char *media_type, const char *fieldname,
114 GstStructure *structure;
117 caps = g_new0(GstCaps, 1);
118 caps->type = _gst_caps_type;
119 caps->structs = g_ptr_array_new();
121 va_start (var_args, fieldname);
122 structure = gst_structure_new_valist (media_type, fieldname, var_args);
125 gst_caps_append_structure (caps, structure);
130 GstCaps *gst_caps_new_full (GstStructure *struct1, ...)
135 va_start (var_args, struct1);
136 caps = gst_caps_new_full_valist (struct1, var_args);
142 GstCaps *gst_caps_new_full_valist (GstStructure *structure,
147 caps = g_new0(GstCaps, 1);
148 caps->type = _gst_caps_type;
149 caps->structs = g_ptr_array_new();
152 gst_caps_append_structure (caps, structure);
153 structure = va_arg (var_args, GstStructure *);
159 GstCaps *gst_caps_copy (const GstCaps *caps)
162 GstStructure *structure;
165 g_return_val_if_fail(caps != NULL, NULL);
167 newcaps = g_new0(GstCaps, 1);
168 newcaps->type = _gst_caps_type;
169 newcaps->flags = caps->flags;
170 newcaps->structs = g_ptr_array_new();
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));
180 void gst_caps_free (GstCaps *caps)
182 GstStructure *structure;
185 g_return_if_fail(caps != NULL);
187 for(i=0;i<caps->structs->len;i++){
188 structure = gst_caps_get_structure (caps, i);
189 gst_structure_free (structure);
191 g_ptr_array_free(caps->structs, TRUE);
193 memset (caps, 0xff, sizeof(GstCaps));
198 const GstCaps *gst_static_caps_get (GstStaticCaps *static_caps)
200 GstCaps *caps = (GstCaps *)static_caps;
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);
209 g_critical ("Could not convert static caps \"%s\"", static_caps->string);
217 void gst_caps_append (GstCaps *caps1, GstCaps *caps2)
219 GstStructure *structure;
222 g_return_if_fail (caps1 != NULL);
223 g_return_if_fail (caps2 != NULL);
228 for(i=0;i<caps2->structs->len;i++){
229 structure = gst_caps_get_structure (caps2, i);
230 gst_caps_append_structure (caps1, structure);
232 g_ptr_array_free(caps2->structs, TRUE);
234 memset (caps2, 0xff, sizeof(GstCaps));
239 void gst_caps_append_structure (GstCaps *caps, GstStructure *structure)
241 g_return_if_fail(caps != NULL);
245 STRUCTURE_POISON (structure);
247 g_ptr_array_add (caps->structs, structure);
251 GstCaps *gst_caps_split_one (GstCaps *caps)
254 g_critical ("unimplemented");
259 int gst_caps_get_size (const GstCaps *caps)
261 g_return_val_if_fail (caps != NULL, 0);
263 return caps->structs->len;
266 GstStructure *gst_caps_get_structure (const GstCaps *caps, int index)
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);
272 return g_ptr_array_index(caps->structs, index);
275 GstCaps *gst_caps_copy_1 (const GstCaps *caps)
278 GstStructure *structure;
280 g_return_val_if_fail(caps != NULL, NULL);
282 newcaps = g_new0(GstCaps, 1);
283 newcaps->type = _gst_caps_type;
284 newcaps->flags = caps->flags;
285 newcaps->structs = g_ptr_array_new();
287 if (caps->structs->len > 0){
288 structure = gst_caps_get_structure (caps, 0);
289 gst_caps_append_structure (newcaps, gst_structure_copy(structure));
295 void gst_caps_set_simple (GstCaps *caps, char *field, ...)
297 GstStructure *structure;
300 g_return_if_fail (caps != NULL);
301 g_return_if_fail (caps->structs->len == 1);
303 structure = gst_caps_get_structure (caps, 0);
305 va_start (var_args, field);
306 gst_structure_set_valist (structure, field, var_args);
310 void gst_caps_set_simple_valist (GstCaps *caps, char *field, va_list varargs)
312 GstStructure *structure;
314 g_return_if_fail (caps != NULL);
315 g_return_if_fail (caps->structs->len != 1);
317 structure = gst_caps_get_structure (caps, 0);
319 gst_structure_set_valist (structure, field, varargs);
323 gboolean gst_caps_is_any (const GstCaps *caps)
325 g_return_val_if_fail(caps != NULL, FALSE);
327 return (caps->flags & GST_CAPS_FLAGS_ANY);
330 gboolean gst_caps_is_empty (const GstCaps *caps)
332 g_return_val_if_fail(caps != NULL, FALSE);
334 if (caps->flags & GST_CAPS_FLAGS_ANY) return FALSE;
336 return (caps->structs == NULL) || (caps->structs->len == 0);
339 gboolean gst_caps_is_chained (const GstCaps *caps)
341 g_return_val_if_fail(caps != NULL, FALSE);
343 return (caps->structs->len > 1);
347 _gst_caps_is_fixed_foreach (GQuark field_id, GValue *value, gpointer unused)
349 GType type = G_VALUE_TYPE (value);
350 if (G_TYPE_IS_FUNDAMENTAL (type)) return TRUE;
351 if (type == GST_TYPE_FOURCC) return TRUE;
355 gboolean gst_caps_is_fixed (const GstCaps *caps)
357 GstStructure *structure;
359 g_return_val_if_fail(caps != NULL, FALSE);
361 if (caps->structs->len != 1) return FALSE;
363 structure = gst_caps_get_structure (caps, 0);
365 return gst_structure_foreach (structure, _gst_caps_is_fixed_foreach, NULL);
369 _gst_structure_is_equal_foreach (GQuark field_id,
370 GValue *val2, gpointer data)
372 GstStructure *struct1 = (GstStructure *) data;
373 const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
375 if (val1 == NULL) return FALSE;
376 if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
383 gboolean gst_caps_is_equal_fixed (const GstCaps *caps1, const GstCaps *caps2)
385 GstStructure *struct1, *struct2;
387 g_return_val_if_fail (gst_caps_is_fixed(caps1), FALSE);
388 g_return_val_if_fail (gst_caps_is_fixed(caps2), FALSE);
390 struct1 = gst_caps_get_structure (caps1, 0);
391 struct2 = gst_caps_get_structure (caps2, 0);
393 if (struct1->name != struct2->name) {
396 if (struct1->fields->len != struct2->fields->len) {
400 return gst_structure_foreach (struct1, _gst_structure_is_equal_foreach,
405 _gst_structure_field_has_compatible (GQuark field_id,
406 GValue *val2, gpointer data)
409 GstStructure *struct1 = (GstStructure *) data;
410 const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
412 if (val1 == NULL) return FALSE;
413 if (gst_value_intersect (&dest, val1, val2)) {
414 g_value_unset (&dest);
422 _gst_cap_is_always_compatible (const GstStructure *struct1,
423 const GstStructure *struct2)
425 if(struct1->name != struct2->name){
429 /* the reversed order is important */
430 return gst_structure_foreach ((GstStructure *) struct2,
431 _gst_structure_field_has_compatible, (gpointer) struct1);
435 _gst_caps_cap_is_always_compatible (const GstStructure *struct1,
436 const GstCaps *caps2)
440 for(i=0;i<caps2->structs->len;i++){
441 GstStructure *struct2 = gst_caps_get_structure (caps2, i);
443 if (_gst_cap_is_always_compatible (struct1, struct2)) {
452 gst_caps_is_always_compatible (const GstCaps *caps1, const GstCaps *caps2)
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);
462 if (gst_caps_is_any (caps2))
464 if (gst_caps_is_any (caps1))
467 for(i=0;i<caps1->structs->len;i++) {
468 GstStructure *struct1 = gst_caps_get_structure (caps1, i);
470 if (_gst_caps_cap_is_always_compatible(struct1, caps2) == FALSE){
481 const GstStructure *intersect;
486 gst_caps_structure_intersect_field (GQuark id, GValue *val1, gpointer data)
488 IntersectData *idata = (IntersectData *) data;
489 GValue dest_value = { 0 };
490 const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
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);
506 static GstStructure *gst_caps_structure_intersect (const GstStructure *struct1,
507 const GstStructure *struct2)
511 g_return_val_if_fail(struct1 != NULL, NULL);
512 g_return_val_if_fail(struct2 != NULL, NULL);
514 if (struct1->name != struct2->name) return NULL;
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))
523 data.intersect = struct1;
524 data.first_run = FALSE;
525 if (!gst_structure_foreach ((GstStructure *) struct2,
526 gst_caps_structure_intersect_field, &data))
532 gst_structure_free (data.dest);
537 static GstStructure *gst_caps_structure_union (const GstStructure *struct1,
538 const GstStructure *struct2)
542 const GstStructureField *field1;
543 const GstStructureField *field2;
546 /* FIXME this doesn't actually work */
548 if (struct1->name != struct2->name) return NULL;
550 dest = gst_structure_id_empty_new (struct1->name);
552 for(i=0;i<struct1->fields->len;i++){
553 GValue dest_value = { 0 };
555 field1 = GST_STRUCTURE_FIELD (struct1, i);
556 field2 = gst_structure_id_get_field (struct2, field1->name);
558 if (field2 == NULL) {
561 if (gst_value_union (&dest_value, &field1->value, &field2->value)) {
562 gst_structure_set_value (dest, g_quark_to_string(field1->name),
565 ret = gst_value_compare (&field1->value, &field2->value);
575 GstCaps *gst_caps_intersect (const GstCaps *caps1, const GstCaps *caps2)
578 GstStructure *struct1;
579 GstStructure *struct2;
583 g_return_val_if_fail (caps1 != NULL, NULL);
584 g_return_val_if_fail (caps2 != NULL, NULL);
586 if (gst_caps_is_empty (caps1) || gst_caps_is_empty (caps2)){
587 return gst_caps_new_empty ();
589 if (gst_caps_is_any (caps1)) return gst_caps_copy (caps2);
590 if (gst_caps_is_any (caps2)) return gst_caps_copy (caps1);
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;
598 struct2 = gst_caps_get_structure (caps2, j);
599 istruct = gst_caps_structure_intersect (struct1, struct2);
601 gst_caps_append_structure(dest, istruct);
606 caps = gst_caps_simplify (dest);
607 gst_caps_free (dest);
615 GstCaps *gst_caps_union (const GstCaps *caps1, const GstCaps *caps2)
620 dest1 = gst_caps_copy (caps1);
621 dest2 = gst_caps_copy (caps2);
622 gst_caps_append (dest1, dest2);
625 /* FIXME: need a simplify function */
630 typedef struct _NormalizeForeach {
632 GstStructure *structure;
636 _gst_caps_normalize_foreach (GQuark field_id, GValue *value, gpointer ptr)
638 NormalizeForeach *nf = (NormalizeForeach *) ptr;
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);
647 gst_structure_id_set_value (structure, field_id, v);
648 gst_caps_append_structure (nf->caps, structure);
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);
660 GstCaps *gst_caps_normalize (const GstCaps *caps)
666 g_return_val_if_fail(caps != NULL, NULL);
668 newcaps = gst_caps_copy (caps);
671 for(i=0;i<newcaps->structs->len;i++){
672 nf.structure = gst_caps_get_structure (newcaps, i);
674 while (!gst_structure_foreach (nf.structure, _gst_caps_normalize_foreach,
682 simplify_foreach (GQuark field_id, GValue *value, gpointer user_data)
684 GstStructure *s2 = (GstStructure *) user_data;
687 v2 = gst_structure_id_get_value (s2, field_id);
688 if (v2 == NULL) return FALSE;
690 if (gst_value_compare (value, v2) == GST_VALUE_EQUAL) return TRUE;
695 gst_caps_structure_simplify (GstStructure *struct1, const GstStructure *struct2)
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;
702 return gst_structure_foreach (struct1, simplify_foreach, (void *)struct2);
705 GstCaps *gst_caps_simplify (const GstCaps *caps)
710 GstStructure *structure;
711 GstStructure *struct2;
713 if (gst_caps_get_size (caps) < 2) {
714 return gst_caps_copy (caps);
717 newcaps = gst_caps_new_empty ();
719 for(i=0;i<gst_caps_get_size (caps);i++){
720 structure = gst_caps_get_structure (caps, i);
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)) {
728 if (j==gst_caps_get_size (newcaps)) {
729 gst_caps_append_structure (newcaps, gst_structure_copy(structure));
736 #ifndef GST_DISABLE_LOADSAVE
737 xmlNodePtr gst_caps_save_thyself (const GstCaps *caps, xmlNodePtr parent)
743 GstCaps *gst_caps_load_thyself (xmlNodePtr parent)
751 void gst_caps_replace (GstCaps **caps, GstCaps *newcaps)
754 if (newcaps) CAPS_POISON (newcaps);
756 if (*caps) gst_caps_free(*caps);
760 gchar *gst_caps_to_string (const GstCaps *caps)
763 GstStructure *structure;
766 /* FIXME does this leak? */
769 return g_strdup("NULL");
771 if(gst_caps_is_any(caps)){
772 return g_strdup("ANY");
774 if(gst_caps_is_empty(caps)){
775 return g_strdup("EMPTY");
777 s = g_string_new("");
778 structure = gst_caps_get_structure (caps, 0);
779 g_string_append(s, gst_structure_to_string(structure));
781 for(i=1;i<caps->structs->len;i++){
782 structure = gst_caps_get_structure (caps, i);
784 g_string_append(s, "; ");
785 g_string_append(s, gst_structure_to_string(structure));
788 return g_string_free(s, FALSE);
791 static gboolean _gst_caps_from_string_inplace (GstCaps *caps,
794 GstStructure *structure;
797 if (strcmp("ANY", string)==0) {
798 caps->flags = GST_CAPS_FLAGS_ANY;
801 if (strcmp("NONE", string)==0) {
805 structure = gst_structure_from_string(string, &s);
806 if (structure == NULL) {
809 gst_caps_append_structure (caps, structure);
813 while (g_ascii_isspace(*s))s++;
814 structure = gst_structure_from_string(s, &s);
815 if (structure == NULL) {
818 gst_caps_append_structure (caps, structure);
819 while (g_ascii_isspace(*s))s++;
829 GstCaps *gst_caps_from_string (const gchar *string)
833 caps = gst_caps_new_empty();
834 if (_gst_caps_from_string_inplace (caps, string)) {
837 gst_caps_free (caps);
842 static void _gst_caps_transform_to_string (const GValue *src_value,
845 g_return_if_fail (src_value != NULL);
846 g_return_if_fail (dest_value != NULL);
848 dest_value->data[0].v_pointer =
849 gst_caps_to_string (src_value->data[0].v_pointer);
852 static void _gst_caps_value_init (GValue *value)
854 value->data[0].v_pointer = gst_caps_new_empty();
857 static void _gst_caps_value_free (GValue *value)
859 if (value->data[0].v_pointer) gst_caps_free (value->data[0].v_pointer);
862 static void _gst_caps_value_copy (const GValue *src, GValue *dest)
864 if (dest->data[0].v_pointer) {
865 gst_caps_free (dest->data[0].v_pointer);
867 if (src->data[0].v_pointer) {
868 dest->data[0].v_pointer = gst_caps_copy (src->data[0].v_pointer);
870 dest->data[0].v_pointer = NULL;
874 static gpointer _gst_caps_value_peek_pointer (const GValue *value)
876 return value->data[0].v_pointer;
879 /* fixate utility functions */
881 gboolean gst_caps_structure_fixate_field_nearest_int (GstStructure *structure,
882 const char *field_name, int target)
886 g_return_val_if_fail(gst_structure_has_field (structure, field_name), FALSE);
888 value = gst_structure_get_value (structure, field_name);
890 if (G_VALUE_TYPE (value) == G_TYPE_INT) {
893 } else if (G_VALUE_TYPE (value) == GST_TYPE_INT_RANGE) {
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);
901 } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
902 const GValue *list_value;
907 n = gst_value_list_get_size (value);
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))) {
918 if(best_index != -1) {
919 gst_structure_set (structure, field_name, G_TYPE_INT, best, NULL);
928 gboolean gst_caps_structure_fixate_field_nearest_double (GstStructure
929 *structure, const char *field_name, double target)
933 g_return_val_if_fail(gst_structure_has_field (structure, field_name), FALSE);
935 value = gst_structure_get_value (structure, field_name);
937 if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE) {
940 } else if (G_VALUE_TYPE (value) == GST_TYPE_DOUBLE_RANGE) {
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);
948 } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
949 const GValue *list_value;
954 n = gst_value_list_get_size (value);
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))) {
965 if(best_index != -1) {
966 gst_structure_set (structure, field_name, G_TYPE_DOUBLE, best, NULL);