• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 /**
21  * SECTION:gstcaps
22  * @title: GstCaps
23  * @short_description: Structure describing sets of media formats
24  * @see_also: #GstStructure, #GstMiniObject
25  *
26  * Caps (capabilities) are lightweight refcounted objects describing media types.
27  * They are composed of an array of #GstStructure.
28  *
29  * Caps are exposed on #GstPadTemplate to describe all possible types a
30  * given pad can handle. They are also stored in the #GstRegistry along with
31  * a description of the #GstElement.
32  *
33  * Caps are exposed on the element pads using the gst_pad_query_caps() pad
34  * function. This function describes the possible types that the pad can
35  * handle or produce at runtime.
36  *
37  * A #GstCaps can be constructed with the following code fragment:
38  *
39  * ``` C
40  *   GstCaps *caps = gst_caps_new_simple ("video/x-raw",
41  *      "format", G_TYPE_STRING, "I420",
42  *      "framerate", GST_TYPE_FRACTION, 25, 1,
43  *      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
44  *      "width", G_TYPE_INT, 320,
45  *      "height", G_TYPE_INT, 240,
46  *      NULL);
47  * ```
48  *
49  * A #GstCaps is fixed when it has no fields with ranges or lists. Use
50  * gst_caps_is_fixed() to test for fixed caps. Fixed caps can be used in a
51  * caps event to notify downstream elements of the current media type.
52  *
53  * Various methods exist to work with the media types such as subtracting
54  * or intersecting.
55  *
56  * Be aware that until 1.20 the #GstCaps / #GstStructure serialization into string
57  * had limited support for nested #GstCaps / #GstStructure fields. It could only
58  * support one level of nesting. Using more levels would lead to unexpected
59  * behavior when using serialization features, such as gst_caps_to_string() or
60  * gst_value_serialize() and their counterparts.
61  */
62 
63 #ifdef HAVE_CONFIG_H
64 #include "config.h"
65 #endif
66 #include <string.h>
67 #include <signal.h>
68 
69 #define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
70 #include "gst_private.h"
71 #include <gst/gst.h>
72 #include <gobject/gvaluecollector.h>
73 
74 #define DEBUG_REFCOUNT
75 
76 typedef struct _GstCapsArrayElement
77 {
78   GstStructure *structure;
79   GstCapsFeatures *features;
80 } GstCapsArrayElement;
81 
82 typedef struct _GstCapsImpl
83 {
84   GstCaps caps;
85 
86   GArray *array;
87 } GstCapsImpl;
88 
89 #define GST_CAPS_ARRAY(c) (((GstCapsImpl *)(c))->array)
90 
91 #define GST_CAPS_LEN(c)   (GST_CAPS_ARRAY(c)->len)
92 
93 #define IS_WRITABLE(caps) \
94   (GST_CAPS_REFCOUNT_VALUE (caps) == 1)
95 
96 /* same as gst_caps_is_any () */
97 #define CAPS_IS_ANY(caps)				\
98   (!!(GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY))
99 
100 /* same as gst_caps_is_empty () */
101 #define CAPS_IS_EMPTY(caps)				\
102   (!CAPS_IS_ANY(caps) && CAPS_IS_EMPTY_SIMPLE(caps))
103 
104 #define CAPS_IS_EMPTY_SIMPLE(caps)					\
105   ((GST_CAPS_ARRAY (caps) == NULL) || (GST_CAPS_LEN (caps) == 0))
106 
107 #define gst_caps_features_copy_conditional(f) ((f && (gst_caps_features_is_any (f) || !gst_caps_features_is_equal (f, GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) ? gst_caps_features_copy (f) : NULL)
108 
109 /* quick way to get a caps structure at an index without doing a type or array
110  * length check */
111 #define gst_caps_get_structure_unchecked(caps, index) \
112      (g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).structure)
113 #define gst_caps_get_features_storage_unchecked(caps, index) \
114      (&g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).features)
115 #define gst_caps_get_features_unchecked(caps, index) \
116      (g_atomic_pointer_get (gst_caps_get_features_storage_unchecked (caps, index)))
117 /* quick way to append a structure without checking the args */
118 #define gst_caps_append_structure_unchecked(caps, s, f) G_STMT_START{\
119   GstCapsArrayElement __e={s, f};                                      \
120   if (gst_structure_set_parent_refcount (__e.structure, &GST_MINI_OBJECT_REFCOUNT(caps)) && \
121       (!__e.features || gst_caps_features_set_parent_refcount (__e.features, &GST_MINI_OBJECT_REFCOUNT(caps))))         \
122     g_array_append_val (GST_CAPS_ARRAY (caps), __e);                             \
123 }G_STMT_END
124 
125 /* lock to protect multiple invocations of static caps to caps conversion */
126 G_LOCK_DEFINE_STATIC (static_caps_lock);
127 
128 static void gst_caps_transform_to_string (const GValue * src_value,
129     GValue * dest_value);
130 static gboolean gst_caps_from_string_inplace (GstCaps * caps,
131     const gchar * string);
132 
133 GType _gst_caps_type = 0;
134 GstCaps *_gst_caps_any;
135 GstCaps *_gst_caps_none;
136 
137 GST_DEFINE_MINI_OBJECT_TYPE (GstCaps, gst_caps);
138 
139 void
_priv_gst_caps_initialize(void)140 _priv_gst_caps_initialize (void)
141 {
142   _gst_caps_type = gst_caps_get_type ();
143 
144   _gst_caps_any = gst_caps_new_any ();
145   _gst_caps_none = gst_caps_new_empty ();
146 
147   g_value_register_transform_func (_gst_caps_type,
148       G_TYPE_STRING, gst_caps_transform_to_string);
149 }
150 
151 void
_priv_gst_caps_cleanup(void)152 _priv_gst_caps_cleanup (void)
153 {
154   gst_caps_unref (_gst_caps_any);
155   _gst_caps_any = NULL;
156   gst_caps_unref (_gst_caps_none);
157   _gst_caps_none = NULL;
158 }
159 
160 GstCapsFeatures *
__gst_caps_get_features_unchecked(const GstCaps * caps,guint idx)161 __gst_caps_get_features_unchecked (const GstCaps * caps, guint idx)
162 {
163   return gst_caps_get_features_unchecked (caps, idx);
164 }
165 
166 static GstCaps *
_gst_caps_copy(const GstCaps * caps)167 _gst_caps_copy (const GstCaps * caps)
168 {
169   GstCaps *newcaps;
170   GstStructure *structure;
171   GstCapsFeatures *features;
172   guint i, n;
173 
174   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
175 
176   newcaps = gst_caps_new_empty ();
177   GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
178   n = GST_CAPS_LEN (caps);
179 
180   GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "doing copy %p -> %p", caps, newcaps);
181 
182   for (i = 0; i < n; i++) {
183     structure = gst_caps_get_structure_unchecked (caps, i);
184     features = gst_caps_get_features_unchecked (caps, i);
185     gst_caps_append_structure_full (newcaps, gst_structure_copy (structure),
186         gst_caps_features_copy_conditional (features));
187   }
188 
189   return newcaps;
190 }
191 
192 /* creation/deletion */
193 static void
_gst_caps_free(GstCaps * caps)194 _gst_caps_free (GstCaps * caps)
195 {
196   GstStructure *structure;
197   GstCapsFeatures *features;
198   guint i, len;
199 
200   /* The refcount must be 0, but since we're only called by gst_caps_unref,
201    * don't bother testing. */
202   len = GST_CAPS_LEN (caps);
203   /* This can be used to get statistics about caps sizes */
204   /*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
205   for (i = 0; i < len; i++) {
206     structure = gst_caps_get_structure_unchecked (caps, i);
207     gst_structure_set_parent_refcount (structure, NULL);
208     gst_structure_free (structure);
209     features = gst_caps_get_features_unchecked (caps, i);
210     if (features) {
211       gst_caps_features_set_parent_refcount (features, NULL);
212       gst_caps_features_free (features);
213     }
214   }
215   g_array_free (GST_CAPS_ARRAY (caps), TRUE);
216 
217 #ifdef DEBUG_REFCOUNT
218   GST_CAT_TRACE (GST_CAT_CAPS, "freeing caps %p", caps);
219 #endif
220 
221 #ifdef USE_POISONING
222   memset (caps, 0xff, sizeof (GstCapsImpl));
223 #endif
224 
225   g_slice_free1 (sizeof (GstCapsImpl), caps);
226 }
227 
228 static void
gst_caps_init(GstCaps * caps)229 gst_caps_init (GstCaps * caps)
230 {
231   gst_mini_object_init (GST_MINI_OBJECT_CAST (caps), 0, _gst_caps_type,
232       (GstMiniObjectCopyFunction) _gst_caps_copy, NULL,
233       (GstMiniObjectFreeFunction) _gst_caps_free);
234 
235   /* the 32 has been determined by logging caps sizes in _gst_caps_free
236    * but g_ptr_array uses 16 anyway if it expands once, so this does not help
237    * in practice
238    * GST_CAPS_ARRAY (caps) = g_ptr_array_sized_new (32);
239    */
240   GST_CAPS_ARRAY (caps) =
241       g_array_new (FALSE, TRUE, sizeof (GstCapsArrayElement));
242 }
243 
244 /**
245  * gst_caps_new_empty:
246  *
247  * Creates a new #GstCaps that is empty.  That is, the returned
248  * #GstCaps contains no media formats.
249  * The #GstCaps is guaranteed to be writable.
250  *
251  * Returns: (transfer full): the new #GstCaps
252  */
253 GstCaps *
gst_caps_new_empty(void)254 gst_caps_new_empty (void)
255 {
256   GstCaps *caps;
257 
258   caps = (GstCaps *) g_slice_new (GstCapsImpl);
259 
260   gst_caps_init (caps);
261 
262 #ifdef DEBUG_REFCOUNT
263   GST_CAT_TRACE (GST_CAT_CAPS, "created caps %p", caps);
264 #endif
265 
266   return caps;
267 }
268 
269 /**
270  * gst_caps_new_any:
271  *
272  * Creates a new #GstCaps that indicates that it is compatible with
273  * any media format.
274  *
275  * Returns: (transfer full): the new #GstCaps
276  */
277 GstCaps *
gst_caps_new_any(void)278 gst_caps_new_any (void)
279 {
280   GstCaps *caps = gst_caps_new_empty ();
281 
282   GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAG_ANY);
283 
284   return caps;
285 }
286 
287 /**
288  * gst_caps_new_empty_simple:
289  * @media_type: the media type of the structure
290  *
291  * Creates a new #GstCaps that contains one #GstStructure with name
292  * @media_type.
293  *
294  * Returns: (transfer full): the new #GstCaps
295  */
296 GstCaps *
gst_caps_new_empty_simple(const char * media_type)297 gst_caps_new_empty_simple (const char *media_type)
298 {
299   GstCaps *caps;
300   GstStructure *structure;
301 
302   caps = gst_caps_new_empty ();
303   structure = gst_structure_new_empty (media_type);
304   if (structure)
305     gst_caps_append_structure_unchecked (caps, structure, NULL);
306 
307   return caps;
308 }
309 
310 /**
311  * gst_caps_new_simple:
312  * @media_type: the media type of the structure
313  * @fieldname: first field to set
314  * @...: additional arguments
315  *
316  * Creates a new #GstCaps that contains one #GstStructure.  The
317  * structure is defined by the arguments, which have the same format
318  * as gst_structure_new().
319  *
320  * Returns: (transfer full): the new #GstCaps
321  */
322 GstCaps *
gst_caps_new_simple(const char * media_type,const char * fieldname,...)323 gst_caps_new_simple (const char *media_type, const char *fieldname, ...)
324 {
325   GstCaps *caps;
326   GstStructure *structure;
327   va_list var_args;
328 
329   caps = gst_caps_new_empty ();
330 
331   va_start (var_args, fieldname);
332   structure = gst_structure_new_valist (media_type, fieldname, var_args);
333   va_end (var_args);
334 
335   if (structure)
336     gst_caps_append_structure_unchecked (caps, structure, NULL);
337   else
338     gst_caps_replace (&caps, NULL);
339 
340   return caps;
341 }
342 
343 /**
344  * gst_caps_new_full:
345  * @struct1: the first structure to add
346  * @...: additional structures to add
347  *
348  * Creates a new #GstCaps and adds all the structures listed as
349  * arguments.  The list must be %NULL-terminated.  The structures
350  * are not copied; the returned #GstCaps owns the structures.
351  *
352  * Returns: (transfer full): the new #GstCaps
353  */
354 GstCaps *
gst_caps_new_full(GstStructure * struct1,...)355 gst_caps_new_full (GstStructure * struct1, ...)
356 {
357   GstCaps *caps;
358   va_list var_args;
359 
360   va_start (var_args, struct1);
361   caps = gst_caps_new_full_valist (struct1, var_args);
362   va_end (var_args);
363 
364   return caps;
365 }
366 
367 /**
368  * gst_caps_new_full_valist:
369  * @structure: the first structure to add
370  * @var_args: additional structures to add
371  *
372  * Creates a new #GstCaps and adds all the structures listed as
373  * arguments.  The list must be %NULL-terminated.  The structures
374  * are not copied; the returned #GstCaps owns the structures.
375  *
376  * Returns: (transfer full): the new #GstCaps
377  */
378 GstCaps *
gst_caps_new_full_valist(GstStructure * structure,va_list var_args)379 gst_caps_new_full_valist (GstStructure * structure, va_list var_args)
380 {
381   GstCaps *caps;
382 
383   caps = gst_caps_new_empty ();
384 
385   while (structure) {
386     gst_caps_append_structure_unchecked (caps, structure, NULL);
387     structure = va_arg (var_args, GstStructure *);
388   }
389 
390   return caps;
391 }
392 
393 G_DEFINE_POINTER_TYPE (GstStaticCaps, gst_static_caps);
394 
395 /**
396  * gst_static_caps_get:
397  * @static_caps: the #GstStaticCaps to convert
398  *
399  * Converts a #GstStaticCaps to a #GstCaps.
400  *
401  * Returns: (transfer full) (nullable): a pointer to the #GstCaps. Since the
402  *     core holds an additional ref to the returned caps, use
403  *     gst_caps_make_writable() on the returned caps to modify it.
404  */
405 GstCaps *
gst_static_caps_get(GstStaticCaps * static_caps)406 gst_static_caps_get (GstStaticCaps * static_caps)
407 {
408   GstCaps **caps;
409 
410   g_return_val_if_fail (static_caps != NULL, NULL);
411 
412   caps = &static_caps->caps;
413 
414   /* refcount is 0 when we need to convert */
415   if (G_UNLIKELY (*caps == NULL)) {
416     const char *string;
417 
418     G_LOCK (static_caps_lock);
419     /* check if other thread already updated */
420     if (G_UNLIKELY (*caps != NULL))
421       goto done;
422 
423     string = static_caps->string;
424 
425     if (G_UNLIKELY (string == NULL))
426       goto no_string;
427 
428     *caps = gst_caps_from_string (string);
429 
430     /* convert to string */
431     if (G_UNLIKELY (*caps == NULL)) {
432       g_critical ("Could not convert static caps \"%s\"", string);
433       goto done;
434     }
435 
436     /* Caps generated from static caps are usually leaked */
437     GST_MINI_OBJECT_FLAG_SET (*caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
438 
439     GST_CAT_TRACE (GST_CAT_CAPS, "created %p from string %s", static_caps,
440         string);
441   done:
442     G_UNLOCK (static_caps_lock);
443   }
444   /* ref the caps, makes it not writable */
445   if (G_LIKELY (*caps != NULL))
446     gst_caps_ref (*caps);
447 
448   return *caps;
449 
450   /* ERRORS */
451 no_string:
452   {
453     G_UNLOCK (static_caps_lock);
454     g_warning ("static caps %p string is NULL", static_caps);
455     return NULL;
456   }
457 }
458 
459 /**
460  * gst_static_caps_cleanup:
461  * @static_caps: the #GstStaticCaps to clean
462  *
463  * Cleans up the cached caps contained in @static_caps.
464  */
465 void
gst_static_caps_cleanup(GstStaticCaps * static_caps)466 gst_static_caps_cleanup (GstStaticCaps * static_caps)
467 {
468   G_LOCK (static_caps_lock);
469   gst_caps_replace (&static_caps->caps, NULL);
470   G_UNLOCK (static_caps_lock);
471 }
472 
473 /* manipulation */
474 
475 static void
gst_caps_remove_and_get_structure_and_features(GstCaps * caps,guint idx,GstStructure ** s,GstCapsFeatures ** f)476 gst_caps_remove_and_get_structure_and_features (GstCaps * caps, guint idx,
477     GstStructure ** s, GstCapsFeatures ** f)
478 {
479   GstStructure *s_;
480   GstCapsFeatures *f_;
481 
482   s_ = gst_caps_get_structure_unchecked (caps, idx);
483   f_ = gst_caps_get_features_unchecked (caps, idx);
484 
485   /* don't use index_fast, gst_caps_simplify relies on the order */
486   g_array_remove_index (GST_CAPS_ARRAY (caps), idx);
487 
488   gst_structure_set_parent_refcount (s_, NULL);
489   if (f_) {
490     gst_caps_features_set_parent_refcount (f_, NULL);
491   }
492 
493   *s = s_;
494   *f = f_;
495 }
496 
497 static GstStructure *
gst_caps_remove_and_get_structure(GstCaps * caps,guint idx)498 gst_caps_remove_and_get_structure (GstCaps * caps, guint idx)
499 {
500   GstStructure *s;
501   GstCapsFeatures *f;
502 
503   gst_caps_remove_and_get_structure_and_features (caps, idx, &s, &f);
504 
505   if (f)
506     gst_caps_features_free (f);
507 
508   return s;
509 }
510 
511 static void
gst_caps_make_any(GstCaps * caps)512 gst_caps_make_any (GstCaps * caps)
513 {
514   guint i;
515   GstStructure *s;
516 
517   /* empty out residual structures */
518   for (i = GST_CAPS_LEN (caps); i; i--) {
519     s = gst_caps_remove_and_get_structure (caps, 0);
520     gst_structure_free (s);
521   }
522   GST_CAPS_FLAGS (caps) |= GST_CAPS_FLAG_ANY;
523 }
524 
525 /**
526  * gst_caps_steal_structure:
527  * @caps: the #GstCaps to retrieve from
528  * @index: Index of the structure to retrieve
529  *
530  * Retrieves the structure with the given index from the list of structures
531  * contained in @caps. The caller becomes the owner of the returned structure.
532  *
533  * Returns: (transfer full) (nullable): a pointer to the #GstStructure
534  *     corresponding to @index.
535  */
536 GstStructure *
gst_caps_steal_structure(GstCaps * caps,guint index)537 gst_caps_steal_structure (GstCaps * caps, guint index)
538 {
539   g_return_val_if_fail (caps != NULL, NULL);
540   g_return_val_if_fail (IS_WRITABLE (caps), NULL);
541 
542   if (G_UNLIKELY (index >= GST_CAPS_LEN (caps)))
543     return NULL;
544 
545   return gst_caps_remove_and_get_structure (caps, index);
546 }
547 
548 /**
549  * gst_caps_append:
550  * @caps1: the #GstCaps that will be appended to
551  * @caps2: (transfer full): the #GstCaps to append
552  *
553  * Appends the structures contained in @caps2 to @caps1. The structures in
554  * @caps2 are not copied -- they are transferred to @caps1, and then @caps2 is
555  * freed. If either caps is ANY, the resulting caps will be ANY.
556  */
557 void
gst_caps_append(GstCaps * caps1,GstCaps * caps2)558 gst_caps_append (GstCaps * caps1, GstCaps * caps2)
559 {
560   GstStructure *structure;
561   GstCapsFeatures *features;
562   int i;
563 
564   g_return_if_fail (GST_IS_CAPS (caps1));
565   g_return_if_fail (GST_IS_CAPS (caps2));
566   g_return_if_fail (IS_WRITABLE (caps1));
567 
568   if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) {
569     gst_caps_make_any (caps1);
570     gst_caps_unref (caps2);
571   } else {
572     caps2 = gst_caps_make_writable (caps2);
573 
574     for (i = GST_CAPS_LEN (caps2); i; i--) {
575       gst_caps_remove_and_get_structure_and_features (caps2, 0, &structure,
576           &features);
577       gst_caps_append_structure_unchecked (caps1, structure, features);
578     }
579     gst_caps_unref (caps2);     /* guaranteed to free it */
580   }
581 }
582 
583 /**
584  * gst_caps_merge:
585  * @caps1: (transfer full): the #GstCaps that will take the new entries
586  * @caps2: (transfer full): the #GstCaps to merge in
587  *
588  * Appends the structures contained in @caps2 to @caps1 if they are not yet
589  * expressed by @caps1. The structures in @caps2 are not copied -- they are
590  * transferred to a writable copy of @caps1, and then @caps2 is freed.
591  * If either caps is ANY, the resulting caps will be ANY.
592  *
593  * Returns: (transfer full): the merged caps.
594  */
595 GstCaps *
gst_caps_merge(GstCaps * caps1,GstCaps * caps2)596 gst_caps_merge (GstCaps * caps1, GstCaps * caps2)
597 {
598   GstStructure *structure;
599   GstCapsFeatures *features;
600   int i;
601   GstCaps *result;
602 
603   g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
604   g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
605 
606   if (G_UNLIKELY (CAPS_IS_ANY (caps1))) {
607     gst_caps_unref (caps2);
608     result = caps1;
609   } else if (G_UNLIKELY (CAPS_IS_ANY (caps2))) {
610     gst_caps_unref (caps1);
611     result = caps2;
612   } else {
613     caps2 = gst_caps_make_writable (caps2);
614 
615     for (i = GST_CAPS_LEN (caps2); i; i--) {
616       gst_caps_remove_and_get_structure_and_features (caps2, 0, &structure,
617           &features);
618       caps1 = gst_caps_merge_structure_full (caps1, structure, features);
619     }
620     gst_caps_unref (caps2);
621     result = caps1;
622 
623     /* this is too naive
624        GstCaps *com = gst_caps_intersect (caps1, caps2);
625        GstCaps *add = gst_caps_subtract (caps2, com);
626 
627        GST_DEBUG ("common : %d", gst_caps_get_size (com));
628        GST_DEBUG ("adding : %d", gst_caps_get_size (add));
629        gst_caps_append (caps1, add);
630        gst_caps_unref (com);
631      */
632   }
633 
634   return result;
635 }
636 
637 /**
638  * gst_caps_append_structure:
639  * @caps: the #GstCaps that will be appended to
640  * @structure: (transfer full): the #GstStructure to append
641  *
642  * Appends @structure to @caps.  The structure is not copied; @caps
643  * becomes the owner of @structure.
644  */
645 void
gst_caps_append_structure(GstCaps * caps,GstStructure * structure)646 gst_caps_append_structure (GstCaps * caps, GstStructure * structure)
647 {
648   g_return_if_fail (GST_IS_CAPS (caps));
649   g_return_if_fail (IS_WRITABLE (caps));
650 
651   if (CAPS_IS_ANY (caps)) {
652     /* ANY caps will stay as ANY caps */
653     if (structure)
654       gst_structure_free (structure);
655     return;
656   }
657 
658   if (G_LIKELY (structure)) {
659     gst_caps_append_structure_unchecked (caps, structure, NULL);
660   }
661 }
662 
663 /**
664  * gst_caps_append_structure_full:
665  * @caps: the #GstCaps that will be appended to
666  * @structure: (transfer full): the #GstStructure to append
667  * @features: (transfer full) (allow-none): the #GstCapsFeatures to append
668  *
669  * Appends @structure with @features to @caps.  The structure is not copied; @caps
670  * becomes the owner of @structure.
671  *
672  * Since: 1.2
673  */
674 void
gst_caps_append_structure_full(GstCaps * caps,GstStructure * structure,GstCapsFeatures * features)675 gst_caps_append_structure_full (GstCaps * caps, GstStructure * structure,
676     GstCapsFeatures * features)
677 {
678   g_return_if_fail (GST_IS_CAPS (caps));
679   g_return_if_fail (IS_WRITABLE (caps));
680 
681   if (CAPS_IS_ANY (caps)) {
682     /* ANY caps will stay as ANY caps */
683     if (structure)
684       gst_structure_free (structure);
685     if (features)
686       gst_caps_features_free (features);
687     return;
688   }
689 
690   if (G_LIKELY (structure)) {
691     gst_caps_append_structure_unchecked (caps, structure, features);
692   }
693 }
694 
695 /**
696  * gst_caps_remove_structure:
697  * @caps: the #GstCaps to remove from
698  * @idx: Index of the structure to remove
699  *
700  * Removes the structure with the given index from the list of structures
701  * contained in @caps.
702  */
703 void
gst_caps_remove_structure(GstCaps * caps,guint idx)704 gst_caps_remove_structure (GstCaps * caps, guint idx)
705 {
706   GstStructure *structure;
707 
708   g_return_if_fail (caps != NULL);
709   g_return_if_fail (idx < gst_caps_get_size (caps));
710   g_return_if_fail (IS_WRITABLE (caps));
711 
712   structure = gst_caps_remove_and_get_structure (caps, idx);
713   gst_structure_free (structure);
714 }
715 
716 /**
717  * gst_caps_merge_structure:
718  * @caps: (transfer full): the #GstCaps to merge into
719  * @structure: (transfer full): the #GstStructure to merge
720  *
721  * Appends @structure to @caps if it is not already expressed by @caps.
722  *
723  * Returns: (transfer full): the merged caps.
724  */
725 GstCaps *
gst_caps_merge_structure(GstCaps * caps,GstStructure * structure)726 gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
727 {
728   GstStructure *structure1;
729   GstCapsFeatures *features1;
730   int i;
731   gboolean unique = TRUE;
732 
733   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
734 
735   if (G_UNLIKELY (structure == NULL))
736     return caps;
737 
738   if (CAPS_IS_ANY (caps)) {
739     /* ANY caps will stay as ANY caps */
740     gst_structure_free (structure);
741     return caps;
742   }
743 
744   /* check each structure */
745   for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
746     structure1 = gst_caps_get_structure_unchecked (caps, i);
747     features1 = gst_caps_get_features_unchecked (caps, i);
748     if (!features1)
749       features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
750 
751     /* if structure is a subset of structure1 and the
752      * there are no existing features, then skip it */
753     if (gst_caps_features_is_equal (features1,
754             GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)
755         && gst_structure_is_subset (structure, structure1)) {
756       unique = FALSE;
757       break;
758     }
759   }
760   if (unique) {
761     caps = gst_caps_make_writable (caps);
762     gst_caps_append_structure_unchecked (caps, structure, NULL);
763   } else {
764     gst_structure_free (structure);
765   }
766   return caps;
767 }
768 
769 /**
770  * gst_caps_merge_structure_full:
771  * @caps: (transfer full): the #GstCaps to merge into
772  * @structure: (transfer full): the #GstStructure to merge
773  * @features: (transfer full) (allow-none): the #GstCapsFeatures to merge
774  *
775  * Appends @structure with @features to @caps if its not already expressed by @caps.
776  *
777  * Returns: (transfer full): the merged caps.
778  *
779  * Since: 1.2
780  */
781 GstCaps *
gst_caps_merge_structure_full(GstCaps * caps,GstStructure * structure,GstCapsFeatures * features)782 gst_caps_merge_structure_full (GstCaps * caps, GstStructure * structure,
783     GstCapsFeatures * features)
784 {
785   GstStructure *structure1;
786   GstCapsFeatures *features1, *features_tmp;
787   int i;
788   gboolean unique = TRUE;
789 
790   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
791 
792   if (G_UNLIKELY (structure == NULL))
793     return caps;
794 
795   if (CAPS_IS_ANY (caps)) {
796     /* ANY caps will stay as ANY caps */
797     gst_structure_free (structure);
798     if (features)
799       gst_caps_features_free (features);
800     return caps;
801   }
802 
803   /* To make comparisons easier below */
804   features_tmp = features ? features : GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
805 
806   /* check each structure */
807   for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
808     structure1 = gst_caps_get_structure_unchecked (caps, i);
809     features1 = gst_caps_get_features_unchecked (caps, i);
810     if (!features1)
811       features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
812     /* if structure is a subset of structure1 and the
813      * the features are a subset, then skip it */
814     /* FIXME: We only skip if none of the features are
815      * ANY and are still equal. That way all ANY structures
816      * show up in the caps and no non-ANY structures are
817      * swallowed by ANY structures
818      */
819     if (((!gst_caps_features_is_any (features_tmp)
820                 || gst_caps_features_is_any (features1))
821             && gst_caps_features_is_equal (features_tmp, features1))
822         && gst_structure_is_subset (structure, structure1)) {
823       unique = FALSE;
824       break;
825     }
826   }
827   if (unique) {
828     caps = gst_caps_make_writable (caps);
829     gst_caps_append_structure_unchecked (caps, structure, features);
830   } else {
831     gst_structure_free (structure);
832     if (features)
833       gst_caps_features_free (features);
834   }
835   return caps;
836 }
837 
838 /**
839  * gst_caps_get_size:
840  * @caps: a #GstCaps
841  *
842  * Gets the number of structures contained in @caps.
843  *
844  * Returns: the number of structures that @caps contains
845  */
846 guint
gst_caps_get_size(const GstCaps * caps)847 gst_caps_get_size (const GstCaps * caps)
848 {
849   g_return_val_if_fail (GST_IS_CAPS (caps), 0);
850 
851   return GST_CAPS_LEN (caps);
852 }
853 
854 /**
855  * gst_caps_get_structure:
856  * @caps: a #GstCaps
857  * @index: the index of the structure
858  *
859  * Finds the structure in @caps at @index, and returns it.
860  *
861  * WARNING: This function takes a `const GstCaps *`, but returns a
862  * non-const `GstStructure *`.  This is for programming convenience --
863  * the caller should be aware that structures inside a constant
864  * #GstCaps should not be modified. However, if you know the caps
865  * are writable, either because you have just copied them or made
866  * them writable with gst_caps_make_writable(), you may modify the
867  * structure returned in the usual way, e.g. with functions like
868  * gst_structure_set().
869  *
870  * Returns: (transfer none): a pointer to the #GstStructure corresponding
871  *     to @index
872  */
873 GstStructure *
gst_caps_get_structure(const GstCaps * caps,guint index)874 gst_caps_get_structure (const GstCaps * caps, guint index)
875 {
876   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
877   g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL);
878 
879   return gst_caps_get_structure_unchecked (caps, index);
880 }
881 
882 /**
883  * gst_caps_get_features:
884  * @caps: a #GstCaps
885  * @index: the index of the structure
886  *
887  * Finds the features in @caps at @index, and returns it.
888  *
889  * WARNING: This function takes a `const GstCaps *`, but returns a
890  * non-const `GstCapsFeatures *`.  This is for programming convenience --
891  * the caller should be aware that features inside a constant
892  * #GstCaps should not be modified. However, if you know the caps
893  * are writable, either because you have just copied them or made
894  * them writable with gst_caps_make_writable(), you may modify the
895  * features returned in the usual way, e.g. with functions like
896  * gst_caps_features_add().
897  *
898  * Returns: (transfer none) (nullable): a pointer to the #GstCapsFeatures
899  *     corresponding to @index
900  *
901  * Since: 1.2
902  */
903 GstCapsFeatures *
gst_caps_get_features(const GstCaps * caps,guint index)904 gst_caps_get_features (const GstCaps * caps, guint index)
905 {
906   GstCapsFeatures *features;
907 
908   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
909   g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL);
910 
911   features = gst_caps_get_features_unchecked (caps, index);
912   if (!features) {
913     GstCapsFeatures **storage;
914 
915     /* We have to do some atomic pointer magic here as the caps
916      * might not be writable and someone else calls this function
917      * at the very same time */
918     features = gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
919     gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps));
920 
921     storage = gst_caps_get_features_storage_unchecked (caps, index);
922     if (!g_atomic_pointer_compare_and_exchange (storage,
923             (GstCapsFeatures *) NULL, features)) {
924       /* Someone did the same we just tried in the meantime */
925       gst_caps_features_set_parent_refcount (features, NULL);
926       gst_caps_features_free (features);
927 
928       features = gst_caps_get_features_unchecked (caps, index);
929       g_assert (features != NULL);
930     }
931   }
932 
933   return features;
934 }
935 
936 /**
937  * gst_caps_set_features:
938  * @caps: a #GstCaps
939  * @index: the index of the structure
940  * @features: (allow-none) (transfer full): the #GstCapsFeatures to set
941  *
942  * Sets the @features for the structure at @index.
943  *
944  * Since: 1.2
945  */
946 void
gst_caps_set_features(GstCaps * caps,guint index,GstCapsFeatures * features)947 gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features)
948 {
949   GstCapsFeatures **storage, *old;
950 
951   g_return_if_fail (caps != NULL);
952   g_return_if_fail (index < gst_caps_get_size (caps));
953   g_return_if_fail (IS_WRITABLE (caps));
954 
955   storage = gst_caps_get_features_storage_unchecked (caps, index);
956   /* Not much problem here as caps are writable */
957   old = g_atomic_pointer_get (storage);
958   g_atomic_pointer_set (storage, features);
959 
960   if (features)
961     gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps));
962 
963   if (old) {
964     gst_caps_features_set_parent_refcount (old, NULL);
965     gst_caps_features_free (old);
966   }
967 }
968 
969 /**
970  * gst_caps_set_features_simple:
971  * @caps: a #GstCaps
972  * @features: (allow-none) (transfer full): the #GstCapsFeatures to set
973  *
974  * Sets the @features for all the structures of @caps.
975  *
976  * Since: 1.16
977  */
978 void
gst_caps_set_features_simple(GstCaps * caps,GstCapsFeatures * features)979 gst_caps_set_features_simple (GstCaps * caps, GstCapsFeatures * features)
980 {
981   guint i;
982   guint n;
983 
984   g_return_if_fail (caps != NULL);
985   g_return_if_fail (IS_WRITABLE (caps));
986 
987   n = gst_caps_get_size (caps);
988 
989   if (n == 0) {
990     /* features will not be set on any structure */
991     if (features)
992       gst_caps_features_free (features);
993     return;
994   }
995 
996   for (i = 0; i < n; i++) {
997     GstCapsFeatures *f;
998 
999     /* Transfer ownership of @features to the last structure */
1000     if (features && i < n - 1)
1001       f = gst_caps_features_copy (features);
1002     else
1003       f = features;
1004 
1005     gst_caps_set_features (caps, i, f);
1006   }
1007 }
1008 
1009 /**
1010  * gst_caps_copy_nth:
1011  * @caps: the #GstCaps to copy
1012  * @nth: the nth structure to copy
1013  *
1014  * Creates a new #GstCaps and appends a copy of the nth structure
1015  * contained in @caps.
1016  *
1017  * Returns: (transfer full): the new #GstCaps
1018  *
1019  * Since: 1.16
1020  */
1021 GstCaps *
gst_caps_copy_nth(const GstCaps * caps,guint nth)1022 gst_caps_copy_nth (const GstCaps * caps, guint nth)
1023 {
1024   GstCaps *newcaps;
1025   GstStructure *structure;
1026   GstCapsFeatures *features;
1027 
1028   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
1029 
1030   newcaps = gst_caps_new_empty ();
1031   GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
1032 
1033   if (G_LIKELY (GST_CAPS_LEN (caps) > nth)) {
1034     structure = gst_caps_get_structure_unchecked (caps, nth);
1035     features = gst_caps_get_features_unchecked (caps, nth);
1036     gst_caps_append_structure_unchecked (newcaps,
1037         gst_structure_copy (structure),
1038         gst_caps_features_copy_conditional (features));
1039   }
1040 
1041   return newcaps;
1042 }
1043 
1044 /**
1045  * gst_caps_truncate:
1046  * @caps: (transfer full): the #GstCaps to truncate
1047  *
1048  * Discards all but the first structure from @caps. Useful when
1049  * fixating.
1050  *
1051  * This function takes ownership of @caps and will call gst_caps_make_writable()
1052  * on it if necessary, so you must not use @caps afterwards unless you keep an
1053  * additional reference to it with gst_caps_ref().
1054  *
1055  * Note that it is not guaranteed that the returned caps have exactly one
1056  * structure. If @caps is any or empty caps then the returned caps will be
1057  * the same and contain no structure at all.
1058  *
1059  * Returns: (transfer full): truncated caps
1060  */
1061 GstCaps *
gst_caps_truncate(GstCaps * caps)1062 gst_caps_truncate (GstCaps * caps)
1063 {
1064   gint i;
1065 
1066   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
1067 
1068   /* Nothing to truncate here */
1069   if (GST_CAPS_LEN (caps) == 0)
1070     return caps;
1071 
1072   i = GST_CAPS_LEN (caps) - 1;
1073 
1074   /* Already truncated */
1075   if (i == 0)
1076     return caps;
1077 
1078   caps = gst_caps_make_writable (caps);
1079   while (i > 0)
1080     gst_caps_remove_structure (caps, i--);
1081 
1082   return caps;
1083 }
1084 
1085 /**
1086  * gst_caps_set_value:
1087  * @caps: a writable caps
1088  * @field: name of the field to set
1089  * @value: value to set the field to
1090  *
1091  * Sets the given @field on all structures of @caps to the given @value.
1092  * This is a convenience function for calling gst_structure_set_value() on
1093  * all structures of @caps.
1094  **/
1095 void
gst_caps_set_value(GstCaps * caps,const char * field,const GValue * value)1096 gst_caps_set_value (GstCaps * caps, const char *field, const GValue * value)
1097 {
1098   guint i, len;
1099 
1100   g_return_if_fail (GST_IS_CAPS (caps));
1101   g_return_if_fail (IS_WRITABLE (caps));
1102   g_return_if_fail (field != NULL);
1103   g_return_if_fail (G_IS_VALUE (value));
1104 
1105   len = GST_CAPS_LEN (caps);
1106   for (i = 0; i < len; i++) {
1107     GstStructure *structure = gst_caps_get_structure_unchecked (caps, i);
1108     gst_structure_set_value (structure, field, value);
1109   }
1110 }
1111 
1112 /**
1113  * gst_caps_set_simple_valist:
1114  * @caps: the #GstCaps to set
1115  * @field: first field to set
1116  * @varargs: additional parameters
1117  *
1118  * Sets fields in a #GstCaps.  The arguments must be passed in the same
1119  * manner as gst_structure_set(), and be %NULL-terminated.
1120  */
1121 void
gst_caps_set_simple_valist(GstCaps * caps,const char * field,va_list varargs)1122 gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs)
1123 {
1124   GValue value = { 0, };
1125 
1126   g_return_if_fail (GST_IS_CAPS (caps));
1127   g_return_if_fail (IS_WRITABLE (caps));
1128 
1129   while (field) {
1130     GType type;
1131     char *err;
1132 
1133     type = va_arg (varargs, GType);
1134 
1135     G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err);
1136     if (G_UNLIKELY (err)) {
1137       g_critical ("%s", err);
1138       g_free (err);
1139       return;
1140     }
1141 
1142     gst_caps_set_value (caps, field, &value);
1143 
1144     g_value_unset (&value);
1145 
1146     field = va_arg (varargs, const gchar *);
1147   }
1148 }
1149 
1150 /**
1151  * gst_caps_set_simple:
1152  * @caps: the #GstCaps to set
1153  * @field: first field to set
1154  * @...: additional parameters
1155  *
1156  * Sets fields in a #GstCaps.  The arguments must be passed in the same
1157  * manner as gst_structure_set(), and be %NULL-terminated.
1158  */
1159 void
gst_caps_set_simple(GstCaps * caps,const char * field,...)1160 gst_caps_set_simple (GstCaps * caps, const char *field, ...)
1161 {
1162   va_list var_args;
1163 
1164   g_return_if_fail (GST_IS_CAPS (caps));
1165   g_return_if_fail (IS_WRITABLE (caps));
1166 
1167   va_start (var_args, field);
1168   gst_caps_set_simple_valist (caps, field, var_args);
1169   va_end (var_args);
1170 }
1171 
1172 /* tests */
1173 
1174 /**
1175  * gst_caps_is_any:
1176  * @caps: the #GstCaps to test
1177  *
1178  * Determines if @caps represents any media format.
1179  *
1180  * Returns: %TRUE if @caps represents any format.
1181  */
1182 gboolean
gst_caps_is_any(const GstCaps * caps)1183 gst_caps_is_any (const GstCaps * caps)
1184 {
1185   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
1186 
1187   return (CAPS_IS_ANY (caps));
1188 }
1189 
1190 /**
1191  * gst_caps_is_empty:
1192  * @caps: the #GstCaps to test
1193  *
1194  * Determines if @caps represents no media formats.
1195  *
1196  * Returns: %TRUE if @caps represents no formats.
1197  */
1198 gboolean
gst_caps_is_empty(const GstCaps * caps)1199 gst_caps_is_empty (const GstCaps * caps)
1200 {
1201   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
1202 
1203   if (CAPS_IS_ANY (caps))
1204     return FALSE;
1205 
1206   return CAPS_IS_EMPTY_SIMPLE (caps);
1207 }
1208 
1209 static gboolean
gst_caps_is_fixed_foreach(GQuark field_id,const GValue * value,gpointer unused)1210 gst_caps_is_fixed_foreach (GQuark field_id, const GValue * value,
1211     gpointer unused)
1212 {
1213   return gst_value_is_fixed (value);
1214 }
1215 
1216 /**
1217  * gst_caps_is_fixed:
1218  * @caps: the #GstCaps to test
1219  *
1220  * Fixed #GstCaps describe exactly one format, that is, they have exactly
1221  * one structure, and each field in the structure describes a fixed type.
1222  * Examples of non-fixed types are GST_TYPE_INT_RANGE and GST_TYPE_LIST.
1223  *
1224  * Returns: %TRUE if @caps is fixed
1225  */
1226 gboolean
gst_caps_is_fixed(const GstCaps * caps)1227 gst_caps_is_fixed (const GstCaps * caps)
1228 {
1229   GstStructure *structure;
1230   GstCapsFeatures *features;
1231 
1232   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
1233 
1234   if (GST_CAPS_LEN (caps) != 1)
1235     return FALSE;
1236 
1237   /* double check not ANY, even though ANY caps should have 0 length */
1238   if (CAPS_IS_ANY (caps))
1239     return FALSE;
1240 
1241   features = gst_caps_get_features_unchecked (caps, 0);
1242   if (features && gst_caps_features_is_any (features))
1243     return FALSE;
1244 
1245   structure = gst_caps_get_structure_unchecked (caps, 0);
1246 
1247   return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL);
1248 }
1249 
1250 /**
1251  * gst_caps_is_equal_fixed:
1252  * @caps1: the #GstCaps to test
1253  * @caps2: the #GstCaps to test
1254  *
1255  * Tests if two #GstCaps are equal.  This function only works on fixed
1256  * #GstCaps.
1257  *
1258  * Returns: %TRUE if the arguments represent the same format
1259  */
1260 gboolean
gst_caps_is_equal_fixed(const GstCaps * caps1,const GstCaps * caps2)1261 gst_caps_is_equal_fixed (const GstCaps * caps1, const GstCaps * caps2)
1262 {
1263   GstStructure *struct1, *struct2;
1264   GstCapsFeatures *features1, *features2;
1265 
1266   g_return_val_if_fail (gst_caps_is_fixed (caps1), FALSE);
1267   g_return_val_if_fail (gst_caps_is_fixed (caps2), FALSE);
1268 
1269   struct1 = gst_caps_get_structure_unchecked (caps1, 0);
1270   features1 = gst_caps_get_features_unchecked (caps1, 0);
1271   if (!features1)
1272     features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1273   struct2 = gst_caps_get_structure_unchecked (caps2, 0);
1274   features2 = gst_caps_get_features_unchecked (caps2, 0);
1275   if (!features2)
1276     features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1277 
1278   return gst_structure_is_equal (struct1, struct2) &&
1279       gst_caps_features_is_equal (features1, features2);
1280 }
1281 
1282 /**
1283  * gst_caps_is_always_compatible:
1284  * @caps1: the #GstCaps to test
1285  * @caps2: the #GstCaps to test
1286  *
1287  * A given #GstCaps structure is always compatible with another if
1288  * every media format that is in the first is also contained in the
1289  * second.  That is, @caps1 is a subset of @caps2.
1290  *
1291  * Returns: %TRUE if @caps1 is a subset of @caps2.
1292  */
1293 gboolean
gst_caps_is_always_compatible(const GstCaps * caps1,const GstCaps * caps2)1294 gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2)
1295 {
1296   g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
1297   g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
1298 
1299   return gst_caps_is_subset (caps1, caps2);
1300 }
1301 
1302 /**
1303  * gst_caps_is_subset:
1304  * @subset: a #GstCaps
1305  * @superset: a potentially greater #GstCaps
1306  *
1307  * Checks if all caps represented by @subset are also represented by @superset.
1308  *
1309  * Returns: %TRUE if @subset is a subset of @superset
1310  */
1311 gboolean
gst_caps_is_subset(const GstCaps * subset,const GstCaps * superset)1312 gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
1313 {
1314   GstStructure *s1, *s2;
1315   GstCapsFeatures *f1, *f2;
1316   gboolean ret = TRUE;
1317   gint i, j;
1318 
1319   g_return_val_if_fail (subset != NULL, FALSE);
1320   g_return_val_if_fail (superset != NULL, FALSE);
1321 
1322   if (CAPS_IS_EMPTY (subset) || CAPS_IS_ANY (superset))
1323     return TRUE;
1324   if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset))
1325     return FALSE;
1326 
1327   for (i = GST_CAPS_LEN (subset) - 1; i >= 0; i--) {
1328     s1 = gst_caps_get_structure_unchecked (subset, i);
1329     f1 = gst_caps_get_features_unchecked (subset, i);
1330     if (!f1)
1331       f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1332 
1333     for (j = GST_CAPS_LEN (superset) - 1; j >= 0; j--) {
1334       s2 = gst_caps_get_structure_unchecked (superset, j);
1335       f2 = gst_caps_get_features_unchecked (superset, j);
1336       if (!f2)
1337         f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1338       if ((!gst_caps_features_is_any (f1) || gst_caps_features_is_any (f2)) &&
1339           gst_caps_features_is_equal (f1, f2)
1340           && gst_structure_is_subset (s1, s2)) {
1341         /* If we found a superset, continue with the next
1342          * subset structure */
1343         break;
1344       }
1345     }
1346 
1347     /* If we found no superset for this subset structure
1348      * we return FALSE immediately */
1349     if (j == -1) {
1350       ret = FALSE;
1351       break;
1352     }
1353   }
1354 
1355   return ret;
1356 }
1357 
1358 /**
1359  * gst_caps_is_subset_structure:
1360  * @caps: a #GstCaps
1361  * @structure: a potential #GstStructure subset of @caps
1362  *
1363  * Checks if @structure is a subset of @caps. See gst_caps_is_subset()
1364  * for more information.
1365  *
1366  * Returns: %TRUE if @structure is a subset of @caps
1367  */
1368 gboolean
gst_caps_is_subset_structure(const GstCaps * caps,const GstStructure * structure)1369 gst_caps_is_subset_structure (const GstCaps * caps,
1370     const GstStructure * structure)
1371 {
1372   GstStructure *s;
1373   gint i;
1374 
1375   g_return_val_if_fail (caps != NULL, FALSE);
1376   g_return_val_if_fail (structure != NULL, FALSE);
1377 
1378   if (CAPS_IS_ANY (caps))
1379     return TRUE;
1380   if (CAPS_IS_EMPTY (caps))
1381     return FALSE;
1382 
1383   for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
1384     s = gst_caps_get_structure_unchecked (caps, i);
1385     if (gst_structure_is_subset (structure, s)) {
1386       /* If we found a superset return TRUE */
1387       return TRUE;
1388     }
1389   }
1390 
1391   return FALSE;
1392 }
1393 
1394 /**
1395  * gst_caps_is_subset_structure_full:
1396  * @caps: a #GstCaps
1397  * @structure: a potential #GstStructure subset of @caps
1398  * @features: (allow-none): a #GstCapsFeatures for @structure
1399  *
1400  * Checks if @structure is a subset of @caps. See gst_caps_is_subset()
1401  * for more information.
1402  *
1403  * Returns: %TRUE if @structure is a subset of @caps
1404  *
1405  * Since: 1.2
1406  */
1407 gboolean
gst_caps_is_subset_structure_full(const GstCaps * caps,const GstStructure * structure,const GstCapsFeatures * features)1408 gst_caps_is_subset_structure_full (const GstCaps * caps,
1409     const GstStructure * structure, const GstCapsFeatures * features)
1410 {
1411   GstStructure *s;
1412   GstCapsFeatures *f;
1413   gint i;
1414 
1415   g_return_val_if_fail (caps != NULL, FALSE);
1416   g_return_val_if_fail (structure != NULL, FALSE);
1417 
1418   if (CAPS_IS_ANY (caps))
1419     return TRUE;
1420   if (CAPS_IS_EMPTY (caps))
1421     return FALSE;
1422 
1423   if (!features)
1424     features = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1425 
1426   for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
1427     s = gst_caps_get_structure_unchecked (caps, i);
1428     f = gst_caps_get_features_unchecked (caps, i);
1429     if (!f)
1430       f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1431     if ((!gst_caps_features_is_any (features) || gst_caps_features_is_any (f))
1432         && gst_caps_features_is_equal (features, f)
1433         && gst_structure_is_subset (structure, s)) {
1434       /* If we found a superset return TRUE */
1435       return TRUE;
1436     }
1437   }
1438 
1439   return FALSE;
1440 }
1441 
1442 /**
1443  * gst_caps_is_equal:
1444  * @caps1: a #GstCaps
1445  * @caps2: another #GstCaps
1446  *
1447  * Checks if the given caps represent the same set of caps.
1448  *
1449  * Returns: %TRUE if both caps are equal.
1450  */
1451 gboolean
gst_caps_is_equal(const GstCaps * caps1,const GstCaps * caps2)1452 gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2)
1453 {
1454   g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
1455   g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
1456 
1457   if (G_UNLIKELY (caps1 == caps2))
1458     return TRUE;
1459 
1460   if (G_UNLIKELY (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2)))
1461     return gst_caps_is_equal_fixed (caps1, caps2);
1462 
1463   return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1);
1464 }
1465 
1466 /**
1467  * gst_caps_is_strictly_equal:
1468  * @caps1: a #GstCaps
1469  * @caps2: another #GstCaps
1470  *
1471  * Checks if the given caps are exactly the same set of caps.
1472  *
1473  * Returns: %TRUE if both caps are strictly equal.
1474  */
1475 gboolean
gst_caps_is_strictly_equal(const GstCaps * caps1,const GstCaps * caps2)1476 gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
1477 {
1478   int i;
1479   GstStructure *s1, *s2;
1480   GstCapsFeatures *f1, *f2;
1481 
1482   g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
1483   g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
1484 
1485   if (G_UNLIKELY (caps1 == caps2))
1486     return TRUE;
1487 
1488   /* if both are ANY caps, consider them strictly equal */
1489   if (CAPS_IS_ANY (caps1))
1490     return (CAPS_IS_ANY (caps2));
1491   else if (CAPS_IS_ANY (caps2))
1492     return FALSE;
1493 
1494   if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
1495     return FALSE;
1496 
1497   for (i = 0; i < GST_CAPS_LEN (caps1); i++) {
1498     s1 = gst_caps_get_structure_unchecked (caps1, i);
1499     f1 = gst_caps_get_features_unchecked (caps1, i);
1500     if (!f1)
1501       f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1502     s2 = gst_caps_get_structure_unchecked (caps2, i);
1503     f2 = gst_caps_get_features_unchecked (caps2, i);
1504     if (!f2)
1505       f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1506 
1507     if (gst_caps_features_is_any (f1) != gst_caps_features_is_any (f2) ||
1508         !gst_caps_features_is_equal (f1, f2) ||
1509         !gst_structure_is_equal (s1, s2))
1510       return FALSE;
1511   }
1512 
1513   return TRUE;
1514 }
1515 
1516 /* intersect operation */
1517 
1518 /**
1519  * gst_caps_can_intersect:
1520  * @caps1: a #GstCaps to intersect
1521  * @caps2: a #GstCaps to intersect
1522  *
1523  * Tries intersecting @caps1 and @caps2 and reports whether the result would not
1524  * be empty
1525  *
1526  * Returns: %TRUE if intersection would be not empty
1527  */
1528 gboolean
gst_caps_can_intersect(const GstCaps * caps1,const GstCaps * caps2)1529 gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
1530 {
1531   guint64 i;                    /* index can be up to 2 * G_MAX_UINT */
1532   guint j, k, len1, len2;
1533   GstStructure *struct1;
1534   GstStructure *struct2;
1535   GstCapsFeatures *features1;
1536   GstCapsFeatures *features2;
1537 
1538   g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
1539   g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
1540 
1541   /* caps are exactly the same pointers */
1542   if (G_UNLIKELY (caps1 == caps2))
1543     return TRUE;
1544 
1545   /* empty caps on either side, return empty */
1546   if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
1547     return FALSE;
1548 
1549   /* one of the caps is any */
1550   if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2)))
1551     return TRUE;
1552 
1553   /* run zigzag on top line then right line, this preserves the caps order
1554    * much better than a simple loop.
1555    *
1556    * This algorithm zigzags over the caps structures as demonstrated in
1557    * the following matrix:
1558    *
1559    *          caps1                              0  1  2  3
1560    *       +-------------     total distance:  +-------------
1561    *       | 1  2  4  7                      0 | 0  1  2  3
1562    * caps2 | 3  5  8 10                      1 | 1  2  3  4
1563    *       | 6  9 11 12                      2 | 2  3  4  5
1564    *
1565    * First we iterate over the caps1 structures (top line) intersecting
1566    * the structures diagonally down, then we iterate over the caps2
1567    * structures. The result is that the intersections are ordered based on the
1568    * sum of the indexes in the list.
1569    */
1570   len1 = GST_CAPS_LEN (caps1);
1571   len2 = GST_CAPS_LEN (caps2);
1572   for (i = 0; i < len1 + len2 - 1; i++) {
1573     /* superset index goes from 0 to superset->structs->len-1 */
1574     j = MIN (i, len1 - 1);
1575     /* subset index stays 0 until i reaches superset->structs->len, then it
1576      * counts up from 1 to subset->structs->len - 1 */
1577     k = (i > j) ? (i - j) : 0;  /* MAX (0, i - j) */
1578     /* now run the diagonal line, end condition is the left or bottom
1579      * border */
1580     while (k < len2) {
1581       struct1 = gst_caps_get_structure_unchecked (caps1, j);
1582       features1 = gst_caps_get_features_unchecked (caps1, j);
1583       if (!features1)
1584         features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1585       struct2 = gst_caps_get_structure_unchecked (caps2, k);
1586       features2 = gst_caps_get_features_unchecked (caps2, k);
1587       if (!features2)
1588         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1589       if (gst_caps_features_is_equal (features1, features2) &&
1590           gst_structure_can_intersect (struct1, struct2)) {
1591         return TRUE;
1592       }
1593       /* move down left */
1594       k++;
1595       if (G_UNLIKELY (j == 0))
1596         break;                  /* so we don't roll back to G_MAXUINT */
1597       j--;
1598     }
1599   }
1600 
1601   return FALSE;
1602 }
1603 
1604 static GstCaps *
gst_caps_intersect_zig_zag(GstCaps * caps1,GstCaps * caps2)1605 gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
1606 {
1607   guint64 i;                    /* index can be up to 2 * G_MAX_UINT */
1608   guint j, k, len1, len2;
1609   GstStructure *struct1;
1610   GstStructure *struct2;
1611   GstCapsFeatures *features1;
1612   GstCapsFeatures *features2;
1613   GstCaps *dest;
1614   GstStructure *istruct;
1615 
1616   dest = gst_caps_new_empty ();
1617   /* run zigzag on top line then right line, this preserves the caps order
1618    * much better than a simple loop.
1619    *
1620    * This algorithm zigzags over the caps structures as demonstrated in
1621    * the following matrix:
1622    *
1623    *          caps1
1624    *       +-------------
1625    *       | 1  2  4  7
1626    * caps2 | 3  5  8 10
1627    *       | 6  9 11 12
1628    *
1629    * First we iterate over the caps1 structures (top line) intersecting
1630    * the structures diagonally down, then we iterate over the caps2
1631    * structures.
1632    */
1633   len1 = GST_CAPS_LEN (caps1);
1634   len2 = GST_CAPS_LEN (caps2);
1635   for (i = 0; i < len1 + len2 - 1; i++) {
1636     /* caps1 index goes from 0 to GST_CAPS_LEN (caps1)-1 */
1637     j = MIN (i, len1 - 1);
1638     /* caps2 index stays 0 until i reaches GST_CAPS_LEN (caps1), then it counts
1639      * up from 1 to GST_CAPS_LEN (caps2) - 1 */
1640     k = (i > j) ? (i - j) : 0;  /* MAX (0, i - j) */
1641     /* now run the diagonal line, end condition is the left or bottom
1642      * border */
1643     while (k < len2) {
1644       struct1 = gst_caps_get_structure_unchecked (caps1, j);
1645       features1 = gst_caps_get_features_unchecked (caps1, j);
1646       if (!features1)
1647         features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1648       struct2 = gst_caps_get_structure_unchecked (caps2, k);
1649       features2 = gst_caps_get_features_unchecked (caps2, k);
1650       if (!features2)
1651         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1652       if (gst_caps_features_is_equal (features1, features2)) {
1653         istruct = gst_structure_intersect (struct1, struct2);
1654         if (istruct) {
1655           if (gst_caps_features_is_any (features1))
1656             dest =
1657                 gst_caps_merge_structure_full (dest, istruct,
1658                 gst_caps_features_copy_conditional (features2));
1659           else
1660             dest =
1661                 gst_caps_merge_structure_full (dest, istruct,
1662                 gst_caps_features_copy_conditional (features1));
1663         }
1664       }
1665       /* move down left */
1666       k++;
1667       if (G_UNLIKELY (j == 0))
1668         break;                  /* so we don't roll back to G_MAXUINT */
1669       j--;
1670     }
1671   }
1672   return dest;
1673 }
1674 
1675 /**
1676  * gst_caps_intersect_first:
1677  * @caps1: a #GstCaps to intersect
1678  * @caps2: a #GstCaps to intersect
1679  *
1680  * Creates a new #GstCaps that contains all the formats that are common
1681  * to both @caps1 and @caps2.
1682  *
1683  * Unlike @gst_caps_intersect, the returned caps will be ordered in a similar
1684  * fashion as @caps1.
1685  *
1686  * Returns: (transfer full): the new #GstCaps
1687  */
1688 static GstCaps *
gst_caps_intersect_first(GstCaps * caps1,GstCaps * caps2)1689 gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2)
1690 {
1691   guint i;
1692   guint j, len1, len2;
1693   GstStructure *struct1;
1694   GstStructure *struct2;
1695   GstCapsFeatures *features1;
1696   GstCapsFeatures *features2;
1697   GstCaps *dest;
1698   GstStructure *istruct;
1699 
1700   dest = gst_caps_new_empty ();
1701   len1 = GST_CAPS_LEN (caps1);
1702   len2 = GST_CAPS_LEN (caps2);
1703   for (i = 0; i < len1; i++) {
1704     struct1 = gst_caps_get_structure_unchecked (caps1, i);
1705     features1 = gst_caps_get_features_unchecked (caps1, i);
1706     if (!features1)
1707       features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1708     for (j = 0; j < len2; j++) {
1709       struct2 = gst_caps_get_structure_unchecked (caps2, j);
1710       features2 = gst_caps_get_features_unchecked (caps2, j);
1711       if (!features2)
1712         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1713       if (gst_caps_features_is_equal (features1, features2)) {
1714         istruct = gst_structure_intersect (struct1, struct2);
1715         if (istruct) {
1716           if (gst_caps_features_is_any (features1))
1717             dest =
1718                 gst_caps_merge_structure_full (dest, istruct,
1719                 gst_caps_features_copy_conditional (features2));
1720           else
1721             dest =
1722                 gst_caps_merge_structure_full (dest, istruct,
1723                 gst_caps_features_copy_conditional (features1));
1724         }
1725       }
1726     }
1727   }
1728 
1729   return dest;
1730 }
1731 
1732 /**
1733  * gst_caps_intersect_full:
1734  * @caps1: a #GstCaps to intersect
1735  * @caps2: a #GstCaps to intersect
1736  * @mode: The intersection algorithm/mode to use
1737  *
1738  * Creates a new #GstCaps that contains all the formats that are common
1739  * to both @caps1 and @caps2, the order is defined by the #GstCapsIntersectMode
1740  * used.
1741  *
1742  * Returns: (transfer full): the new #GstCaps
1743  */
1744 GstCaps *
gst_caps_intersect_full(GstCaps * caps1,GstCaps * caps2,GstCapsIntersectMode mode)1745 gst_caps_intersect_full (GstCaps * caps1, GstCaps * caps2,
1746     GstCapsIntersectMode mode)
1747 {
1748   g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
1749   g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
1750 
1751   /* Common fast-path */
1752   /* caps are exactly the same pointers, just copy one caps */
1753   if (G_UNLIKELY (caps1 == caps2))
1754     return gst_caps_ref (caps1);
1755 
1756   /* empty caps on either side, return empty */
1757   if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
1758     return gst_caps_ref (GST_CAPS_NONE);
1759 
1760   /* one of the caps is any, just copy the other caps */
1761   if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
1762     return gst_caps_ref (caps2);
1763 
1764   if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
1765     return gst_caps_ref (caps1);
1766 
1767   switch (mode) {
1768     case GST_CAPS_INTERSECT_FIRST:
1769       return gst_caps_intersect_first (caps1, caps2);
1770     default:
1771       g_warning ("Unknown caps intersect mode: %d", mode);
1772       /* fallthrough */
1773     case GST_CAPS_INTERSECT_ZIG_ZAG:
1774       return gst_caps_intersect_zig_zag (caps1, caps2);
1775   }
1776 }
1777 
1778 /**
1779  * gst_caps_intersect:
1780  * @caps1: a #GstCaps to intersect
1781  * @caps2: a #GstCaps to intersect
1782  *
1783  * Creates a new #GstCaps that contains all the formats that are common
1784  * to both @caps1 and @caps2. Defaults to %GST_CAPS_INTERSECT_ZIG_ZAG mode.
1785  *
1786  * Returns: (transfer full): the new #GstCaps
1787  */
1788 GstCaps *
gst_caps_intersect(GstCaps * caps1,GstCaps * caps2)1789 gst_caps_intersect (GstCaps * caps1, GstCaps * caps2)
1790 {
1791   return gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG);
1792 }
1793 
1794 /* subtract operation */
1795 
1796 typedef struct
1797 {
1798   const GstStructure *subtract_from;
1799   GSList *put_into;
1800 } SubtractionEntry;
1801 
1802 static gboolean
gst_caps_structure_subtract_field(GQuark field_id,const GValue * value,gpointer user_data)1803 gst_caps_structure_subtract_field (GQuark field_id, const GValue * value,
1804     gpointer user_data)
1805 {
1806   SubtractionEntry *e = user_data;
1807   GValue subtraction = { 0, };
1808   const GValue *other;
1809   GstStructure *structure;
1810 
1811   other = gst_structure_id_get_value (e->subtract_from, field_id);
1812 
1813   if (!other) {
1814     return FALSE;
1815   }
1816 
1817   if (!gst_value_subtract (&subtraction, other, value))
1818     return TRUE;
1819 
1820   if (gst_value_compare (&subtraction, other) == GST_VALUE_EQUAL) {
1821     g_value_unset (&subtraction);
1822     return FALSE;
1823   } else {
1824     structure = gst_structure_copy (e->subtract_from);
1825     gst_structure_id_take_value (structure, field_id, &subtraction);
1826     e->put_into = g_slist_prepend (e->put_into, structure);
1827     return TRUE;
1828   }
1829 }
1830 
1831 static gboolean
gst_caps_structure_subtract(GSList ** into,const GstStructure * minuend,const GstStructure * subtrahend)1832 gst_caps_structure_subtract (GSList ** into, const GstStructure * minuend,
1833     const GstStructure * subtrahend)
1834 {
1835   SubtractionEntry e;
1836   gboolean ret;
1837 
1838   e.subtract_from = minuend;
1839   e.put_into = NULL;
1840   ret = gst_structure_foreach ((GstStructure *) subtrahend,
1841       gst_caps_structure_subtract_field, &e);
1842 
1843   if (ret) {
1844     *into = e.put_into;
1845   } else {
1846     GSList *walk;
1847 
1848     for (walk = e.put_into; walk; walk = g_slist_next (walk)) {
1849       gst_structure_free (walk->data);
1850     }
1851     g_slist_free (e.put_into);
1852   }
1853 
1854   return ret;
1855 }
1856 
1857 /**
1858  * gst_caps_subtract:
1859  * @minuend: #GstCaps to subtract from
1860  * @subtrahend: #GstCaps to subtract
1861  *
1862  * Subtracts the @subtrahend from the @minuend.
1863  * > This function does not work reliably if optional properties for caps
1864  * > are included on one caps and omitted on the other.
1865  *
1866  * Returns: (transfer full): the resulting caps
1867  */
1868 GstCaps *
gst_caps_subtract(GstCaps * minuend,GstCaps * subtrahend)1869 gst_caps_subtract (GstCaps * minuend, GstCaps * subtrahend)
1870 {
1871   guint i, j, sublen;
1872   GstStructure *min;
1873   GstStructure *sub;
1874   GstCapsFeatures *min_f, *sub_f;
1875   GstCaps *dest = NULL, *src;
1876 
1877   g_return_val_if_fail (minuend != NULL, NULL);
1878   g_return_val_if_fail (subtrahend != NULL, NULL);
1879 
1880   if (CAPS_IS_EMPTY (minuend) || CAPS_IS_ANY (subtrahend)) {
1881     return gst_caps_new_empty ();
1882   }
1883 
1884   if (CAPS_IS_EMPTY_SIMPLE (subtrahend))
1885     return gst_caps_ref (minuend);
1886 
1887   /* FIXME: Do we want this here or above?
1888      The reason we need this is that there is no definition about what
1889      ANY means for specific types, so it's not possible to reduce ANY partially
1890      You can only remove everything or nothing and that is done above.
1891      Note: there's a test that checks this behaviour. */
1892 
1893   g_return_val_if_fail (!CAPS_IS_ANY (minuend), NULL);
1894   sublen = GST_CAPS_LEN (subtrahend);
1895   g_assert (sublen > 0);
1896 
1897   src = _gst_caps_copy (minuend);
1898   for (i = 0; i < sublen; i++) {
1899     guint srclen;
1900 
1901     sub = gst_caps_get_structure_unchecked (subtrahend, i);
1902     sub_f = gst_caps_get_features_unchecked (subtrahend, i);
1903     if (!sub_f)
1904       sub_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1905     if (dest) {
1906       gst_caps_unref (src);
1907       src = dest;
1908     }
1909     dest = gst_caps_new_empty ();
1910     srclen = GST_CAPS_LEN (src);
1911     for (j = 0; j < srclen; j++) {
1912       min = gst_caps_get_structure_unchecked (src, j);
1913       min_f = gst_caps_get_features_unchecked (src, j);
1914       if (!min_f)
1915         min_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
1916 
1917       /* Same reason as above for ANY caps */
1918       g_return_val_if_fail (!gst_caps_features_is_any (min_f), NULL);
1919 
1920       if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub) &&
1921           gst_caps_features_is_equal (min_f, sub_f)) {
1922         GSList *list;
1923 
1924         if (gst_caps_structure_subtract (&list, min, sub)) {
1925           GSList *walk;
1926 
1927           for (walk = list; walk; walk = g_slist_next (walk)) {
1928             gst_caps_append_structure_unchecked (dest,
1929                 (GstStructure *) walk->data,
1930                 gst_caps_features_copy_conditional (min_f));
1931           }
1932           g_slist_free (list);
1933         } else {
1934           gst_caps_append_structure_unchecked (dest, gst_structure_copy (min),
1935               gst_caps_features_copy_conditional (min_f));
1936         }
1937       } else {
1938         gst_caps_append_structure_unchecked (dest, gst_structure_copy (min),
1939             gst_caps_features_copy_conditional (min_f));
1940       }
1941     }
1942 
1943     if (CAPS_IS_EMPTY_SIMPLE (dest)) {
1944       gst_caps_unref (src);
1945       return dest;
1946     }
1947   }
1948 
1949   gst_caps_unref (src);
1950   dest = gst_caps_simplify (dest);
1951 
1952   return dest;
1953 }
1954 
1955 /* normalize/simplify operations */
1956 
1957 typedef struct _NormalizeForeach
1958 {
1959   GstCaps *caps;
1960   GstStructure *structure;
1961   GstCapsFeatures *features;
1962 } NormalizeForeach;
1963 
1964 static gboolean
gst_caps_normalize_foreach(GQuark field_id,const GValue * value,gpointer ptr)1965 gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr)
1966 {
1967   NormalizeForeach *nf = (NormalizeForeach *) ptr;
1968   GValue val = { 0 };
1969   guint i;
1970 
1971   if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
1972     guint len = gst_value_list_get_size (value);
1973 
1974     for (i = 1; i < len; i++) {
1975       const GValue *v = gst_value_list_get_value (value, i);
1976       GstStructure *structure = gst_structure_copy (nf->structure);
1977 
1978       gst_structure_id_set_value (structure, field_id, v);
1979       gst_caps_append_structure_unchecked (nf->caps, structure,
1980           gst_caps_features_copy_conditional (nf->features));
1981     }
1982 
1983     gst_value_init_and_copy (&val, gst_value_list_get_value (value, 0));
1984     gst_structure_id_take_value (nf->structure, field_id, &val);
1985     return FALSE;
1986   }
1987 
1988   return TRUE;
1989 }
1990 
1991 /**
1992  * gst_caps_normalize:
1993  * @caps: (transfer full): a #GstCaps to normalize
1994  *
1995  * Returns a #GstCaps that represents the same set of formats as
1996  * @caps, but contains no lists.  Each list is expanded into separate
1997  * #GstStructure.
1998  *
1999  * This function takes ownership of @caps and will call gst_caps_make_writable()
2000  * on it so you must not use @caps afterwards unless you keep an additional
2001  * reference to it with gst_caps_ref().
2002  *
2003  * Returns: (transfer full): the normalized #GstCaps
2004  */
2005 GstCaps *
gst_caps_normalize(GstCaps * caps)2006 gst_caps_normalize (GstCaps * caps)
2007 {
2008   NormalizeForeach nf;
2009   guint i;
2010 
2011   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
2012 
2013   caps = gst_caps_make_writable (caps);
2014   nf.caps = caps;
2015 
2016   for (i = 0; i < gst_caps_get_size (nf.caps); i++) {
2017     nf.structure = gst_caps_get_structure_unchecked (nf.caps, i);
2018     nf.features = gst_caps_get_features_unchecked (nf.caps, i);
2019     while (!gst_structure_foreach (nf.structure,
2020             gst_caps_normalize_foreach, &nf));
2021   }
2022 
2023   return nf.caps;
2024 }
2025 
2026 static gint
gst_caps_compare_structures(gconstpointer one,gconstpointer two)2027 gst_caps_compare_structures (gconstpointer one, gconstpointer two)
2028 {
2029   gint ret;
2030   const GstStructure *struct1 = ((const GstCapsArrayElement *) one)->structure;
2031   const GstStructure *struct2 = ((const GstCapsArrayElement *) two)->structure;
2032 
2033   /* FIXME: this orders alphabetically, but ordering the quarks might be faster
2034      So what's the best way? */
2035   ret = strcmp (gst_structure_get_name (struct1),
2036       gst_structure_get_name (struct2));
2037 
2038   if (ret)
2039     return ret;
2040 
2041   return gst_structure_n_fields (struct2) - gst_structure_n_fields (struct1);
2042 }
2043 
2044 typedef struct
2045 {
2046   GQuark name;
2047   GValue value;
2048   GstStructure *compare;
2049 } UnionField;
2050 
2051 static gboolean
gst_caps_structure_figure_out_union(GQuark field_id,const GValue * value,gpointer user_data)2052 gst_caps_structure_figure_out_union (GQuark field_id, const GValue * value,
2053     gpointer user_data)
2054 {
2055   UnionField *u = user_data;
2056   const GValue *val = gst_structure_id_get_value (u->compare, field_id);
2057 
2058   if (!val) {
2059     if (u->name)
2060       g_value_unset (&u->value);
2061     return FALSE;
2062   }
2063 
2064   if (gst_value_compare (val, value) == GST_VALUE_EQUAL)
2065     return TRUE;
2066 
2067   if (u->name) {
2068     g_value_unset (&u->value);
2069     return FALSE;
2070   }
2071 
2072   u->name = field_id;
2073   gst_value_union (&u->value, val, value);
2074 
2075   return TRUE;
2076 }
2077 
2078 static gboolean
gst_caps_structure_simplify(GstStructure ** result,GstStructure * simplify,GstStructure * compare)2079 gst_caps_structure_simplify (GstStructure ** result,
2080     GstStructure * simplify, GstStructure * compare)
2081 {
2082   GSList *list;
2083   UnionField field = { 0, {0,}, NULL };
2084 
2085   /* try to subtract to get a real subset */
2086   if (gst_caps_structure_subtract (&list, simplify, compare)) {
2087     if (list == NULL) {         /* no result */
2088       *result = NULL;
2089       return TRUE;
2090     } else if (list->next == NULL) {    /* one result */
2091       *result = list->data;
2092       g_slist_free (list);
2093       return TRUE;
2094     } else {                    /* multiple results */
2095       g_slist_foreach (list, (GFunc) gst_structure_free, NULL);
2096       g_slist_free (list);
2097       list = NULL;
2098     }
2099   }
2100 
2101   /* try to union both structs */
2102   field.compare = compare;
2103   if (gst_structure_foreach (simplify,
2104           gst_caps_structure_figure_out_union, &field)) {
2105     gboolean ret = FALSE;
2106 
2107     /* now we know all of simplify's fields are the same in compare
2108      * but at most one field: field.name */
2109     if (G_IS_VALUE (&field.value)) {
2110       if (gst_structure_n_fields (simplify) == gst_structure_n_fields (compare)) {
2111         gst_structure_id_take_value (compare, field.name, &field.value);
2112         *result = NULL;
2113         ret = TRUE;
2114       } else {
2115         g_value_unset (&field.value);
2116       }
2117     } else
2118         if (gst_structure_n_fields (simplify) <=
2119         gst_structure_n_fields (compare)) {
2120       /* compare is just more specific, will be optimized away later */
2121       /* FIXME: do this here? */
2122       GST_LOG ("found a case that will be optimized later.");
2123     } else {
2124       gchar *one = gst_structure_to_string (simplify);
2125       gchar *two = gst_structure_to_string (compare);
2126 
2127       GST_ERROR
2128           ("caps mismatch: structures %s and %s claim to be possible to unify, but aren't",
2129           one, two);
2130       g_free (one);
2131       g_free (two);
2132     }
2133     return ret;
2134   }
2135 
2136   return FALSE;
2137 }
2138 
2139 static void
gst_caps_switch_structures(GstCaps * caps,GstStructure * old,GstStructure * new,gint i)2140 gst_caps_switch_structures (GstCaps * caps, GstStructure * old,
2141     GstStructure * new, gint i)
2142 {
2143   gst_structure_set_parent_refcount (old, NULL);
2144   gst_structure_free (old);
2145   gst_structure_set_parent_refcount (new, &GST_CAPS_REFCOUNT (caps));
2146   g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, i).structure = new;
2147 }
2148 
2149 /**
2150  * gst_caps_simplify:
2151  * @caps: (transfer full): a #GstCaps to simplify
2152  *
2153  * Converts the given @caps into a representation that represents the
2154  * same set of formats, but in a simpler form.  Component structures that are
2155  * identical are merged.  Component structures that have values that can be
2156  * merged are also merged.
2157  *
2158  * This function takes ownership of @caps and will call gst_caps_make_writable()
2159  * on it if necessary, so you must not use @caps afterwards unless you keep an
2160  * additional reference to it with gst_caps_ref().
2161  *
2162  * This method does not preserve the original order of @caps.
2163  *
2164  * Returns: (transfer full): The simplified caps.
2165  */
2166 GstCaps *
gst_caps_simplify(GstCaps * caps)2167 gst_caps_simplify (GstCaps * caps)
2168 {
2169   GstStructure *simplify, *compare, *result = NULL;
2170   GstCapsFeatures *simplify_f, *compare_f;
2171   gint i, j, start;
2172 
2173   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
2174 
2175   /* empty/any caps are as simple as can be */
2176   if (GST_CAPS_LEN (caps) == 0)
2177     return caps;
2178 
2179   start = GST_CAPS_LEN (caps) - 1;
2180   /* one caps, already as simple as can be */
2181   if (start == 0)
2182     return caps;
2183 
2184   caps = gst_caps_make_writable (caps);
2185 
2186   g_array_sort (GST_CAPS_ARRAY (caps), gst_caps_compare_structures);
2187 
2188   for (i = start; i >= 0; i--) {
2189     simplify = gst_caps_get_structure_unchecked (caps, i);
2190     simplify_f = gst_caps_get_features_unchecked (caps, i);
2191     if (!simplify_f)
2192       simplify_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
2193     compare = gst_caps_get_structure_unchecked (caps, start);
2194     compare_f = gst_caps_get_features_unchecked (caps, start);
2195     if (!compare_f)
2196       compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
2197     if (gst_structure_get_name_id (simplify) !=
2198         gst_structure_get_name_id (compare) ||
2199         !gst_caps_features_is_equal (simplify_f, compare_f))
2200       start = i;
2201     for (j = start; j >= 0; j--) {
2202       if (j == i)
2203         continue;
2204       compare = gst_caps_get_structure_unchecked (caps, j);
2205       compare_f = gst_caps_get_features_unchecked (caps, j);
2206       if (!compare_f)
2207         compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
2208       if (gst_structure_get_name_id (simplify) !=
2209           gst_structure_get_name_id (compare) ||
2210           !gst_caps_features_is_equal (simplify_f, compare_f)) {
2211         break;
2212       }
2213       if (gst_caps_structure_simplify (&result, simplify, compare)) {
2214         if (result) {
2215           gst_caps_switch_structures (caps, simplify, result, i);
2216           simplify = result;
2217         } else {
2218           gst_caps_remove_structure (caps, i);
2219           start--;
2220           break;
2221         }
2222       }
2223     }
2224   }
2225   return caps;
2226 }
2227 
2228 /**
2229  * gst_caps_fixate:
2230  * @caps: (transfer full): a #GstCaps to fixate
2231  *
2232  * Modifies the given @caps into a representation with only fixed
2233  * values. First the caps will be truncated and then the first structure will be
2234  * fixated with gst_structure_fixate().
2235  *
2236  * This function takes ownership of @caps and will call gst_caps_make_writable()
2237  * on it so you must not use @caps afterwards unless you keep an additional
2238  * reference to it with gst_caps_ref().
2239  *
2240  * Note that it is not guaranteed that the returned caps have exactly one
2241  * structure. If @caps are empty caps then the returned caps will be
2242  * the empty too and contain no structure at all.
2243  *
2244  * Calling this function with ANY caps is not allowed.
2245  *
2246  * Returns: (transfer full): the fixated caps
2247  */
2248 GstCaps *
gst_caps_fixate(GstCaps * caps)2249 gst_caps_fixate (GstCaps * caps)
2250 {
2251   GstStructure *s;
2252   GstCapsFeatures *f;
2253 
2254   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
2255   g_return_val_if_fail (!CAPS_IS_ANY (caps), NULL);
2256 
2257   /* default fixation */
2258   caps = gst_caps_truncate (caps);
2259   caps = gst_caps_make_writable (caps);
2260 
2261   /* need to return early here because empty caps have no structure
2262    * but must return after make_writable() because the documentation
2263    * specifies that it will call make_writable() on the return value
2264    * and callers might assume writable caps.
2265    */
2266   if (CAPS_IS_EMPTY (caps))
2267     return caps;
2268 
2269   s = gst_caps_get_structure (caps, 0);
2270   gst_structure_fixate (s);
2271 
2272   /* Set features to sysmem if they're still ANY */
2273   f = gst_caps_get_features_unchecked (caps, 0);
2274   if (f && gst_caps_features_is_any (f)) {
2275     f = gst_caps_features_new_empty ();
2276     gst_caps_set_features (caps, 0, f);
2277   }
2278 
2279   return caps;
2280 }
2281 
2282 /* utility */
2283 
2284 static gchar *
caps_serialize(const GstCaps * caps,GstSerializeFlags flags)2285 caps_serialize (const GstCaps * caps, GstSerializeFlags flags)
2286 {
2287   guint i, slen, clen;
2288   GString *s;
2289   gboolean nested_structs_brackets =
2290       !(flags & GST_SERIALIZE_FLAG_BACKWARD_COMPAT);
2291 
2292   /* NOTE:  This function is potentially called by the debug system,
2293    * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.)
2294    * should be careful to avoid recursion.  This includes any functions
2295    * called by gst_caps_to_string.  In particular, calls should
2296    * not use the GST_PTR_FORMAT extension.  */
2297 
2298   if (caps == NULL) {
2299     return g_strdup ("NULL");
2300   }
2301   if (CAPS_IS_ANY (caps)) {
2302     return g_strdup ("ANY");
2303   }
2304   if (CAPS_IS_EMPTY_SIMPLE (caps)) {
2305     return g_strdup ("EMPTY");
2306   }
2307 
2308   /* estimate a rough string length to avoid unnecessary reallocs in GString */
2309   slen = 0;
2310   clen = GST_CAPS_LEN (caps);
2311   for (i = 0; i < clen; i++) {
2312     GstCapsFeatures *f;
2313 
2314     slen +=
2315         STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure_unchecked
2316         (caps, i));
2317     f = gst_caps_get_features_unchecked (caps, i);
2318     if (f)
2319       slen += FEATURES_ESTIMATED_STRING_LEN (f);
2320   }
2321 
2322   s = g_string_sized_new (slen);
2323   for (i = 0; i < clen; i++) {
2324     GstStructure *structure;
2325     GstCapsFeatures *features;
2326 
2327     if (i > 0) {
2328       /* ';' is now added by gst_structure_to_string */
2329       g_string_append_c (s, ' ');
2330     }
2331 
2332     structure = gst_caps_get_structure_unchecked (caps, i);
2333     features = gst_caps_get_features_unchecked (caps, i);
2334 
2335     g_string_append (s, gst_structure_get_name (structure));
2336     if (features && (gst_caps_features_is_any (features)
2337             || !gst_caps_features_is_equal (features,
2338                 GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) {
2339       g_string_append_c (s, '(');
2340       priv_gst_caps_features_append_to_gstring (features, s);
2341       g_string_append_c (s, ')');
2342     }
2343     priv_gst_structure_append_to_gstring (structure, s,
2344         nested_structs_brackets);
2345   }
2346   if (s->len && s->str[s->len - 1] == ';') {
2347     /* remove latest ';' */
2348     s->str[--s->len] = '\0';
2349   }
2350   return g_string_free (s, FALSE);
2351 }
2352 
2353 /**
2354  * gst_caps_to_string:
2355  * @caps: a #GstCaps
2356  *
2357  * Converts @caps to a string representation.  This string representation
2358  * can be converted back to a #GstCaps by gst_caps_from_string().
2359  *
2360  * For debugging purposes its easier to do something like this:
2361  *
2362  * ``` C
2363  * GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
2364  * ```
2365  *
2366  * This prints the caps in human readable form.
2367  *
2368  * The implementation of serialization up to 1.20 would lead to unexpected results
2369  * when there were nested #GstCaps / #GstStructure deeper than one level.
2370  *
2371  * Returns: (transfer full): a newly allocated string representing @caps.
2372  */
2373 gchar *
gst_caps_to_string(const GstCaps * caps)2374 gst_caps_to_string (const GstCaps * caps)
2375 {
2376   return caps_serialize (caps, GST_SERIALIZE_FLAG_BACKWARD_COMPAT);
2377 }
2378 
2379 /**
2380  * gst_caps_serialize:
2381  * @caps: a #GstCaps
2382  * @flags: a #GstSerializeFlags
2383  *
2384  * Converts @caps to a string representation.  This string representation can be
2385  * converted back to a #GstCaps by gst_caps_from_string().
2386  *
2387  * This prints the caps in human readable form.
2388  *
2389  * This version of the caps serialization function introduces support for nested
2390  * structures and caps but the resulting strings won't be parsable with
2391  * GStreamer prior to 1.20 unless #GST_SERIALIZE_FLAG_BACKWARD_COMPAT is passed
2392  * as @flag.
2393  *
2394  * Returns: (transfer full): a newly allocated string representing @caps.
2395  *
2396  * Since: 1.20
2397  */
2398 gchar *
gst_caps_serialize(const GstCaps * caps,GstSerializeFlags flags)2399 gst_caps_serialize (const GstCaps * caps, GstSerializeFlags flags)
2400 {
2401   return caps_serialize (caps, flags);
2402 }
2403 
2404 static gboolean
gst_caps_from_string_inplace(GstCaps * caps,const gchar * string)2405 gst_caps_from_string_inplace (GstCaps * caps, const gchar * string)
2406 {
2407   GstStructure *structure;
2408   gchar *s, *copy, *end, *next, save;
2409 
2410   if (strcmp ("ANY", string) == 0) {
2411     GST_CAPS_FLAGS (caps) = GST_CAPS_FLAG_ANY;
2412     return TRUE;
2413   }
2414 
2415   if (strcmp ("EMPTY", string) == 0 || strcmp ("NONE", string) == 0) {
2416     return TRUE;
2417   }
2418 
2419   copy = s = g_strdup (string);
2420   do {
2421     GstCapsFeatures *features = NULL;
2422 
2423     while (g_ascii_isspace (*s))
2424       s++;
2425     if (*s == '\0') {
2426       break;
2427     }
2428 
2429     if (!priv_gst_structure_parse_name (s, &s, &end, &next, FALSE)) {
2430       g_free (copy);
2431       return FALSE;
2432     }
2433 
2434     save = *end;
2435     *end = '\0';
2436     structure = gst_structure_new_empty (s);
2437     *end = save;
2438 
2439     if (structure == NULL) {
2440       g_free (copy);
2441       return FALSE;
2442     }
2443 
2444     s = next;
2445 
2446     if (*s == '\0') {
2447       goto append;
2448     }
2449 
2450     if (*s == '(') {
2451       s++;
2452       end = s;
2453 
2454       while (TRUE) {
2455         if (*end == '\0') {
2456           break;
2457         } else if (*end == ')') {
2458           break;
2459         } else {
2460           end++;
2461         }
2462       }
2463 
2464       save = *end;
2465       *end = '\0';
2466       features = gst_caps_features_from_string (s);
2467       if (!features) {
2468         gst_structure_free (structure);
2469         g_free (copy);
2470         return FALSE;
2471       }
2472       *end = save;
2473       s = end;
2474       if (save == ')')
2475         s++;
2476     }
2477 
2478     if (*s == '\0') {
2479       goto append;
2480     }
2481 
2482     if (!priv_gst_structure_parse_fields (s, &s, structure)) {
2483       gst_structure_free (structure);
2484       if (features)
2485         gst_caps_features_free (features);
2486       g_free (copy);
2487       return FALSE;
2488     }
2489 
2490   append:
2491     gst_caps_append_structure_unchecked (caps, structure, features);
2492     features = NULL;
2493     if (*s == '\0')
2494       break;
2495   } while (TRUE);
2496 
2497   g_free (copy);
2498 
2499   return TRUE;
2500 }
2501 
2502 /**
2503  * gst_caps_from_string:
2504  * @string: a string to convert to #GstCaps
2505  *
2506  * Converts @caps from a string representation.
2507  *
2508  * The implementation of serialization up to 1.20 would lead to unexpected results
2509  * when there were nested #GstCaps / #GstStructure deeper than one level.
2510  *
2511  * Returns: (transfer full) (nullable): a newly allocated #GstCaps
2512  */
2513 GstCaps *
gst_caps_from_string(const gchar * string)2514 gst_caps_from_string (const gchar * string)
2515 {
2516   GstCaps *caps;
2517 
2518   g_return_val_if_fail (string, NULL);
2519 
2520   caps = gst_caps_new_empty ();
2521   if (gst_caps_from_string_inplace (caps, string)) {
2522     return caps;
2523   } else {
2524     gst_caps_unref (caps);
2525     return NULL;
2526   }
2527 }
2528 
2529 static void
gst_caps_transform_to_string(const GValue * src_value,GValue * dest_value)2530 gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value)
2531 {
2532   g_return_if_fail (G_IS_VALUE (src_value));
2533   g_return_if_fail (G_IS_VALUE (dest_value));
2534   g_return_if_fail (G_VALUE_HOLDS (src_value, GST_TYPE_CAPS));
2535   g_return_if_fail (G_VALUE_HOLDS (dest_value, G_TYPE_STRING)
2536       || G_VALUE_HOLDS (dest_value, G_TYPE_POINTER));
2537 
2538   g_value_take_string (dest_value,
2539       gst_caps_to_string (gst_value_get_caps (src_value)));
2540 }
2541 
2542 /**
2543  * gst_caps_foreach:
2544  * @caps: a #GstCaps
2545  * @func: (scope call): a function to call for each field
2546  * @user_data: (closure): private data
2547  *
2548  * Calls the provided function once for each structure and caps feature in the
2549  * #GstCaps. The function must not modify the fields.
2550  * Also see gst_caps_map_in_place() and gst_caps_filter_and_map_in_place().
2551  *
2552  * Returns: %TRUE if the supplied function returns %TRUE for each call,
2553  * %FALSE otherwise.
2554  *
2555  * Since: 1.6
2556  */
2557 gboolean
gst_caps_foreach(const GstCaps * caps,GstCapsForeachFunc func,gpointer user_data)2558 gst_caps_foreach (const GstCaps * caps, GstCapsForeachFunc func,
2559     gpointer user_data)
2560 {
2561   guint i, n;
2562   GstCapsFeatures *features;
2563   GstStructure *structure;
2564   gboolean ret;
2565 
2566   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
2567   g_return_val_if_fail (func != NULL, FALSE);
2568 
2569   n = GST_CAPS_LEN (caps);
2570 
2571   for (i = 0; i < n; i++) {
2572     features = gst_caps_get_features_unchecked (caps, i);
2573     structure = gst_caps_get_structure_unchecked (caps, i);
2574 
2575     ret = func (features, structure, user_data);
2576     if (G_UNLIKELY (!ret))
2577       return FALSE;
2578   }
2579 
2580   return TRUE;
2581 }
2582 
2583 /**
2584  * gst_caps_map_in_place:
2585  * @caps: a #GstCaps
2586  * @func: (scope call): a function to call for each field
2587  * @user_data: (closure): private data
2588  *
2589  * Calls the provided function once for each structure and caps feature in the
2590  * #GstCaps. In contrast to gst_caps_foreach(), the function may modify but not
2591  * delete the structures and features. The caps must be mutable.
2592  *
2593  * Returns: %TRUE if the supplied function returns %TRUE for each call,
2594  * %FALSE otherwise.
2595  *
2596  * Since: 1.6
2597  */
2598 gboolean
gst_caps_map_in_place(GstCaps * caps,GstCapsMapFunc func,gpointer user_data)2599 gst_caps_map_in_place (GstCaps * caps, GstCapsMapFunc func, gpointer user_data)
2600 {
2601   guint i, n;
2602   GstCapsFeatures *features;
2603   GstStructure *structure;
2604   gboolean ret;
2605 
2606   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
2607   g_return_val_if_fail (gst_caps_is_writable (caps), FALSE);
2608   g_return_val_if_fail (func != NULL, FALSE);
2609 
2610   n = GST_CAPS_LEN (caps);
2611 
2612   for (i = 0; i < n; i++) {
2613     features = gst_caps_get_features_unchecked (caps, i);
2614     structure = gst_caps_get_structure_unchecked (caps, i);
2615 
2616     /* Provide sysmem features if there are none yet */
2617     if (!features) {
2618       features =
2619           gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
2620       gst_caps_set_features (caps, i, features);
2621     }
2622 
2623     ret = func (features, structure, user_data);
2624     if (G_UNLIKELY (!ret))
2625       return FALSE;
2626   }
2627 
2628   return TRUE;
2629 }
2630 
2631 /**
2632  * gst_caps_filter_and_map_in_place:
2633  * @caps: a #GstCaps
2634  * @func: (scope call): a function to call for each field
2635  * @user_data: (closure): private data
2636  *
2637  * Calls the provided function once for each structure and caps feature in the
2638  * #GstCaps. In contrast to gst_caps_foreach(), the function may modify the
2639  * structure and features. In contrast to gst_caps_filter_and_map_in_place(),
2640  * the structure and features are removed from the caps if %FALSE is returned
2641  * from the function.
2642  * The caps must be mutable.
2643  *
2644  * Since: 1.6
2645  */
2646 void
gst_caps_filter_and_map_in_place(GstCaps * caps,GstCapsFilterMapFunc func,gpointer user_data)2647 gst_caps_filter_and_map_in_place (GstCaps * caps, GstCapsFilterMapFunc func,
2648     gpointer user_data)
2649 {
2650   guint i, n;
2651   GstCapsFeatures *features;
2652   GstStructure *structure;
2653   gboolean ret;
2654 
2655   g_return_if_fail (GST_IS_CAPS (caps));
2656   g_return_if_fail (gst_caps_is_writable (caps));
2657   g_return_if_fail (func != NULL);
2658 
2659   n = GST_CAPS_LEN (caps);
2660 
2661   for (i = 0; i < n;) {
2662     features = gst_caps_get_features_unchecked (caps, i);
2663     structure = gst_caps_get_structure_unchecked (caps, i);
2664 
2665     /* Provide sysmem features if there are none yet */
2666     if (!features) {
2667       features =
2668           gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
2669       gst_caps_set_features (caps, i, features);
2670     }
2671 
2672     ret = func (features, structure, user_data);
2673     if (!ret) {
2674       GST_CAPS_ARRAY (caps) = g_array_remove_index (GST_CAPS_ARRAY (caps), i);
2675 
2676       gst_structure_set_parent_refcount (structure, NULL);
2677       gst_structure_free (structure);
2678       if (features) {
2679         gst_caps_features_set_parent_refcount (features, NULL);
2680         gst_caps_features_free (features);
2681       }
2682 
2683       n = GST_CAPS_LEN (caps);
2684     } else {
2685       i++;
2686     }
2687   }
2688 }
2689 
2690 /**
2691  * gst_caps_copy:
2692  * @caps: a #GstCaps.
2693  *
2694  * Creates a new #GstCaps as a copy of the old @caps. The new caps will have a
2695  * refcount of 1, owned by the caller. The structures are copied as well.
2696  *
2697  * Note that this function is the semantic equivalent of a gst_caps_ref()
2698  * followed by a gst_caps_make_writable(). If you only want to hold on to a
2699  * reference to the data, you should use gst_caps_ref().
2700  *
2701  * Returns: (transfer full): the new #GstCaps
2702  */
2703 GstCaps *(gst_caps_copy) (const GstCaps * caps)
2704 {
2705   return GST_CAPS (gst_mini_object_copy (GST_MINI_OBJECT_CAST (caps)));
2706 }
2707 
2708 /**
2709  * gst_caps_ref: (skip)
2710  * @caps: the #GstCaps to reference
2711  *
2712  * Adds a reference to a #GstCaps object.
2713  *
2714  * From this point on, until the caller calls gst_caps_unref() or
2715  * gst_caps_make_writable(), it is guaranteed that the caps object will not
2716  * change. This means its structures won't change, etc. To use a #GstCaps
2717  * object, you must always have a refcount on it -- either the one made
2718  * implicitly by e.g. gst_caps_new_simple(), or via taking one explicitly with
2719  * this function.
2720  *
2721  * Returns: the same #GstCaps object.
2722  */
2723 GstCaps *
gst_caps_ref(GstCaps * caps)2724 gst_caps_ref (GstCaps * caps)
2725 {
2726   return (GstCaps *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (caps));
2727 }
2728 
2729 /**
2730  * gst_caps_unref: (skip)
2731  * @caps: a #GstCaps.
2732  *
2733  * Unrefs a #GstCaps and frees all its structures and the
2734  * structures' values when the refcount reaches 0.
2735  */
2736 void
gst_caps_unref(GstCaps * caps)2737 gst_caps_unref (GstCaps * caps)
2738 {
2739   gst_mini_object_unref (GST_MINI_OBJECT_CAST (caps));
2740 }
2741 
2742 /**
2743  * gst_clear_caps: (skip)
2744  * @caps_ptr: a pointer to a #GstCaps reference
2745  *
2746  * Clears a reference to a #GstCaps.
2747  *
2748  * @caps_ptr must not be %NULL.
2749  *
2750  * If the reference is %NULL then this function does nothing. Otherwise, the
2751  * reference count of the caps is decreased and the pointer is set to %NULL.
2752  *
2753  * Since: 1.16
2754  */
2755 void
gst_clear_caps(GstCaps ** caps_ptr)2756 gst_clear_caps (GstCaps ** caps_ptr)
2757 {
2758   gst_clear_mini_object ((GstMiniObject **) caps_ptr);
2759 }
2760 
2761 /**
2762  * gst_caps_replace: (skip)
2763  * @old_caps: (inout) (transfer full) (nullable): pointer to a pointer
2764  *     to a #GstCaps to be replaced.
2765  * @new_caps: (transfer none) (allow-none): pointer to a #GstCaps that will
2766  *     replace the caps pointed to by @old_caps.
2767  *
2768  * Modifies a pointer to a #GstCaps to point to a different #GstCaps. The
2769  * modification is done atomically (so this is useful for ensuring thread safety
2770  * in some cases), and the reference counts are updated appropriately (the old
2771  * caps is unreffed, the new is reffed).
2772  *
2773  * Either @new_caps or the #GstCaps pointed to by @old_caps may be %NULL.
2774  *
2775  * Returns: %TRUE if @new_caps was different from @old_caps
2776  */
2777 gboolean
gst_caps_replace(GstCaps ** old_caps,GstCaps * new_caps)2778 gst_caps_replace (GstCaps ** old_caps, GstCaps * new_caps)
2779 {
2780   return gst_mini_object_replace ((GstMiniObject **) old_caps,
2781       (GstMiniObject *) new_caps);
2782 }
2783 
2784 /**
2785  * gst_caps_take: (skip)
2786  * @old_caps: (inout) (transfer full): pointer to a pointer to a #GstCaps to be
2787  *     replaced.
2788  * @new_caps: (transfer full) (allow-none): pointer to a #GstCaps that will
2789  *     replace the caps pointed to by @old_caps.
2790  *
2791  * Modifies a pointer to a #GstCaps to point to a different #GstCaps. This
2792  * function is similar to gst_caps_replace() except that it takes ownership
2793  * of @new_caps.
2794  *
2795  * Returns: %TRUE if @new_caps was different from @old_caps
2796  */
2797 gboolean
gst_caps_take(GstCaps ** old_caps,GstCaps * new_caps)2798 gst_caps_take (GstCaps ** old_caps, GstCaps * new_caps)
2799 {
2800   return gst_mini_object_take ((GstMiniObject **) old_caps,
2801       (GstMiniObject *) new_caps);
2802 }
2803