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