93 } \ |
93 } \ |
94 } G_STMT_END |
94 } G_STMT_END |
95 #define IS_WRITABLE(caps) \ |
95 #define IS_WRITABLE(caps) \ |
96 (g_atomic_int_get (&(caps)->refcount) == 1) |
96 (g_atomic_int_get (&(caps)->refcount) == 1) |
97 |
97 |
98 #if GLIB_CHECK_VERSION (2, 10, 0) |
98 /* quick way to get a caps structure at an index without doing a type or array |
99 #define ALLOC_CAPS() g_slice_new (GstCaps) |
99 * length check */ |
100 #define FREE_CAPS(caps) g_slice_free (GstCaps, caps) |
100 #define gst_caps_get_structure_unchecked(caps, index) \ |
101 #else |
101 ((GstStructure *)g_ptr_array_index ((caps)->structs, (index))) |
102 #define ALLOC_CAPS() g_new (GstCaps, 1) |
102 |
103 #define FREE_CAPS(caps) g_free (caps) |
|
104 #endif |
|
105 |
103 |
106 /* lock to protect multiple invocations of static caps to caps conversion */ |
104 /* lock to protect multiple invocations of static caps to caps conversion */ |
107 G_LOCK_DEFINE_STATIC (static_caps_lock); |
105 G_LOCK_DEFINE_STATIC (static_caps_lock); |
108 |
106 |
109 static void gst_caps_transform_to_string (const GValue * src_value, |
107 static void gst_caps_transform_to_string (const GValue * src_value, |
302 GstCaps * |
300 GstCaps * |
303 gst_caps_copy (const GstCaps * caps) |
301 gst_caps_copy (const GstCaps * caps) |
304 { |
302 { |
305 GstCaps *newcaps; |
303 GstCaps *newcaps; |
306 GstStructure *structure; |
304 GstStructure *structure; |
307 guint i; |
305 guint i, n; |
308 |
306 |
309 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
307 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
310 |
308 |
311 newcaps = gst_caps_new_empty (); |
309 newcaps = gst_caps_new_empty (); |
312 newcaps->flags = caps->flags; |
310 newcaps->flags = caps->flags; |
313 |
311 n = caps->structs->len; |
314 for (i = 0; i < caps->structs->len; i++) { |
312 |
315 structure = gst_caps_get_structure (caps, i); |
313 for (i = 0; i < n; i++) { |
|
314 structure = gst_caps_get_structure_unchecked (caps, i); |
316 gst_caps_append_structure (newcaps, gst_structure_copy (structure)); |
315 gst_caps_append_structure (newcaps, gst_structure_copy (structure)); |
317 } |
316 } |
318 |
317 |
319 return newcaps; |
318 return newcaps; |
320 } |
319 } |
321 |
320 |
322 static void |
321 static void |
323 _gst_caps_free (GstCaps * caps) |
322 _gst_caps_free (GstCaps * caps) |
324 { |
323 { |
325 GstStructure *structure; |
324 GstStructure *structure; |
326 guint i; |
325 guint i, len; |
327 |
326 |
328 /* The refcount must be 0, but since we're only called by gst_caps_unref, |
327 /* The refcount must be 0, but since we're only called by gst_caps_unref, |
329 * don't bother testing. */ |
328 * don't bother testing. */ |
330 |
329 len = caps->structs->len; |
331 for (i = 0; i < caps->structs->len; i++) { |
330 for (i = 0; i < len; i++) { |
332 structure = (GstStructure *) gst_caps_get_structure (caps, i); |
331 structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i); |
333 gst_structure_set_parent_refcount (structure, NULL); |
332 gst_structure_set_parent_refcount (structure, NULL); |
334 gst_structure_free (structure); |
333 gst_structure_free (structure); |
335 } |
334 } |
336 g_ptr_array_free (caps->structs, TRUE); |
335 g_ptr_array_free (caps->structs, TRUE); |
337 #ifdef USE_POISONING |
336 #ifdef USE_POISONING |
339 #endif |
338 #endif |
340 |
339 |
341 #ifdef DEBUG_REFCOUNT |
340 #ifdef DEBUG_REFCOUNT |
342 GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps); |
341 GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps); |
343 #endif |
342 #endif |
344 FREE_CAPS (caps); |
343 g_slice_free (GstCaps, caps); |
345 } |
344 } |
346 |
345 |
347 /** |
346 /** |
348 * gst_caps_make_writable: |
347 * gst_caps_make_writable: |
349 * @caps: the #GstCaps to make writable |
348 * @caps: the #GstCaps to make writable |
511 temp.flags = 0; |
510 temp.flags = 0; |
512 temp.structs = g_ptr_array_new (); |
511 temp.structs = g_ptr_array_new (); |
513 |
512 |
514 /* initialize the caps to a refcount of 1 so the caps can be writable for |
513 /* initialize the caps to a refcount of 1 so the caps can be writable for |
515 * the next statement */ |
514 * the next statement */ |
516 gst_atomic_int_set (&temp.refcount, 1); |
515 temp.refcount = 1; |
517 |
516 |
518 /* convert to string */ |
517 /* convert to string */ |
519 if (G_UNLIKELY (!gst_caps_from_string_inplace (&temp, string))) |
518 if (G_UNLIKELY (!gst_caps_from_string_inplace (&temp, string))) |
520 g_critical ("Could not convert static caps \"%s\"", string); |
519 g_critical ("Could not convert static caps \"%s\"", string); |
521 |
520 |
522 /* now copy stuff over to the real caps. */ |
521 /* now copy stuff over to the real caps. */ |
523 caps->type = temp.type; |
522 caps->type = temp.type; |
524 caps->flags = temp.flags; |
523 caps->flags = temp.flags; |
525 caps->structs = temp.structs; |
524 caps->structs = temp.structs; |
526 /* and bump the refcount so other threads can now read */ |
525 /* and bump the refcount so other threads can now read */ |
527 gst_atomic_int_set (&caps->refcount, 1); |
526 g_atomic_int_set (&caps->refcount, 1); |
528 |
527 |
529 GST_CAT_LOG (GST_CAT_CAPS, "created %p", static_caps); |
528 GST_CAT_LOG (GST_CAT_CAPS, "created %p", static_caps); |
530 done: |
529 done: |
531 G_UNLOCK (static_caps_lock); |
530 G_UNLOCK (static_caps_lock); |
532 } |
531 } |
576 gpointer user_data) |
575 gpointer user_data) |
577 { |
576 { |
578 GstStructure *subtract_from = user_data; |
577 GstStructure *subtract_from = user_data; |
579 GValue subtraction = { 0, }; |
578 GValue subtraction = { 0, }; |
580 const GValue *other; |
579 const GValue *other; |
581 gint res; |
580 |
582 |
581 if (!(other = gst_structure_id_get_value (subtract_from, field_id))) |
583 other = gst_structure_id_get_value (subtract_from, field_id); |
|
584 if (!other) { |
|
585 /* field is missing in one set */ |
582 /* field is missing in one set */ |
586 return FALSE; |
583 return FALSE; |
587 } |
584 |
|
585 /* equal values are subset */ |
|
586 if (gst_value_compare (other, value) == GST_VALUE_EQUAL) |
|
587 return TRUE; |
|
588 |
588 /* |
589 /* |
|
590 * 1 - [1,2] = empty |
|
591 * -> !subset |
|
592 * |
589 * [1,2] - 1 = 2 |
593 * [1,2] - 1 = 2 |
590 * 1 - [1,2] = ??? |
594 * -> 1 - [1,2] = empty |
|
595 * -> subset |
|
596 * |
|
597 * [1,3] - [1,2] = 3 |
|
598 * -> [1,2] - [1,3] = empty |
|
599 * -> subset |
|
600 * |
|
601 * {1,2} - {1,3} = 2 |
|
602 * -> {1,3} - {1,2} = 3 |
|
603 * -> !subset |
|
604 * |
|
605 * First caps subtraction needs to return a non-empty set, second |
|
606 * subtractions needs to give en empty set. |
591 */ |
607 */ |
592 if (!gst_value_subtract (&subtraction, other, value)) { |
608 if (gst_value_subtract (&subtraction, other, value)) { |
593 /* empty result -> values are the same, or first was a value and |
609 g_value_unset (&subtraction); |
594 * second was a list |
610 /* !empty result, swapping must be empty */ |
595 * verify that result is empty by swapping args */ |
611 if (!gst_value_subtract (&subtraction, value, other)) |
596 if (!gst_value_subtract (&subtraction, value, other)) { |
|
597 return TRUE; |
612 return TRUE; |
598 } |
613 |
599 g_value_unset (&subtraction); |
614 g_value_unset (&subtraction); |
600 return FALSE; |
615 } |
601 } |
616 return FALSE; |
602 |
|
603 res = gst_value_compare (&subtraction, other); |
|
604 g_value_unset (&subtraction); |
|
605 |
|
606 if (res == GST_VALUE_EQUAL) { |
|
607 /* value was empty ? */ |
|
608 return FALSE; |
|
609 } else { |
|
610 return TRUE; |
|
611 } |
|
612 } |
617 } |
613 |
618 |
614 static gboolean |
619 static gboolean |
615 gst_caps_structure_is_subset (const GstStructure * minuend, |
620 gst_caps_structure_is_subset (const GstStructure * minuend, |
616 const GstStructure * subtrahend) |
621 const GstStructure * subtrahend) |
650 g_return_if_fail (IS_WRITABLE (caps2)); |
655 g_return_if_fail (IS_WRITABLE (caps2)); |
651 |
656 |
652 #ifdef USE_POISONING |
657 #ifdef USE_POISONING |
653 CAPS_POISON (caps2); |
658 CAPS_POISON (caps2); |
654 #endif |
659 #endif |
655 if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2)) { |
660 if (G_UNLIKELY (gst_caps_is_any (caps1) || gst_caps_is_any (caps2))) { |
656 /* FIXME: this leaks */ |
661 /* FIXME: this leaks */ |
657 caps1->flags |= GST_CAPS_FLAGS_ANY; |
662 caps1->flags |= GST_CAPS_FLAGS_ANY; |
658 for (i = caps2->structs->len - 1; i >= 0; i--) { |
663 for (i = caps2->structs->len - 1; i >= 0; i--) { |
659 structure = gst_caps_remove_and_get_structure (caps2, i); |
664 structure = gst_caps_remove_and_get_structure (caps2, i); |
660 gst_structure_free (structure); |
665 gst_structure_free (structure); |
661 } |
666 } |
662 } else { |
667 } else { |
663 int len = caps2->structs->len; |
668 for (i = caps2->structs->len; i; i--) { |
664 |
|
665 for (i = 0; i < len; i++) { |
|
666 structure = gst_caps_remove_and_get_structure (caps2, 0); |
669 structure = gst_caps_remove_and_get_structure (caps2, 0); |
667 gst_caps_append_structure (caps1, structure); |
670 gst_caps_append_structure (caps1, structure); |
668 } |
671 } |
669 } |
672 } |
670 gst_caps_unref (caps2); /* guaranteed to free it */ |
673 gst_caps_unref (caps2); /* guaranteed to free it */ |
698 g_return_if_fail (IS_WRITABLE (caps2)); |
701 g_return_if_fail (IS_WRITABLE (caps2)); |
699 |
702 |
700 #ifdef USE_POISONING |
703 #ifdef USE_POISONING |
701 CAPS_POISON (caps2); |
704 CAPS_POISON (caps2); |
702 #endif |
705 #endif |
703 if (gst_caps_is_any (caps1)) { |
706 if (G_UNLIKELY (gst_caps_is_any (caps1))) { |
704 for (i = caps2->structs->len - 1; i >= 0; i--) { |
707 for (i = caps2->structs->len - 1; i >= 0; i--) { |
705 structure = gst_caps_remove_and_get_structure (caps2, i); |
708 structure = gst_caps_remove_and_get_structure (caps2, i); |
706 gst_structure_free (structure); |
709 gst_structure_free (structure); |
707 } |
710 } |
708 } else if (gst_caps_is_any (caps2)) { |
711 } else if (G_UNLIKELY (gst_caps_is_any (caps2))) { |
709 caps1->flags |= GST_CAPS_FLAGS_ANY; |
712 caps1->flags |= GST_CAPS_FLAGS_ANY; |
710 for (i = caps1->structs->len - 1; i >= 0; i--) { |
713 for (i = caps1->structs->len - 1; i >= 0; i--) { |
711 structure = gst_caps_remove_and_get_structure (caps1, i); |
714 structure = gst_caps_remove_and_get_structure (caps1, i); |
712 gst_structure_free (structure); |
715 gst_structure_free (structure); |
713 } |
716 } |
714 } else { |
717 } else { |
715 int len = caps2->structs->len; |
718 for (i = caps2->structs->len; i; i--) { |
716 |
|
717 for (i = 0; i < len; i++) { |
|
718 structure = gst_caps_remove_and_get_structure (caps2, 0); |
719 structure = gst_caps_remove_and_get_structure (caps2, 0); |
719 gst_caps_merge_structure (caps1, structure); |
720 gst_caps_merge_structure (caps1, structure); |
720 } |
721 } |
721 /* this is too naive |
722 /* this is too naive |
722 GstCaps *com = gst_caps_intersect (caps1, caps2); |
723 GstCaps *com = gst_caps_intersect (caps1, caps2); |
815 STRUCTURE_POISON (structure); |
816 STRUCTURE_POISON (structure); |
816 #endif |
817 #endif |
817 #endif |
818 #endif |
818 /* check each structure */ |
819 /* check each structure */ |
819 for (i = caps->structs->len - 1; i >= 0; i--) { |
820 for (i = caps->structs->len - 1; i >= 0; i--) { |
820 structure1 = gst_caps_get_structure (caps, i); |
821 structure1 = gst_caps_get_structure_unchecked (caps, i); |
821 /* if structure is a subset of structure1, then skip it */ |
822 /* if structure is a subset of structure1, then skip it */ |
822 if (gst_caps_structure_is_subset (structure1, structure)) { |
823 if (gst_caps_structure_is_subset (structure1, structure)) { |
823 unique = FALSE; |
824 unique = FALSE; |
824 break; |
825 break; |
825 } |
826 } |
863 * returns it. |
864 * returns it. |
864 * |
865 * |
865 * WARNING: This function takes a const GstCaps *, but returns a |
866 * WARNING: This function takes a const GstCaps *, but returns a |
866 * non-const GstStructure *. This is for programming convenience -- |
867 * non-const GstStructure *. This is for programming convenience -- |
867 * the caller should be aware that structures inside a constant |
868 * the caller should be aware that structures inside a constant |
868 * #GstCaps should not be modified. |
869 * #GstCaps should not be modified. However, if you know the caps |
|
870 * are writable, either because you have just copied them or made |
|
871 * them writable with gst_caps_make_writable(), you may modify the |
|
872 * structure returned in the usual way, e.g. with functions like |
|
873 * gst_structure_set_simple(). |
|
874 * |
|
875 * You do not need to free or unref the structure returned, it |
|
876 * belongs to the #GstCaps. |
869 * |
877 * |
870 * Returns: a pointer to the #GstStructure corresponding to @index |
878 * Returns: a pointer to the #GstStructure corresponding to @index |
871 */ |
879 */ |
872 #ifdef __SYMBIAN32__ |
880 #ifdef __SYMBIAN32__ |
873 EXPORT_C |
881 EXPORT_C |
877 gst_caps_get_structure (const GstCaps * caps, guint index) |
885 gst_caps_get_structure (const GstCaps * caps, guint index) |
878 { |
886 { |
879 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
887 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
880 g_return_val_if_fail (index < caps->structs->len, NULL); |
888 g_return_val_if_fail (index < caps->structs->len, NULL); |
881 |
889 |
882 return g_ptr_array_index (caps->structs, index); |
890 return gst_caps_get_structure_unchecked (caps, index); |
883 } |
891 } |
884 |
892 |
885 /** |
893 /** |
886 * gst_caps_copy_nth: |
894 * gst_caps_copy_nth: |
887 * @caps: the #GstCaps to copy |
895 * @caps: the #GstCaps to copy |
905 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
913 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
906 |
914 |
907 newcaps = gst_caps_new_empty (); |
915 newcaps = gst_caps_new_empty (); |
908 newcaps->flags = caps->flags; |
916 newcaps->flags = caps->flags; |
909 |
917 |
910 if (caps->structs->len > nth) { |
918 if (G_LIKELY (caps->structs->len > nth)) { |
911 structure = gst_caps_get_structure (caps, nth); |
919 structure = gst_caps_get_structure_unchecked (caps, nth); |
912 gst_caps_append_structure (newcaps, gst_structure_copy (structure)); |
920 gst_caps_append_structure (newcaps, gst_structure_copy (structure)); |
913 } |
921 } |
914 |
922 |
915 return newcaps; |
923 return newcaps; |
916 } |
924 } |
953 #ifdef __SYMBIAN32__ |
961 #ifdef __SYMBIAN32__ |
954 EXPORT_C |
962 EXPORT_C |
955 #endif |
963 #endif |
956 |
964 |
957 void |
965 void |
958 gst_caps_set_simple (GstCaps * caps, char *field, ...) |
966 gst_caps_set_simple (GstCaps * caps, const char *field, ...) |
959 { |
967 { |
960 GstStructure *structure; |
968 GstStructure *structure; |
961 va_list var_args; |
969 va_list var_args; |
962 |
970 |
963 g_return_if_fail (GST_IS_CAPS (caps)); |
971 g_return_if_fail (GST_IS_CAPS (caps)); |
964 g_return_if_fail (caps->structs->len == 1); |
972 g_return_if_fail (caps->structs->len == 1); |
965 g_return_if_fail (IS_WRITABLE (caps)); |
973 g_return_if_fail (IS_WRITABLE (caps)); |
966 |
974 |
967 structure = gst_caps_get_structure (caps, 0); |
975 structure = gst_caps_get_structure_unchecked (caps, 0); |
968 |
976 |
969 va_start (var_args, field); |
977 va_start (var_args, field); |
970 gst_structure_set_valist (structure, field, var_args); |
978 gst_structure_set_valist (structure, field, var_args); |
971 va_end (var_args); |
979 va_end (var_args); |
972 } |
980 } |
984 #ifdef __SYMBIAN32__ |
992 #ifdef __SYMBIAN32__ |
985 EXPORT_C |
993 EXPORT_C |
986 #endif |
994 #endif |
987 |
995 |
988 void |
996 void |
989 gst_caps_set_simple_valist (GstCaps * caps, char *field, va_list varargs) |
997 gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs) |
990 { |
998 { |
991 GstStructure *structure; |
999 GstStructure *structure; |
992 |
1000 |
993 g_return_if_fail (GST_IS_CAPS (caps)); |
1001 g_return_if_fail (GST_IS_CAPS (caps)); |
994 g_return_if_fail (caps->structs->len == 1); |
1002 g_return_if_fail (caps->structs->len == 1); |
995 g_return_if_fail (IS_WRITABLE (caps)); |
1003 g_return_if_fail (IS_WRITABLE (caps)); |
996 |
1004 |
997 structure = gst_caps_get_structure (caps, 0); |
1005 structure = gst_caps_get_structure_unchecked (caps, 0); |
998 |
1006 |
999 gst_structure_set_valist (structure, field, varargs); |
1007 gst_structure_set_valist (structure, field, varargs); |
1000 } |
1008 } |
1001 |
1009 |
1002 /* tests */ |
1010 /* tests */ |
1073 g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); |
1081 g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); |
1074 |
1082 |
1075 if (caps->structs->len != 1) |
1083 if (caps->structs->len != 1) |
1076 return FALSE; |
1084 return FALSE; |
1077 |
1085 |
1078 structure = gst_caps_get_structure (caps, 0); |
1086 structure = gst_caps_get_structure_unchecked (caps, 0); |
1079 |
1087 |
1080 return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL); |
1088 return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL); |
1081 } |
1089 } |
1082 |
1090 |
1083 /** |
1091 /** |
1100 GstStructure *struct1, *struct2; |
1108 GstStructure *struct1, *struct2; |
1101 |
1109 |
1102 g_return_val_if_fail (gst_caps_is_fixed (caps1), FALSE); |
1110 g_return_val_if_fail (gst_caps_is_fixed (caps1), FALSE); |
1103 g_return_val_if_fail (gst_caps_is_fixed (caps2), FALSE); |
1111 g_return_val_if_fail (gst_caps_is_fixed (caps2), FALSE); |
1104 |
1112 |
1105 struct1 = gst_caps_get_structure (caps1, 0); |
1113 struct1 = gst_caps_get_structure_unchecked (caps1, 0); |
1106 struct2 = gst_caps_get_structure (caps2, 0); |
1114 struct2 = gst_caps_get_structure_unchecked (caps2, 0); |
1107 |
1115 |
1108 if (struct1->name != struct2->name) { |
1116 if (struct1->name != struct2->name) { |
1109 return FALSE; |
1117 return FALSE; |
1110 } |
1118 } |
1111 if (struct1->fields->len != struct2->fields->len) { |
1119 if (struct1->fields->len != struct2->fields->len) { |
1193 #endif |
1201 #endif |
1194 |
1202 |
1195 gboolean |
1203 gboolean |
1196 gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2) |
1204 gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2) |
1197 { |
1205 { |
|
1206 /* FIXME 0.11: NULL pointers are no valid Caps but indicate an error |
|
1207 * So there should be an assertion that caps1 and caps2 != NULL */ |
|
1208 |
1198 /* NULL <-> NULL is allowed here */ |
1209 /* NULL <-> NULL is allowed here */ |
1199 if (caps1 == caps2) |
1210 if (G_UNLIKELY (caps1 == caps2)) |
1200 return TRUE; |
1211 return TRUE; |
1201 |
1212 |
1202 /* one of them NULL => they are different (can't be both NULL because |
1213 /* one of them NULL => they are different (can't be both NULL because |
1203 * we checked that above) */ |
1214 * we checked that above) */ |
1204 if (caps1 == NULL || caps2 == NULL) |
1215 if (G_UNLIKELY (caps1 == NULL || caps2 == NULL)) |
1205 return FALSE; |
1216 return FALSE; |
1206 |
1217 |
1207 if (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2)) |
1218 if (G_UNLIKELY (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2))) |
1208 return gst_caps_is_equal_fixed (caps1, caps2); |
1219 return gst_caps_is_equal_fixed (caps1, caps2); |
1209 |
1220 |
1210 return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1); |
1221 return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1); |
1211 } |
1222 } |
1212 |
1223 |
1224 { |
1235 { |
1225 IntersectData *idata = (IntersectData *) data; |
1236 IntersectData *idata = (IntersectData *) data; |
1226 GValue dest_value = { 0 }; |
1237 GValue dest_value = { 0 }; |
1227 const GValue *val2 = gst_structure_id_get_value (idata->intersect, id); |
1238 const GValue *val2 = gst_structure_id_get_value (idata->intersect, id); |
1228 |
1239 |
1229 if (val2 == NULL) { |
1240 if (G_UNLIKELY (val2 == NULL)) { |
1230 gst_structure_id_set_value (idata->dest, id, val1); |
1241 gst_structure_id_set_value (idata->dest, id, val1); |
1231 } else if (idata->first_run) { |
1242 } else if (idata->first_run) { |
1232 if (gst_value_intersect (&dest_value, val1, val2)) { |
1243 if (gst_value_intersect (&dest_value, val1, val2)) { |
1233 gst_structure_id_set_value (idata->dest, id, &dest_value); |
1244 gst_structure_id_set_value (idata->dest, id, &dest_value); |
1234 g_value_unset (&dest_value); |
1245 g_value_unset (&dest_value); |
1247 IntersectData data; |
1258 IntersectData data; |
1248 |
1259 |
1249 g_return_val_if_fail (struct1 != NULL, NULL); |
1260 g_return_val_if_fail (struct1 != NULL, NULL); |
1250 g_return_val_if_fail (struct2 != NULL, NULL); |
1261 g_return_val_if_fail (struct2 != NULL, NULL); |
1251 |
1262 |
1252 if (struct1->name != struct2->name) |
1263 if (G_UNLIKELY (struct1->name != struct2->name)) |
1253 return NULL; |
1264 return NULL; |
1254 |
1265 |
1255 data.dest = gst_structure_id_empty_new (struct1->name); |
1266 data.dest = gst_structure_id_empty_new (struct1->name); |
1256 data.intersect = struct2; |
1267 data.intersect = struct2; |
1257 data.first_run = TRUE; |
1268 data.first_run = TRUE; |
1258 if (!gst_structure_foreach ((GstStructure *) struct1, |
1269 if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1, |
1259 gst_caps_structure_intersect_field, &data)) |
1270 gst_caps_structure_intersect_field, &data))) |
1260 goto error; |
1271 goto error; |
1261 |
1272 |
1262 data.intersect = struct1; |
1273 data.intersect = struct1; |
1263 data.first_run = FALSE; |
1274 data.first_run = FALSE; |
1264 if (!gst_structure_foreach ((GstStructure *) struct2, |
1275 if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2, |
1265 gst_caps_structure_intersect_field, &data)) |
1276 gst_caps_structure_intersect_field, &data))) |
1266 goto error; |
1277 goto error; |
1267 |
1278 |
1268 return data.dest; |
1279 return data.dest; |
1269 |
1280 |
1270 error: |
1281 error: |
1330 |
1341 |
1331 GstCaps * |
1342 GstCaps * |
1332 gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2) |
1343 gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2) |
1333 { |
1344 { |
1334 guint64 i; /* index can be up to 2 * G_MAX_UINT */ |
1345 guint64 i; /* index can be up to 2 * G_MAX_UINT */ |
1335 guint j, k; |
1346 guint j, k, len1, len2; |
1336 |
1347 |
1337 GstStructure *struct1; |
1348 GstStructure *struct1; |
1338 GstStructure *struct2; |
1349 GstStructure *struct2; |
1339 GstCaps *dest; |
1350 GstCaps *dest; |
1340 GstStructure *istruct; |
1351 GstStructure *istruct; |
1341 |
1352 |
1342 g_return_val_if_fail (GST_IS_CAPS (caps1), NULL); |
1353 g_return_val_if_fail (GST_IS_CAPS (caps1), NULL); |
1343 g_return_val_if_fail (GST_IS_CAPS (caps2), NULL); |
1354 g_return_val_if_fail (GST_IS_CAPS (caps2), NULL); |
1344 |
1355 |
1345 /* caps are exactly the same pointers, just copy one caps */ |
1356 /* caps are exactly the same pointers, just copy one caps */ |
1346 if (caps1 == caps2) |
1357 if (G_UNLIKELY (caps1 == caps2)) |
1347 return gst_caps_copy (caps1); |
1358 return gst_caps_copy (caps1); |
1348 |
1359 |
1349 /* empty caps on either side, return empty */ |
1360 /* empty caps on either side, return empty */ |
1350 if (gst_caps_is_empty (caps1) || gst_caps_is_empty (caps2)) |
1361 if (G_UNLIKELY (gst_caps_is_empty (caps1) || gst_caps_is_empty (caps2))) |
1351 return gst_caps_new_empty (); |
1362 return gst_caps_new_empty (); |
1352 |
1363 |
1353 /* one of the caps is any, just copy the other caps */ |
1364 /* one of the caps is any, just copy the other caps */ |
1354 if (gst_caps_is_any (caps1)) |
1365 if (G_UNLIKELY (gst_caps_is_any (caps1))) |
1355 return gst_caps_copy (caps2); |
1366 return gst_caps_copy (caps2); |
1356 if (gst_caps_is_any (caps2)) |
1367 if (G_UNLIKELY (gst_caps_is_any (caps2))) |
1357 return gst_caps_copy (caps1); |
1368 return gst_caps_copy (caps1); |
1358 |
1369 |
1359 dest = gst_caps_new_empty (); |
1370 dest = gst_caps_new_empty (); |
1360 |
1371 |
1361 /* run zigzag on top line then right line, this preserves the caps order |
1372 /* run zigzag on top line then right line, this preserves the caps order |
1372 * |
1383 * |
1373 * First we iterate over the caps1 structures (top line) intersecting |
1384 * First we iterate over the caps1 structures (top line) intersecting |
1374 * the structures diagonally down, then we iterate over the caps2 |
1385 * the structures diagonally down, then we iterate over the caps2 |
1375 * structures. |
1386 * structures. |
1376 */ |
1387 */ |
1377 for (i = 0; i < caps1->structs->len + caps2->structs->len - 1; i++) { |
1388 len1 = caps1->structs->len; |
|
1389 len2 = caps2->structs->len; |
|
1390 for (i = 0; i < len1 + len2 - 1; i++) { |
1378 /* caps1 index goes from 0 to caps1->structs->len-1 */ |
1391 /* caps1 index goes from 0 to caps1->structs->len-1 */ |
1379 j = MIN (i, caps1->structs->len - 1); |
1392 j = MIN (i, len1 - 1); |
1380 /* caps2 index stays 0 until i reaches caps1->structs->len, then it counts |
1393 /* caps2 index stays 0 until i reaches caps1->structs->len, then it counts |
1381 * up from 1 to caps2->structs->len - 1 */ |
1394 * up from 1 to caps2->structs->len - 1 */ |
1382 k = MAX (0, i - j); |
1395 k = MAX (0, i - j); |
1383 |
1396 |
1384 /* now run the diagonal line, end condition is the left or bottom |
1397 /* now run the diagonal line, end condition is the left or bottom |
1385 * border */ |
1398 * border */ |
1386 while (k < caps2->structs->len) { |
1399 while (k < len2) { |
1387 struct1 = gst_caps_get_structure (caps1, j); |
1400 struct1 = gst_caps_get_structure_unchecked (caps1, j); |
1388 struct2 = gst_caps_get_structure (caps2, k); |
1401 struct2 = gst_caps_get_structure_unchecked (caps2, k); |
1389 |
1402 |
1390 istruct = gst_caps_structure_intersect (struct1, struct2); |
1403 istruct = gst_caps_structure_intersect (struct1, struct2); |
1391 |
1404 |
1392 gst_caps_append_structure (dest, istruct); |
1405 gst_caps_append_structure (dest, istruct); |
1393 /* move down left */ |
1406 /* move down left */ |
1394 k++; |
1407 k++; |
1395 if (j == 0) |
1408 if (G_UNLIKELY (j == 0)) |
1396 break; /* so we don't roll back to G_MAXUINT */ |
1409 break; /* so we don't roll back to G_MAXUINT */ |
1397 j--; |
1410 j--; |
1398 } |
1411 } |
1399 } |
1412 } |
1400 return dest; |
1413 return dest; |
1496 The reason we need this is that there is no definition about what |
1509 The reason we need this is that there is no definition about what |
1497 ANY means for specific types, so it's not possible to reduce ANY partially |
1510 ANY means for specific types, so it's not possible to reduce ANY partially |
1498 You can only remove everything or nothing and that is done above. |
1511 You can only remove everything or nothing and that is done above. |
1499 Note: there's a test that checks this behaviour. */ |
1512 Note: there's a test that checks this behaviour. */ |
1500 g_return_val_if_fail (!gst_caps_is_any (minuend), NULL); |
1513 g_return_val_if_fail (!gst_caps_is_any (minuend), NULL); |
1501 g_assert (subtrahend->structs->len > 0); |
1514 sublen = subtrahend->structs->len; |
|
1515 g_assert (sublen > 0); |
1502 |
1516 |
1503 src = gst_caps_copy (minuend); |
1517 src = gst_caps_copy (minuend); |
1504 for (i = 0; i < subtrahend->structs->len; i++) { |
1518 for (i = 0; i < sublen; i++) { |
1505 sub = gst_caps_get_structure (subtrahend, i); |
1519 guint srclen; |
|
1520 |
|
1521 sub = gst_caps_get_structure_unchecked (subtrahend, i); |
1506 if (dest) { |
1522 if (dest) { |
1507 gst_caps_unref (src); |
1523 gst_caps_unref (src); |
1508 src = dest; |
1524 src = dest; |
1509 } |
1525 } |
1510 dest = gst_caps_new_empty (); |
1526 dest = gst_caps_new_empty (); |
1511 for (j = 0; j < src->structs->len; j++) { |
1527 srclen = src->structs->len; |
1512 min = gst_caps_get_structure (src, j); |
1528 for (j = 0; j < srclen; j++) { |
|
1529 min = gst_caps_get_structure_unchecked (src, j); |
1513 if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub)) { |
1530 if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub)) { |
1514 GSList *list; |
1531 GSList *list; |
1515 |
1532 |
1516 if (gst_caps_structure_subtract (&list, min, sub)) { |
1533 if (gst_caps_structure_subtract (&list, min, sub)) { |
1517 GSList *walk; |
1534 GSList *walk; |
1556 gst_caps_union (const GstCaps * caps1, const GstCaps * caps2) |
1573 gst_caps_union (const GstCaps * caps1, const GstCaps * caps2) |
1557 { |
1574 { |
1558 GstCaps *dest1; |
1575 GstCaps *dest1; |
1559 GstCaps *dest2; |
1576 GstCaps *dest2; |
1560 |
1577 |
|
1578 /* NULL pointers are no correct GstCaps */ |
|
1579 g_return_val_if_fail (caps1 != NULL, NULL); |
|
1580 g_return_val_if_fail (caps2 != NULL, NULL); |
|
1581 |
|
1582 if (gst_caps_is_empty (caps1)) |
|
1583 return gst_caps_copy (caps2); |
|
1584 |
|
1585 if (gst_caps_is_empty (caps2)) |
|
1586 return gst_caps_copy (caps1); |
|
1587 |
1561 if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2)) |
1588 if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2)) |
1562 return gst_caps_new_any (); |
1589 return gst_caps_new_any (); |
1563 |
1590 |
1564 dest1 = gst_caps_copy (caps1); |
1591 dest1 = gst_caps_copy (caps1); |
1565 dest2 = gst_caps_copy (caps2); |
1592 dest2 = gst_caps_copy (caps2); |
1582 NormalizeForeach *nf = (NormalizeForeach *) ptr; |
1609 NormalizeForeach *nf = (NormalizeForeach *) ptr; |
1583 GValue val = { 0 }; |
1610 GValue val = { 0 }; |
1584 guint i; |
1611 guint i; |
1585 |
1612 |
1586 if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { |
1613 if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { |
1587 for (i = 1; i < gst_value_list_get_size (value); i++) { |
1614 guint len = gst_value_list_get_size (value); |
|
1615 for (i = 1; i < len; i++) { |
1588 const GValue *v = gst_value_list_get_value (value, i); |
1616 const GValue *v = gst_value_list_get_value (value, i); |
1589 GstStructure *structure = gst_structure_copy (nf->structure); |
1617 GstStructure *structure = gst_structure_copy (nf->structure); |
1590 |
1618 |
1591 gst_structure_id_set_value (structure, field_id, v); |
1619 gst_structure_id_set_value (structure, field_id, v); |
1592 gst_caps_append_structure (nf->caps, structure); |
1620 gst_caps_append_structure (nf->caps, structure); |
1618 GstCaps * |
1646 GstCaps * |
1619 gst_caps_normalize (const GstCaps * caps) |
1647 gst_caps_normalize (const GstCaps * caps) |
1620 { |
1648 { |
1621 NormalizeForeach nf; |
1649 NormalizeForeach nf; |
1622 GstCaps *newcaps; |
1650 GstCaps *newcaps; |
1623 guint i; |
1651 guint i, nlen; |
1624 |
1652 |
1625 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
1653 g_return_val_if_fail (GST_IS_CAPS (caps), NULL); |
1626 |
1654 |
1627 newcaps = gst_caps_copy (caps); |
1655 newcaps = gst_caps_copy (caps); |
1628 nf.caps = newcaps; |
1656 nf.caps = newcaps; |
1629 |
1657 nlen = newcaps->structs->len; |
1630 for (i = 0; i < newcaps->structs->len; i++) { |
1658 |
1631 nf.structure = gst_caps_get_structure (newcaps, i); |
1659 for (i = 0; i < nlen; i++) { |
|
1660 nf.structure = gst_caps_get_structure_unchecked (newcaps, i); |
1632 |
1661 |
1633 while (!gst_structure_foreach (nf.structure, |
1662 while (!gst_structure_foreach (nf.structure, |
1634 gst_caps_normalize_foreach, &nf)); |
1663 gst_caps_normalize_foreach, &nf)); |
1635 } |
1664 } |
1636 |
1665 |
1791 |
1820 |
1792 g_ptr_array_sort (caps->structs, gst_caps_compare_structures); |
1821 g_ptr_array_sort (caps->structs, gst_caps_compare_structures); |
1793 |
1822 |
1794 start = caps->structs->len - 1; |
1823 start = caps->structs->len - 1; |
1795 for (i = caps->structs->len - 1; i >= 0; i--) { |
1824 for (i = caps->structs->len - 1; i >= 0; i--) { |
1796 simplify = gst_caps_get_structure (caps, i); |
1825 simplify = gst_caps_get_structure_unchecked (caps, i); |
1797 if (gst_structure_get_name_id (simplify) != |
1826 if (gst_structure_get_name_id (simplify) != |
1798 gst_structure_get_name_id (gst_caps_get_structure (caps, start))) |
1827 gst_structure_get_name_id (gst_caps_get_structure_unchecked (caps, |
|
1828 start))) |
1799 start = i; |
1829 start = i; |
1800 for (j = start; j >= 0; j--) { |
1830 for (j = start; j >= 0; j--) { |
1801 if (j == i) |
1831 if (j == i) |
1802 continue; |
1832 continue; |
1803 compare = gst_caps_get_structure (caps, j); |
1833 compare = gst_caps_get_structure_unchecked (caps, j); |
1804 if (gst_structure_get_name_id (simplify) != |
1834 if (gst_structure_get_name_id (simplify) != |
1805 gst_structure_get_name_id (compare)) { |
1835 gst_structure_get_name_id (compare)) { |
1806 break; |
1836 break; |
1807 } |
1837 } |
1808 if (gst_caps_structure_simplify (&result, simplify, compare)) { |
1838 if (gst_caps_structure_simplify (&result, simplify, compare)) { |
1909 * |
1939 * |
1910 * Converts @caps to a string representation. This string representation |
1940 * Converts @caps to a string representation. This string representation |
1911 * can be converted back to a #GstCaps by gst_caps_from_string(). |
1941 * can be converted back to a #GstCaps by gst_caps_from_string(). |
1912 * |
1942 * |
1913 * For debugging purposes its easier to do something like this: |
1943 * For debugging purposes its easier to do something like this: |
1914 * <programlisting> |
1944 * |[ |
1915 * GST_LOG ("caps are %" GST_PTR_FORMAT, caps); |
1945 * GST_LOG ("caps are %" GST_PTR_FORMAT, caps); |
1916 * </programlisting> |
1946 * ]| |
1917 * This prints the caps in human readble form. |
1947 * This prints the caps in human readble form. |
1918 * |
1948 * |
1919 * Returns: a newly allocated string representing @caps. |
1949 * Returns: a newly allocated string representing @caps. |
1920 */ |
1950 */ |
1921 #ifdef __SYMBIAN32__ |
1951 #ifdef __SYMBIAN32__ |
1923 #endif |
1953 #endif |
1924 |
1954 |
1925 gchar * |
1955 gchar * |
1926 gst_caps_to_string (const GstCaps * caps) |
1956 gst_caps_to_string (const GstCaps * caps) |
1927 { |
1957 { |
1928 guint i, slen; |
1958 guint i, slen, clen; |
1929 GString *s; |
1959 GString *s; |
1930 |
1960 |
1931 /* NOTE: This function is potentially called by the debug system, |
1961 /* NOTE: This function is potentially called by the debug system, |
1932 * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.) |
1962 * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.) |
1933 * should be careful to avoid recursion. This includes any functions |
1963 * should be careful to avoid recursion. This includes any functions |
1944 return g_strdup ("EMPTY"); |
1974 return g_strdup ("EMPTY"); |
1945 } |
1975 } |
1946 |
1976 |
1947 /* estimate a rough string length to avoid unnecessary reallocs in GString */ |
1977 /* estimate a rough string length to avoid unnecessary reallocs in GString */ |
1948 slen = 0; |
1978 slen = 0; |
1949 for (i = 0; i < caps->structs->len; i++) { |
1979 clen = caps->structs->len; |
1950 slen += STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure (caps, i)); |
1980 for (i = 0; i < clen; i++) { |
|
1981 slen += |
|
1982 STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure_unchecked (caps, |
|
1983 i)); |
1951 } |
1984 } |
1952 |
1985 |
1953 s = g_string_sized_new (slen); |
1986 s = g_string_sized_new (slen); |
1954 for (i = 0; i < caps->structs->len; i++) { |
1987 for (i = 0; i < clen; i++) { |
1955 GstStructure *structure; |
1988 GstStructure *structure; |
1956 |
1989 |
1957 if (i > 0) { |
1990 if (i > 0) { |
1958 /* ';' is now added by gst_structure_to_string */ |
1991 /* ';' is now added by gst_structure_to_string */ |
1959 g_string_append_c (s, ' '); |
1992 g_string_append_c (s, ' '); |
1960 } |
1993 } |
1961 |
1994 |
1962 structure = gst_caps_get_structure (caps, i); |
1995 structure = gst_caps_get_structure_unchecked (caps, i); |
1963 priv_gst_structure_append_to_gstring (structure, s); |
1996 priv_gst_structure_append_to_gstring (structure, s); |
1964 } |
1997 } |
1965 if (s->len && s->str[s->len - 1] == ';') { |
1998 if (s->len && s->str[s->len - 1] == ';') { |
1966 /* remove latest ';' */ |
1999 /* remove latest ';' */ |
1967 s->str[--s->len] = '\0'; |
2000 s->str[--s->len] = '\0'; |