• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *                    2002 Thomas Vander Stichele <thomas@apestaart.org>
5  *                    2004 Wim Taymans <wim@fluendo.com>
6  *                    2015 Jan Schmidt <jan@centricular.com>
7  *
8  * gstutils.c: Utility functions
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25 
26 /**
27  * SECTION:gstutils
28  * @title: GstUtils
29  * @short_description: Various utility functions
30  *
31  */
32 
33 /* FIXME 2.0: suppress warnings for deprecated API such as GValueArray
34  * with newer GLib versions (>= 2.31.0) */
35 #define GLIB_DISABLE_DEPRECATION_WARNINGS
36 
37 #include "gst_private.h"
38 #include <stdio.h>
39 #include <string.h>
40 
41 #include "gstghostpad.h"
42 #include "gstutils.h"
43 #include "gsterror.h"
44 #include "gstinfo.h"
45 #include "gstparse.h"
46 #include "gstvalue.h"
47 #include "gstquark.h"
48 #include "gst-i18n-lib.h"
49 #include "glib-compat-private.h"
50 #include <math.h>
51 
52 
53 static void
gst_util_dump_mem_offset(const guchar * mem,guint size,guint offset)54 gst_util_dump_mem_offset (const guchar * mem, guint size, guint offset)
55 {
56   guint i, j;
57   GString *string = g_string_sized_new (50);
58   GString *chars = g_string_sized_new (18);
59 
60   i = j = 0;
61   while (i < size) {
62     if (g_ascii_isprint (mem[i]))
63       g_string_append_c (chars, mem[i]);
64     else
65       g_string_append_c (chars, '.');
66 
67     g_string_append_printf (string, "%02x ", mem[i]);
68 
69     j++;
70     i++;
71 
72     if (j == 16 || i == size) {
73       g_print ("%08x (%p): %-48.48s %-16.16s\n", i - j + offset, mem + i - j,
74           string->str, chars->str);
75       g_string_set_size (string, 0);
76       g_string_set_size (chars, 0);
77       j = 0;
78     }
79   }
80   g_string_free (string, TRUE);
81   g_string_free (chars, TRUE);
82 }
83 
84 /**
85  * gst_util_dump_mem:
86  * @mem: (array length=size): a pointer to the memory to dump
87  * @size: the size of the memory block to dump
88  *
89  * Dumps the memory block into a hex representation. Useful for debugging.
90  */
91 void
gst_util_dump_mem(const guchar * mem,guint size)92 gst_util_dump_mem (const guchar * mem, guint size)
93 {
94   gst_util_dump_mem_offset (mem, size, 0);
95 }
96 
97 /**
98  * gst_util_dump_buffer:
99  * @buf: a #GstBuffer whose memory to dump
100  *
101  * Dumps the buffer memory into a hex representation. Useful for debugging.
102  *
103  * Since: 1.14
104  */
105 void
gst_util_dump_buffer(GstBuffer * buf)106 gst_util_dump_buffer (GstBuffer * buf)
107 {
108   GstMapInfo map;
109   GstMemory *mem;
110   guint n_memory;
111   guint i;
112   guint offset;
113 
114   n_memory = gst_buffer_n_memory (buf);
115 
116   if (n_memory == 1) {
117     if (gst_buffer_map (buf, &map, GST_MAP_READ)) {
118       gst_util_dump_mem (map.data, map.size);
119       gst_buffer_unmap (buf, &map);
120     }
121   } else if (n_memory > 1) {
122     /* gst_buffer_map() will merge multiple memory segments into one contiguous
123      * area so we need to use gst_memory_map() in order not to affect the
124      * contents of buf */
125     offset = 0;
126     for (i = 0; i < n_memory; ++i) {
127       g_print ("[Memory #%u]\n", i);
128       mem = gst_buffer_get_memory (buf, i);
129       if (gst_memory_map (mem, &map, GST_MAP_READ)) {
130         gst_util_dump_mem_offset (map.data, map.size, offset);
131         offset += map.size;
132         gst_memory_unmap (mem, &map);
133       }
134       gst_memory_unref (mem);
135     }
136   } else {
137     g_print ("[Empty]\n");
138   }
139 }
140 
141 /**
142  * gst_util_set_value_from_string:
143  * @value: (out caller-allocates): the value to set
144  * @value_str: the string to get the value from
145  *
146  * Converts the string to the type of the value and
147  * sets the value with it.
148  *
149  * Note that this function is dangerous as it does not return any indication
150  * if the conversion worked or not.
151  */
152 void
gst_util_set_value_from_string(GValue * value,const gchar * value_str)153 gst_util_set_value_from_string (GValue * value, const gchar * value_str)
154 {
155   gboolean res;
156 
157   g_return_if_fail (value != NULL);
158   g_return_if_fail (value_str != NULL);
159 
160   GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
161       g_type_name (G_VALUE_TYPE (value)));
162 
163   res = gst_value_deserialize (value, value_str);
164   if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
165     /* backwards compat, all booleans that fail to parse are false */
166     g_value_set_boolean (value, FALSE);
167     res = TRUE;
168   }
169   g_return_if_fail (res);
170 }
171 
172 /**
173  * gst_util_set_object_arg:
174  * @object: the object to set the argument of
175  * @name: the name of the argument to set
176  * @value: the string value to set
177  *
178  * Converts the string value to the type of the objects argument and
179  * sets the argument with it.
180  *
181  * Note that this function silently returns if @object has no property named
182  * @name or when @value cannot be converted to the type of the property.
183  */
184 void
gst_util_set_object_arg(GObject * object,const gchar * name,const gchar * value)185 gst_util_set_object_arg (GObject * object, const gchar * name,
186     const gchar * value)
187 {
188   GParamSpec *pspec;
189   GType value_type;
190   GValue v = { 0, };
191 
192   g_return_if_fail (G_IS_OBJECT (object));
193   g_return_if_fail (name != NULL);
194   g_return_if_fail (value != NULL);
195 
196   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
197   if (!pspec)
198     return;
199 
200   value_type = pspec->value_type;
201 
202   GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s",
203       pspec->flags, g_type_name (value_type));
204 
205   if (!(pspec->flags & G_PARAM_WRITABLE))
206     return;
207 
208   g_value_init (&v, value_type);
209 
210   /* special case for element <-> xml (de)serialisation */
211   if (value_type == GST_TYPE_STRUCTURE && strcmp (value, "NULL") == 0) {
212     g_value_set_boxed (&v, NULL);
213     goto done;
214   }
215 
216   if (!gst_value_deserialize_with_pspec (&v, value, pspec))
217     return;
218 
219 done:
220 
221   g_object_set_property (object, pspec->name, &v);
222   g_value_unset (&v);
223 }
224 
225 /**
226  * gst_util_set_object_array:
227  * @object: the object to set the array to
228  * @name: the name of the property to set
229  * @array: a #GValueArray containing the values
230  *
231  * Transfer a #GValueArray to %GST_TYPE_ARRAY and set this value on the
232  * specified property name. This allow language bindings to set GST_TYPE_ARRAY
233  * properties which are otherwise not an accessible type.
234  *
235  * Since: 1.12
236  */
237 gboolean
gst_util_set_object_array(GObject * object,const gchar * name,const GValueArray * array)238 gst_util_set_object_array (GObject * object, const gchar * name,
239     const GValueArray * array)
240 {
241   GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
242   gboolean ret = FALSE;
243 
244   g_value_init (&v1, G_TYPE_VALUE_ARRAY);
245   g_value_init (&v2, GST_TYPE_ARRAY);
246 
247   g_value_set_static_boxed (&v1, array);
248 
249   if (g_value_transform (&v1, &v2)) {
250     g_object_set_property (object, name, &v2);
251     ret = TRUE;
252   }
253 
254   g_value_unset (&v1);
255   g_value_unset (&v2);
256 
257   return ret;
258 }
259 
260 /**
261  * gst_util_get_object_array:
262  * @object: the object to set the array to
263  * @name: the name of the property to set
264  * @array: (out): a return #GValueArray
265  *
266  * Get a property of type %GST_TYPE_ARRAY and transform it into a
267  * #GValueArray. This allow language bindings to get GST_TYPE_ARRAY
268  * properties which are otherwise not an accessible type.
269  *
270  * Since: 1.12
271  */
272 gboolean
gst_util_get_object_array(GObject * object,const gchar * name,GValueArray ** array)273 gst_util_get_object_array (GObject * object, const gchar * name,
274     GValueArray ** array)
275 {
276   GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
277   gboolean ret = FALSE;
278 
279   g_value_init (&v1, G_TYPE_VALUE_ARRAY);
280   g_value_init (&v2, GST_TYPE_ARRAY);
281 
282   g_object_get_property (object, name, &v2);
283 
284   if (g_value_transform (&v2, &v1)) {
285     *array = g_value_get_boxed (&v1);
286     ret = TRUE;
287   }
288 
289   g_value_unset (&v2);
290 
291   return ret;
292 }
293 
294 /* work around error C2520: conversion from unsigned __int64 to double
295  * not implemented, use signed __int64
296  *
297  * These are implemented as functions because on some platforms a 64bit int to
298  * double conversion is not defined/implemented.
299  */
300 
301 /**
302  * gst_util_guint64_to_gdouble:
303  * @value: The #guint64 value to convert to double
304  *
305  * Returns: @value casted to #gdouble
306  */
307 gdouble
gst_util_guint64_to_gdouble(guint64 value)308 gst_util_guint64_to_gdouble (guint64 value)
309 {
310   if (value & G_GINT64_CONSTANT (0x8000000000000000))
311     return (gdouble) ((gint64) value) + (gdouble) 18446744073709551616.;
312   else
313     return (gdouble) ((gint64) value);
314 }
315 
316 /**
317  * gst_util_gdouble_to_guint64:
318  * @value: The #gdouble value to convert guint64 double
319  *
320  * Returns: @value casted to #guint64
321  */
322 guint64
gst_util_gdouble_to_guint64(gdouble value)323 gst_util_gdouble_to_guint64 (gdouble value)
324 {
325   if (value < (gdouble) 9223372036854775808.)   /* 1 << 63 */
326     return ((guint64) ((gint64) value));
327 
328   value -= (gdouble) 18446744073709551616.;
329   return ((guint64) ((gint64) value));
330 }
331 
332 #ifndef HAVE_UINT128_T
333 /* convenience struct for getting high and low uint32 parts of
334  * a guint64 */
335 typedef union
336 {
337   guint64 ll;
338   struct
339   {
340 #if G_BYTE_ORDER == G_BIG_ENDIAN
341     guint32 high, low;
342 #else
343     guint32 low, high;
344 #endif
345   } l;
346 } GstUInt64;
347 
348 #if defined (__x86_64__) && defined (__GNUC__)
349 static inline void
gst_util_uint64_mul_uint64(GstUInt64 * c1,GstUInt64 * c0,guint64 arg1,guint64 arg2)350 gst_util_uint64_mul_uint64 (GstUInt64 * c1, GstUInt64 * c0, guint64 arg1,
351     guint64 arg2)
352 {
353   __asm__ __volatile__ ("mulq %3":"=a" (c0->ll), "=d" (c1->ll)
354       :"a" (arg1), "g" (arg2)
355       );
356 }
357 #else /* defined (__x86_64__) */
358 /* multiply two 64-bit unsigned ints into a 128-bit unsigned int.  the high
359  * and low 64 bits of the product are placed in c1 and c0 respectively.
360  * this operation cannot overflow. */
361 static inline void
gst_util_uint64_mul_uint64(GstUInt64 * c1,GstUInt64 * c0,guint64 arg1,guint64 arg2)362 gst_util_uint64_mul_uint64 (GstUInt64 * c1, GstUInt64 * c0, guint64 arg1,
363     guint64 arg2)
364 {
365   GstUInt64 a1, b0;
366   GstUInt64 v, n;
367 
368   /* prepare input */
369   v.ll = arg1;
370   n.ll = arg2;
371 
372   /* do 128 bits multiply
373    *                   nh   nl
374    *                *  vh   vl
375    *                ----------
376    * a0 =              vl * nl
377    * a1 =         vl * nh
378    * b0 =         vh * nl
379    * b1 =  + vh * nh
380    *       -------------------
381    *        c1h  c1l  c0h  c0l
382    *
383    * "a0" is optimized away, result is stored directly in c0.  "b1" is
384    * optimized away, result is stored directly in c1.
385    */
386   c0->ll = (guint64) v.l.low * n.l.low;
387   a1.ll = (guint64) v.l.low * n.l.high;
388   b0.ll = (guint64) v.l.high * n.l.low;
389 
390   /* add the high word of a0 to the low words of a1 and b0 using c1 as
391    * scratch space to capture the carry.  the low word of the result becomes
392    * the final high word of c0 */
393   c1->ll = (guint64) c0->l.high + a1.l.low + b0.l.low;
394   c0->l.high = c1->l.low;
395 
396   /* add the carry from the result above (found in the high word of c1) and
397    * the high words of a1 and b0 to b1, the result is c1. */
398   c1->ll = (guint64) v.l.high * n.l.high + c1->l.high + a1.l.high + b0.l.high;
399 }
400 #endif /* defined (__x86_64__) */
401 
402 #if defined (__x86_64__) && defined (__GNUC__)
403 static inline guint64
gst_util_div128_64(GstUInt64 c1,GstUInt64 c0,guint64 denom)404 gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom)
405 {
406   guint64 res;
407 
408   __asm__ __volatile__ ("divq %3":"=a" (res)
409       :"d" (c1.ll), "a" (c0.ll), "g" (denom)
410       );
411 
412   return res;
413 }
414 #else
415 /* count leading zeros */
416 static inline guint
gst_util_clz(guint32 val)417 gst_util_clz (guint32 val)
418 {
419   guint s;
420 
421   s = val | (val >> 1);
422   s |= (s >> 2);
423   s |= (s >> 4);
424   s |= (s >> 8);
425   s = ~(s | (s >> 16));
426   s = s - ((s >> 1) & 0x55555555);
427   s = (s & 0x33333333) + ((s >> 2) & 0x33333333);
428   s = (s + (s >> 4)) & 0x0f0f0f0f;
429   s += (s >> 8);
430   s = (s + (s >> 16)) & 0x3f;
431 
432   return s;
433 }
434 
435 /* based on Hacker's Delight p152 */
436 static inline guint64
gst_util_div128_64(GstUInt64 c1,GstUInt64 c0,guint64 denom)437 gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom)
438 {
439   GstUInt64 q1, q0, rhat;
440   GstUInt64 v, cmp1, cmp2;
441   guint s;
442 
443   v.ll = denom;
444 
445   /* count number of leading zeroes, we know they must be in the high
446    * part of denom since denom > G_MAXUINT32. */
447   s = gst_util_clz (v.l.high);
448 
449   if (s > 0) {
450     /* normalize divisor and dividend */
451     v.ll <<= s;
452     c1.ll = (c1.ll << s) | (c0.l.high >> (32 - s));
453     c0.ll <<= s;
454   }
455 
456   q1.ll = c1.ll / v.l.high;
457   rhat.ll = c1.ll - q1.ll * v.l.high;
458 
459   cmp1.l.high = rhat.l.low;
460   cmp1.l.low = c0.l.high;
461   cmp2.ll = q1.ll * v.l.low;
462 
463   while (q1.l.high || cmp2.ll > cmp1.ll) {
464     q1.ll--;
465     rhat.ll += v.l.high;
466     if (rhat.l.high)
467       break;
468     cmp1.l.high = rhat.l.low;
469     cmp2.ll -= v.l.low;
470   }
471   c1.l.high = c1.l.low;
472   c1.l.low = c0.l.high;
473   c1.ll -= q1.ll * v.ll;
474   q0.ll = c1.ll / v.l.high;
475   rhat.ll = c1.ll - q0.ll * v.l.high;
476 
477   cmp1.l.high = rhat.l.low;
478   cmp1.l.low = c0.l.low;
479   cmp2.ll = q0.ll * v.l.low;
480 
481   while (q0.l.high || cmp2.ll > cmp1.ll) {
482     q0.ll--;
483     rhat.ll += v.l.high;
484     if (rhat.l.high)
485       break;
486     cmp1.l.high = rhat.l.low;
487     cmp2.ll -= v.l.low;
488   }
489   q0.l.high += q1.l.low;
490 
491   return q0.ll;
492 }
493 #endif /* defined (__GNUC__) */
494 
495 /* This always gives the correct result because:
496  * a) val <= G_MAXUINT64-1
497  * b) (c0,c1) <= G_MAXUINT64 * (G_MAXUINT64-1)
498  *    or
499  *    (c0,c1) == G_MAXUINT64 * G_MAXUINT64 and denom < G_MAXUINT64
500  *    (note: num==denom case is handled by short path)
501  * This means that (c0,c1) either has enough space for val
502  * or that the overall result will overflow anyway.
503  */
504 
505 /* add correction with carry */
506 #define CORRECT(c0,c1,val)                    \
507   if (val) {                                  \
508     if (G_MAXUINT64 - c0.ll < val) {          \
509       if (G_UNLIKELY (c1.ll == G_MAXUINT64))  \
510         /* overflow */                        \
511         return G_MAXUINT64;                   \
512       c1.ll++;                                \
513     }                                         \
514     c0.ll += val;                             \
515   }
516 
517 static guint64
gst_util_uint64_scale_uint64_unchecked(guint64 val,guint64 num,guint64 denom,guint64 correct)518 gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num,
519     guint64 denom, guint64 correct)
520 {
521   GstUInt64 c1, c0;
522 
523   /* compute 128-bit numerator product */
524   gst_util_uint64_mul_uint64 (&c1, &c0, val, num);
525 
526   /* perform rounding correction */
527   CORRECT (c0, c1, correct);
528 
529   /* high word as big as or bigger than denom --> overflow */
530   if (G_UNLIKELY (c1.ll >= denom))
531     return G_MAXUINT64;
532 
533   /* compute quotient, fits in 64 bits */
534   return gst_util_div128_64 (c1, c0, denom);
535 }
536 #else
537 
538 #define GST_MAXUINT128 ((__uint128_t) -1)
539 static guint64
gst_util_uint64_scale_uint64_unchecked(guint64 val,guint64 num,guint64 denom,guint64 correct)540 gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num,
541     guint64 denom, guint64 correct)
542 {
543   __uint128_t tmp;
544 
545   /* Calculate val * num */
546   tmp = ((__uint128_t) val) * ((__uint128_t) num);
547 
548   /* overflow checks */
549   if (G_UNLIKELY (GST_MAXUINT128 - correct < tmp))
550     return G_MAXUINT64;
551 
552   /* perform rounding correction */
553   tmp += correct;
554 
555   /* Divide by denom */
556   tmp /= denom;
557 
558   /* if larger than G_MAXUINT64 --> overflow */
559   if (G_UNLIKELY (tmp > G_MAXUINT64))
560     return G_MAXUINT64;
561 
562   /* compute quotient, fits in 64 bits */
563   return (guint64) tmp;
564 }
565 
566 #endif
567 
568 #if !defined (__x86_64__) && !defined (HAVE_UINT128_T)
569 static inline void
gst_util_uint64_mul_uint32(GstUInt64 * c1,GstUInt64 * c0,guint64 arg1,guint32 arg2)570 gst_util_uint64_mul_uint32 (GstUInt64 * c1, GstUInt64 * c0, guint64 arg1,
571     guint32 arg2)
572 {
573   GstUInt64 a;
574 
575   a.ll = arg1;
576 
577   c0->ll = (guint64) a.l.low * arg2;
578   c1->ll = (guint64) a.l.high * arg2 + c0->l.high;
579   c0->l.high = 0;
580 }
581 
582 /* divide a 96-bit unsigned int by a 32-bit unsigned int when we know the
583  * quotient fits into 64 bits.  the high 64 bits and low 32 bits of the
584  * numerator are expected in c1 and c0 respectively. */
585 static inline guint64
gst_util_div96_32(guint64 c1,guint64 c0,guint32 denom)586 gst_util_div96_32 (guint64 c1, guint64 c0, guint32 denom)
587 {
588   c0 += (c1 % denom) << 32;
589   return ((c1 / denom) << 32) + (c0 / denom);
590 }
591 
592 static inline guint64
gst_util_uint64_scale_uint32_unchecked(guint64 val,guint32 num,guint32 denom,guint32 correct)593 gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num,
594     guint32 denom, guint32 correct)
595 {
596   GstUInt64 c1, c0;
597 
598   /* compute 96-bit numerator product */
599   gst_util_uint64_mul_uint32 (&c1, &c0, val, num);
600 
601   /* condition numerator based on rounding mode */
602   CORRECT (c0, c1, correct);
603 
604   /* high 32 bits as big as or bigger than denom --> overflow */
605   if (G_UNLIKELY (c1.l.high >= denom))
606     return G_MAXUINT64;
607 
608   /* compute quotient, fits in 64 bits */
609   return gst_util_div96_32 (c1.ll, c0.ll, denom);
610 }
611 #endif
612 
613 /* the guts of the gst_util_uint64_scale() variants */
614 static guint64
_gst_util_uint64_scale(guint64 val,guint64 num,guint64 denom,guint64 correct)615 _gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom,
616     guint64 correct)
617 {
618   g_return_val_if_fail (denom != 0, G_MAXUINT64);
619 
620   if (G_UNLIKELY (num == 0))
621     return 0;
622 
623   if (G_UNLIKELY (num == denom))
624     return val;
625 
626   /* on 64bits we always use a full 128bits multiply/division */
627 #if !defined (__x86_64__) && !defined (HAVE_UINT128_T)
628   /* denom is low --> try to use 96 bit muldiv */
629   if (G_LIKELY (denom <= G_MAXUINT32)) {
630     /* num is low --> use 96 bit muldiv */
631     if (G_LIKELY (num <= G_MAXUINT32))
632       return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num,
633           (guint32) denom, correct);
634 
635     /* num is high but val is low --> swap and use 96-bit muldiv */
636     if (G_LIKELY (val <= G_MAXUINT32))
637       return gst_util_uint64_scale_uint32_unchecked (num, (guint32) val,
638           (guint32) denom, correct);
639   }
640 #endif /* !defined (__x86_64__) && !defined (HAVE_UINT128_T) */
641 
642   /* val is high and num is high --> use 128-bit muldiv */
643   return gst_util_uint64_scale_uint64_unchecked (val, num, denom, correct);
644 }
645 
646 /**
647  * gst_util_uint64_scale:
648  * @val: the number to scale
649  * @num: the numerator of the scale ratio
650  * @denom: the denominator of the scale ratio
651  *
652  * Scale @val by the rational number @num / @denom, avoiding overflows and
653  * underflows and without loss of precision.
654  *
655  * This function can potentially be very slow if val and num are both
656  * greater than G_MAXUINT32.
657  *
658  * Returns: @val * @num / @denom.  In the case of an overflow, this
659  * function returns G_MAXUINT64.  If the result is not exactly
660  * representable as an integer it is truncated.  See also
661  * gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil(),
662  * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(),
663  * gst_util_uint64_scale_int_ceil().
664  */
665 guint64
gst_util_uint64_scale(guint64 val,guint64 num,guint64 denom)666 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
667 {
668   return _gst_util_uint64_scale (val, num, denom, 0);
669 }
670 
671 /**
672  * gst_util_uint64_scale_round:
673  * @val: the number to scale
674  * @num: the numerator of the scale ratio
675  * @denom: the denominator of the scale ratio
676  *
677  * Scale @val by the rational number @num / @denom, avoiding overflows and
678  * underflows and without loss of precision.
679  *
680  * This function can potentially be very slow if val and num are both
681  * greater than G_MAXUINT32.
682  *
683  * Returns: @val * @num / @denom.  In the case of an overflow, this
684  * function returns G_MAXUINT64.  If the result is not exactly
685  * representable as an integer, it is rounded to the nearest integer
686  * (half-way cases are rounded up).  See also gst_util_uint64_scale(),
687  * gst_util_uint64_scale_ceil(), gst_util_uint64_scale_int(),
688  * gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil().
689  */
690 guint64
gst_util_uint64_scale_round(guint64 val,guint64 num,guint64 denom)691 gst_util_uint64_scale_round (guint64 val, guint64 num, guint64 denom)
692 {
693   return _gst_util_uint64_scale (val, num, denom, denom >> 1);
694 }
695 
696 /**
697  * gst_util_uint64_scale_ceil:
698  * @val: the number to scale
699  * @num: the numerator of the scale ratio
700  * @denom: the denominator of the scale ratio
701  *
702  * Scale @val by the rational number @num / @denom, avoiding overflows and
703  * underflows and without loss of precision.
704  *
705  * This function can potentially be very slow if val and num are both
706  * greater than G_MAXUINT32.
707  *
708  * Returns: @val * @num / @denom.  In the case of an overflow, this
709  * function returns G_MAXUINT64.  If the result is not exactly
710  * representable as an integer, it is rounded up.  See also
711  * gst_util_uint64_scale(), gst_util_uint64_scale_round(),
712  * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(),
713  * gst_util_uint64_scale_int_ceil().
714  */
715 guint64
gst_util_uint64_scale_ceil(guint64 val,guint64 num,guint64 denom)716 gst_util_uint64_scale_ceil (guint64 val, guint64 num, guint64 denom)
717 {
718   return _gst_util_uint64_scale (val, num, denom, denom - 1);
719 }
720 
721 /* the guts of the gst_util_uint64_scale_int() variants */
722 static guint64
_gst_util_uint64_scale_int(guint64 val,gint num,gint denom,gint correct)723 _gst_util_uint64_scale_int (guint64 val, gint num, gint denom, gint correct)
724 {
725   g_return_val_if_fail (denom > 0, G_MAXUINT64);
726   g_return_val_if_fail (num >= 0, G_MAXUINT64);
727 
728   if (G_UNLIKELY (num == 0))
729     return 0;
730 
731   if (G_UNLIKELY (num == denom))
732     return val;
733 
734   if (val <= G_MAXUINT32) {
735     /* simple case.  num and denom are not negative so casts are OK.  when
736      * not truncating, the additions to the numerator cannot overflow
737      * because val*num <= G_MAXUINT32 * G_MAXINT32 < G_MAXUINT64 -
738      * G_MAXINT32, so there's room to add another gint32. */
739     val *= (guint64) num;
740     /* add rounding correction */
741     val += correct;
742 
743     return val / (guint64) denom;
744   }
745 #if !defined (__x86_64__) && !defined (HAVE_UINT128_T)
746   /* num and denom are not negative so casts are OK */
747   return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num,
748       (guint32) denom, (guint32) correct);
749 #else
750   /* always use full 128bits scale */
751   return gst_util_uint64_scale_uint64_unchecked (val, num, denom, correct);
752 #endif
753 }
754 
755 /**
756  * gst_util_uint64_scale_int:
757  * @val: guint64 (such as a #GstClockTime) to scale.
758  * @num: numerator of the scale factor.
759  * @denom: denominator of the scale factor.
760  *
761  * Scale @val by the rational number @num / @denom, avoiding overflows and
762  * underflows and without loss of precision.  @num must be non-negative and
763  * @denom must be positive.
764  *
765  * Returns: @val * @num / @denom.  In the case of an overflow, this
766  * function returns G_MAXUINT64.  If the result is not exactly
767  * representable as an integer, it is truncated.  See also
768  * gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil(),
769  * gst_util_uint64_scale(), gst_util_uint64_scale_round(),
770  * gst_util_uint64_scale_ceil().
771  */
772 guint64
gst_util_uint64_scale_int(guint64 val,gint num,gint denom)773 gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
774 {
775   return _gst_util_uint64_scale_int (val, num, denom, 0);
776 }
777 
778 /**
779  * gst_util_uint64_scale_int_round:
780  * @val: guint64 (such as a #GstClockTime) to scale.
781  * @num: numerator of the scale factor.
782  * @denom: denominator of the scale factor.
783  *
784  * Scale @val by the rational number @num / @denom, avoiding overflows and
785  * underflows and without loss of precision.  @num must be non-negative and
786  * @denom must be positive.
787  *
788  * Returns: @val * @num / @denom.  In the case of an overflow, this
789  * function returns G_MAXUINT64.  If the result is not exactly
790  * representable as an integer, it is rounded to the nearest integer
791  * (half-way cases are rounded up).  See also gst_util_uint64_scale_int(),
792  * gst_util_uint64_scale_int_ceil(), gst_util_uint64_scale(),
793  * gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil().
794  */
795 guint64
gst_util_uint64_scale_int_round(guint64 val,gint num,gint denom)796 gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom)
797 {
798   /* we can use a shift to divide by 2 because denom is required to be
799    * positive. */
800   return _gst_util_uint64_scale_int (val, num, denom, denom >> 1);
801 }
802 
803 /**
804  * gst_util_uint64_scale_int_ceil:
805  * @val: guint64 (such as a #GstClockTime) to scale.
806  * @num: numerator of the scale factor.
807  * @denom: denominator of the scale factor.
808  *
809  * Scale @val by the rational number @num / @denom, avoiding overflows and
810  * underflows and without loss of precision.  @num must be non-negative and
811  * @denom must be positive.
812  *
813  * Returns: @val * @num / @denom.  In the case of an overflow, this
814  * function returns G_MAXUINT64.  If the result is not exactly
815  * representable as an integer, it is rounded up.  See also
816  * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(),
817  * gst_util_uint64_scale(), gst_util_uint64_scale_round(),
818  * gst_util_uint64_scale_ceil().
819  */
820 guint64
gst_util_uint64_scale_int_ceil(guint64 val,gint num,gint denom)821 gst_util_uint64_scale_int_ceil (guint64 val, gint num, gint denom)
822 {
823   return _gst_util_uint64_scale_int (val, num, denom, denom - 1);
824 }
825 
826 /**
827  * gst_util_seqnum_next:
828  *
829  * Return a constantly incrementing sequence number.
830  *
831  * This function is used internally to GStreamer to be able to determine which
832  * events and messages are "the same". For example, elements may set the seqnum
833  * on a segment-done message to be the same as that of the last seek event, to
834  * indicate that event and the message correspond to the same segment.
835  *
836  * This function never returns %GST_SEQNUM_INVALID (which is 0).
837  *
838  * Returns: A constantly incrementing 32-bit unsigned integer, which might
839  * overflow at some point. Use gst_util_seqnum_compare() to make sure
840  * you handle wraparound correctly.
841  */
842 guint32
gst_util_seqnum_next(void)843 gst_util_seqnum_next (void)
844 {
845   static gint counter = 1;
846   gint ret = g_atomic_int_add (&counter, 1);
847 
848   /* Make sure we don't return 0 */
849   if (G_UNLIKELY (ret == GST_SEQNUM_INVALID))
850     ret = g_atomic_int_add (&counter, 1);
851 
852   return ret;
853 }
854 
855 /**
856  * gst_util_seqnum_compare:
857  * @s1: A sequence number.
858  * @s2: Another sequence number.
859  *
860  * Compare two sequence numbers, handling wraparound.
861  *
862  * The current implementation just returns (gint32)(@s1 - @s2).
863  *
864  * Returns: A negative number if @s1 is before @s2, 0 if they are equal, or a
865  * positive number if @s1 is after @s2.
866  */
867 gint32
gst_util_seqnum_compare(guint32 s1,guint32 s2)868 gst_util_seqnum_compare (guint32 s1, guint32 s2)
869 {
870   return (gint32) (s1 - s2);
871 }
872 
873 /* -----------------------------------------------------
874  *
875  *  The following code will be moved out of the main
876  * gstreamer library someday.
877  */
878 
879 #include "gstpad.h"
880 
881 /**
882  * gst_element_create_all_pads:
883  * @element: (transfer none): a #GstElement to create pads for
884  *
885  * Creates a pad for each pad template that is always available.
886  * This function is only useful during object initialization of
887  * subclasses of #GstElement.
888  */
889 void
gst_element_create_all_pads(GstElement * element)890 gst_element_create_all_pads (GstElement * element)
891 {
892   GList *padlist;
893 
894   /* FIXME: lock element */
895 
896   padlist =
897       gst_element_class_get_pad_template_list (GST_ELEMENT_CLASS
898       (G_OBJECT_GET_CLASS (element)));
899 
900   while (padlist) {
901     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
902 
903     if (padtempl->presence == GST_PAD_ALWAYS) {
904       GstPad *pad;
905 
906       pad = gst_pad_new_from_template (padtempl, padtempl->name_template);
907 
908       gst_element_add_pad (element, pad);
909     }
910     padlist = padlist->next;
911   }
912 }
913 
914 /**
915  * gst_element_get_compatible_pad_template:
916  * @element: (transfer none): a #GstElement to get a compatible pad template for
917  * @compattempl: (transfer none): the #GstPadTemplate to find a compatible
918  *     template for
919  *
920  * Retrieves a pad template from @element that is compatible with @compattempl.
921  * Pads from compatible templates can be linked together.
922  *
923  * Returns: (transfer none) (nullable): a compatible #GstPadTemplate,
924  *   or %NULL if none was found. No unreferencing is necessary.
925  */
926 GstPadTemplate *
gst_element_get_compatible_pad_template(GstElement * element,GstPadTemplate * compattempl)927 gst_element_get_compatible_pad_template (GstElement * element,
928     GstPadTemplate * compattempl)
929 {
930   GstPadTemplate *newtempl = NULL;
931   GList *padlist;
932   GstElementClass *class;
933   gboolean compatible;
934 
935   g_return_val_if_fail (element != NULL, NULL);
936   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
937   g_return_val_if_fail (compattempl != NULL, NULL);
938 
939   class = GST_ELEMENT_GET_CLASS (element);
940 
941   padlist = gst_element_class_get_pad_template_list (class);
942 
943   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
944       "Looking for a suitable pad template in %s out of %d templates...",
945       GST_ELEMENT_NAME (element), g_list_length (padlist));
946 
947   while (padlist) {
948     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
949 
950     /* Ignore name
951      * Ignore presence
952      * Check direction (must be opposite)
953      * Check caps
954      */
955     GST_CAT_LOG (GST_CAT_CAPS,
956         "checking pad template %s", padtempl->name_template);
957     if (padtempl->direction != compattempl->direction) {
958       GST_CAT_DEBUG (GST_CAT_CAPS,
959           "compatible direction: found %s pad template \"%s\"",
960           padtempl->direction == GST_PAD_SRC ? "src" : "sink",
961           padtempl->name_template);
962 
963       GST_CAT_DEBUG (GST_CAT_CAPS,
964           "intersecting %" GST_PTR_FORMAT, GST_PAD_TEMPLATE_CAPS (compattempl));
965       GST_CAT_DEBUG (GST_CAT_CAPS,
966           "..and %" GST_PTR_FORMAT, GST_PAD_TEMPLATE_CAPS (padtempl));
967 
968       compatible = gst_caps_can_intersect (GST_PAD_TEMPLATE_CAPS (compattempl),
969           GST_PAD_TEMPLATE_CAPS (padtempl));
970 
971       GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible",
972           (compatible ? "" : "not "));
973 
974       if (compatible) {
975         newtempl = padtempl;
976         break;
977       }
978     }
979 
980     padlist = g_list_next (padlist);
981   }
982   if (newtempl)
983     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
984         "Returning new pad template %p", newtempl);
985   else
986     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "No compatible pad template found");
987 
988   return newtempl;
989 }
990 
991 /**
992  * gst_element_get_pad_from_template:
993  * @element: (transfer none): a #GstElement.
994  * @templ: (transfer none): a #GstPadTemplate belonging to @element.
995  *
996  * Gets a pad from @element described by @templ. If the presence of @templ is
997  * #GST_PAD_REQUEST, requests a new pad. Can return %NULL for #GST_PAD_SOMETIMES
998  * templates.
999  *
1000  * Returns: (transfer full) (nullable): the #GstPad, or %NULL if one
1001  *   could not be found or created.
1002  */
1003 static GstPad *
gst_element_get_pad_from_template(GstElement * element,GstPadTemplate * templ)1004 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
1005 {
1006   GstPad *ret = NULL;
1007   GstPadPresence presence;
1008 
1009   /* If this function is ever exported, we need check the validity of `element'
1010    * and `templ', and to make sure the template actually belongs to the
1011    * element. */
1012 
1013   presence = GST_PAD_TEMPLATE_PRESENCE (templ);
1014 
1015   switch (presence) {
1016     case GST_PAD_ALWAYS:
1017     case GST_PAD_SOMETIMES:
1018       ret = gst_element_get_static_pad (element, templ->name_template);
1019       if (!ret && presence == GST_PAD_ALWAYS)
1020         g_warning
1021             ("Element %s has an ALWAYS template %s, but no pad of the same name",
1022             GST_OBJECT_NAME (element), templ->name_template);
1023       break;
1024 
1025     case GST_PAD_REQUEST:
1026       ret = gst_element_request_pad (element, templ, NULL, NULL);
1027       break;
1028   }
1029 
1030   return ret;
1031 }
1032 
1033 /*
1034  * gst_element_request_compatible_pad:
1035  * @element: a #GstElement.
1036  * @templ: the #GstPadTemplate to which the new pad should be able to link.
1037  *
1038  * Requests a pad from @element. The returned pad should be unlinked and
1039  * compatible with @templ. Might return an existing pad, or request a new one.
1040  *
1041  * Returns: (nullable): a #GstPad, or %NULL if one could not be found
1042  *   or created.
1043  */
1044 static GstPad *
gst_element_request_compatible_pad(GstElement * element,GstPadTemplate * templ)1045 gst_element_request_compatible_pad (GstElement * element,
1046     GstPadTemplate * templ)
1047 {
1048   GstPadTemplate *templ_new;
1049   GstPad *pad = NULL;
1050 
1051   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1052   g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
1053 
1054   /* FIXME: should really loop through the templates, testing each for
1055    *      compatibility and pad availability. */
1056   templ_new = gst_element_get_compatible_pad_template (element, templ);
1057   if (templ_new)
1058     pad = gst_element_get_pad_from_template (element, templ_new);
1059   /* This can happen for non-request pads. */
1060   if (pad && GST_PAD_PEER (pad)) {
1061     gst_object_unref (pad);
1062     pad = NULL;
1063   }
1064 
1065   return pad;
1066 }
1067 
1068 /*
1069  * Checks if the source pad and the sink pad can be linked.
1070  * Both @srcpad and @sinkpad must be unlinked and have a parent.
1071  */
1072 static gboolean
gst_pad_check_link(GstPad * srcpad,GstPad * sinkpad)1073 gst_pad_check_link (GstPad * srcpad, GstPad * sinkpad)
1074 {
1075   /* generic checks */
1076   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
1077   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
1078 
1079   GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
1080       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1081 
1082   if (GST_PAD_PEER (srcpad) != NULL) {
1083     GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed",
1084         GST_DEBUG_PAD_NAME (srcpad));
1085     return FALSE;
1086   }
1087   if (GST_PAD_PEER (sinkpad) != NULL) {
1088     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed",
1089         GST_DEBUG_PAD_NAME (sinkpad));
1090     return FALSE;
1091   }
1092   if (!GST_PAD_IS_SRC (srcpad)) {
1093     GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed",
1094         GST_DEBUG_PAD_NAME (srcpad));
1095     return FALSE;
1096   }
1097   if (!GST_PAD_IS_SINK (sinkpad)) {
1098     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed",
1099         GST_DEBUG_PAD_NAME (sinkpad));
1100     return FALSE;
1101   }
1102   if (GST_PAD_PARENT (srcpad) == NULL) {
1103     GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed",
1104         GST_DEBUG_PAD_NAME (srcpad));
1105     return FALSE;
1106   }
1107   if (GST_PAD_PARENT (sinkpad) == NULL) {
1108     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed",
1109         GST_DEBUG_PAD_NAME (srcpad));
1110     return FALSE;
1111   }
1112 
1113   return TRUE;
1114 }
1115 
1116 /**
1117  * gst_element_get_compatible_pad:
1118  * @element: (transfer none): a #GstElement in which the pad should be found.
1119  * @pad: (transfer none): the #GstPad to find a compatible one for.
1120  * @caps: (allow-none): the #GstCaps to use as a filter.
1121  *
1122  * Looks for an unlinked pad to which the given pad can link. It is not
1123  * guaranteed that linking the pads will work, though it should work in most
1124  * cases.
1125  *
1126  * This function will first attempt to find a compatible unlinked ALWAYS pad,
1127  * and if none can be found, it will request a compatible REQUEST pad by looking
1128  * at the templates of @element.
1129  *
1130  * Returns: (transfer full) (nullable): the #GstPad to which a link
1131  *   can be made, or %NULL if one cannot be found. gst_object_unref()
1132  *   after usage.
1133  */
1134 GstPad *
gst_element_get_compatible_pad(GstElement * element,GstPad * pad,GstCaps * caps)1135 gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
1136     GstCaps * caps)
1137 {
1138   GstIterator *pads;
1139   GstPadTemplate *templ;
1140   GstCaps *templcaps;
1141   GstPad *foundpad = NULL;
1142   gboolean done;
1143   GValue padptr = { 0, };
1144 
1145   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1146   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1147 
1148   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1149       "finding pad in %s compatible with %s:%s",
1150       GST_ELEMENT_NAME (element), GST_DEBUG_PAD_NAME (pad));
1151 
1152   g_return_val_if_fail (GST_PAD_PEER (pad) == NULL, NULL);
1153 
1154   done = FALSE;
1155 
1156   /* try to get an existing unlinked pad */
1157   if (GST_PAD_IS_SRC (pad)) {
1158     pads = gst_element_iterate_sink_pads (element);
1159   } else if (GST_PAD_IS_SINK (pad)) {
1160     pads = gst_element_iterate_src_pads (element);
1161   } else {
1162     pads = gst_element_iterate_pads (element);
1163   }
1164 
1165   while (!done) {
1166     switch (gst_iterator_next (pads, &padptr)) {
1167       case GST_ITERATOR_OK:
1168       {
1169         GstPad *peer;
1170         GstPad *current;
1171         GstPad *srcpad;
1172         GstPad *sinkpad;
1173 
1174         current = g_value_get_object (&padptr);
1175 
1176         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
1177             GST_DEBUG_PAD_NAME (current));
1178 
1179         if (GST_PAD_IS_SRC (current)) {
1180           srcpad = current;
1181           sinkpad = pad;
1182         } else {
1183           srcpad = pad;
1184           sinkpad = current;
1185         }
1186         peer = gst_pad_get_peer (current);
1187 
1188         if (peer == NULL && gst_pad_check_link (srcpad, sinkpad)) {
1189           GstCaps *temp, *intersection;
1190           gboolean compatible;
1191 
1192           /* Now check if the two pads' caps are compatible */
1193           temp = gst_pad_query_caps (pad, NULL);
1194           if (caps) {
1195             intersection = gst_caps_intersect (temp, caps);
1196             gst_caps_unref (temp);
1197           } else {
1198             intersection = temp;
1199           }
1200 
1201           temp = gst_pad_query_caps (current, NULL);
1202           compatible = gst_caps_can_intersect (temp, intersection);
1203           gst_caps_unref (temp);
1204           gst_caps_unref (intersection);
1205 
1206           if (compatible) {
1207             GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1208                 "found existing unlinked compatible pad %s:%s",
1209                 GST_DEBUG_PAD_NAME (current));
1210             gst_iterator_free (pads);
1211 
1212             current = gst_object_ref (current);
1213             g_value_unset (&padptr);
1214 
1215             return current;
1216           } else {
1217             GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "incompatible pads");
1218           }
1219         } else {
1220           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1221               "already linked or cannot be linked (peer = %p)", peer);
1222         }
1223         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
1224 
1225         g_value_reset (&padptr);
1226         if (peer)
1227           gst_object_unref (peer);
1228         break;
1229       }
1230       case GST_ITERATOR_DONE:
1231         done = TRUE;
1232         break;
1233       case GST_ITERATOR_RESYNC:
1234         gst_iterator_resync (pads);
1235         break;
1236       case GST_ITERATOR_ERROR:
1237         g_assert_not_reached ();
1238         break;
1239     }
1240   }
1241   g_value_unset (&padptr);
1242   gst_iterator_free (pads);
1243 
1244   GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
1245       "Could not find a compatible unlinked always pad to link to %s:%s, now checking request pads",
1246       GST_DEBUG_PAD_NAME (pad));
1247 
1248   /* try to create a new one */
1249   /* requesting is a little crazy, we need a template. Let's create one */
1250   templcaps = gst_pad_query_caps (pad, NULL);
1251   if (caps) {
1252     GstCaps *inter = gst_caps_intersect (templcaps, caps);
1253 
1254     gst_caps_unref (templcaps);
1255     templcaps = inter;
1256   }
1257   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
1258       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
1259   gst_caps_unref (templcaps);
1260 
1261   foundpad = gst_element_request_compatible_pad (element, templ);
1262   gst_object_unref (templ);
1263 
1264   if (foundpad) {
1265     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1266         "found existing request pad %s:%s", GST_DEBUG_PAD_NAME (foundpad));
1267     return foundpad;
1268   }
1269 
1270   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element,
1271       "Could not find a compatible pad to link to %s:%s",
1272       GST_DEBUG_PAD_NAME (pad));
1273   return NULL;
1274 }
1275 
1276 /**
1277  * gst_element_state_get_name:
1278  * @state: a #GstState to get the name of.
1279  *
1280  * Gets a string representing the given state.
1281  *
1282  * Returns: (transfer none): a string with the name of the state.
1283  */
1284 const gchar *
gst_element_state_get_name(GstState state)1285 gst_element_state_get_name (GstState state)
1286 {
1287   switch (state) {
1288     case GST_STATE_VOID_PENDING:
1289       return "VOID_PENDING";
1290     case GST_STATE_NULL:
1291       return "NULL";
1292     case GST_STATE_READY:
1293       return "READY";
1294     case GST_STATE_PLAYING:
1295       return "PLAYING";
1296     case GST_STATE_PAUSED:
1297       return "PAUSED";
1298     default:
1299       /* This is a memory leak */
1300       return g_strdup_printf ("UNKNOWN!(%d)", state);
1301   }
1302 }
1303 
1304 /**
1305  * gst_element_state_change_return_get_name:
1306  * @state_ret: a #GstStateChangeReturn to get the name of.
1307  *
1308  * Gets a string representing the given state change result.
1309  *
1310  * Returns: (transfer none): a string with the name of the state
1311  *    result.
1312  */
1313 const gchar *
gst_element_state_change_return_get_name(GstStateChangeReturn state_ret)1314 gst_element_state_change_return_get_name (GstStateChangeReturn state_ret)
1315 {
1316   switch (state_ret) {
1317     case GST_STATE_CHANGE_FAILURE:
1318       return "FAILURE";
1319     case GST_STATE_CHANGE_SUCCESS:
1320       return "SUCCESS";
1321     case GST_STATE_CHANGE_ASYNC:
1322       return "ASYNC";
1323     case GST_STATE_CHANGE_NO_PREROLL:
1324       return "NO PREROLL";
1325     default:
1326       /* This is a memory leak */
1327       return g_strdup_printf ("UNKNOWN!(%d)", state_ret);
1328   }
1329 }
1330 
1331 /**
1332  * gst_state_change_get_name:
1333  * @transition: a #GstStateChange to get the name of.
1334  *
1335  * Gets a string representing the given state transition.
1336  *
1337  * Returns: (transfer none): a string with the name of the state
1338  *    result.
1339  *
1340  * Since: 1.14
1341  */
1342 const gchar *
gst_state_change_get_name(GstStateChange transition)1343 gst_state_change_get_name (GstStateChange transition)
1344 {
1345   switch (transition) {
1346     case GST_STATE_CHANGE_NULL_TO_READY:
1347       return "NULL->READY";
1348     case GST_STATE_CHANGE_READY_TO_PAUSED:
1349       return "READY->PAUSED";
1350     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1351       return "PAUSED->PLAYING";
1352     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1353       return "PLAYING->PAUSED";
1354     case GST_STATE_CHANGE_PAUSED_TO_READY:
1355       return "PAUSED->READY";
1356     case GST_STATE_CHANGE_READY_TO_NULL:
1357       return "READY->NULL";
1358     case GST_STATE_CHANGE_NULL_TO_NULL:
1359       return "NULL->NULL";
1360     case GST_STATE_CHANGE_READY_TO_READY:
1361       return "READY->READY";
1362     case GST_STATE_CHANGE_PAUSED_TO_PAUSED:
1363       return "PAUSED->PAUSED";
1364     case GST_STATE_CHANGE_PLAYING_TO_PLAYING:
1365       return "PLAYING->PLAYING";
1366   }
1367 
1368   return "Unknown state return";
1369 }
1370 
1371 
1372 static gboolean
gst_element_factory_can_accept_all_caps_in_direction(GstElementFactory * factory,const GstCaps * caps,GstPadDirection direction)1373 gst_element_factory_can_accept_all_caps_in_direction (GstElementFactory *
1374     factory, const GstCaps * caps, GstPadDirection direction)
1375 {
1376   GList *templates;
1377 
1378   g_return_val_if_fail (factory != NULL, FALSE);
1379   g_return_val_if_fail (caps != NULL, FALSE);
1380 
1381   templates = factory->staticpadtemplates;
1382 
1383   while (templates) {
1384     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
1385 
1386     if (template->direction == direction) {
1387       GstCaps *templcaps = gst_static_caps_get (&template->static_caps);
1388 
1389       if (gst_caps_is_always_compatible (caps, templcaps)) {
1390         gst_caps_unref (templcaps);
1391         return TRUE;
1392       }
1393       gst_caps_unref (templcaps);
1394     }
1395     templates = g_list_next (templates);
1396   }
1397 
1398   return FALSE;
1399 }
1400 
1401 static gboolean
gst_element_factory_can_accept_any_caps_in_direction(GstElementFactory * factory,const GstCaps * caps,GstPadDirection direction)1402 gst_element_factory_can_accept_any_caps_in_direction (GstElementFactory *
1403     factory, const GstCaps * caps, GstPadDirection direction)
1404 {
1405   GList *templates;
1406 
1407   g_return_val_if_fail (factory != NULL, FALSE);
1408   g_return_val_if_fail (caps != NULL, FALSE);
1409 
1410   templates = factory->staticpadtemplates;
1411 
1412   while (templates) {
1413     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
1414 
1415     if (template->direction == direction) {
1416       GstCaps *templcaps = gst_static_caps_get (&template->static_caps);
1417 
1418       if (gst_caps_can_intersect (caps, templcaps)) {
1419         gst_caps_unref (templcaps);
1420         return TRUE;
1421       }
1422       gst_caps_unref (templcaps);
1423     }
1424     templates = g_list_next (templates);
1425   }
1426 
1427   return FALSE;
1428 }
1429 
1430 /**
1431  * gst_element_factory_can_sink_all_caps:
1432  * @factory: factory to query
1433  * @caps: the caps to check
1434  *
1435  * Checks if the factory can sink all possible capabilities.
1436  *
1437  * Returns: %TRUE if the caps are fully compatible.
1438  */
1439 gboolean
gst_element_factory_can_sink_all_caps(GstElementFactory * factory,const GstCaps * caps)1440 gst_element_factory_can_sink_all_caps (GstElementFactory * factory,
1441     const GstCaps * caps)
1442 {
1443   return gst_element_factory_can_accept_all_caps_in_direction (factory, caps,
1444       GST_PAD_SINK);
1445 }
1446 
1447 /**
1448  * gst_element_factory_can_src_all_caps:
1449  * @factory: factory to query
1450  * @caps: the caps to check
1451  *
1452  * Checks if the factory can src all possible capabilities.
1453  *
1454  * Returns: %TRUE if the caps are fully compatible.
1455  */
1456 gboolean
gst_element_factory_can_src_all_caps(GstElementFactory * factory,const GstCaps * caps)1457 gst_element_factory_can_src_all_caps (GstElementFactory * factory,
1458     const GstCaps * caps)
1459 {
1460   return gst_element_factory_can_accept_all_caps_in_direction (factory, caps,
1461       GST_PAD_SRC);
1462 }
1463 
1464 /**
1465  * gst_element_factory_can_sink_any_caps:
1466  * @factory: factory to query
1467  * @caps: the caps to check
1468  *
1469  * Checks if the factory can sink any possible capability.
1470  *
1471  * Returns: %TRUE if the caps have a common subset.
1472  */
1473 gboolean
gst_element_factory_can_sink_any_caps(GstElementFactory * factory,const GstCaps * caps)1474 gst_element_factory_can_sink_any_caps (GstElementFactory * factory,
1475     const GstCaps * caps)
1476 {
1477   return gst_element_factory_can_accept_any_caps_in_direction (factory, caps,
1478       GST_PAD_SINK);
1479 }
1480 
1481 /**
1482  * gst_element_factory_can_src_any_caps:
1483  * @factory: factory to query
1484  * @caps: the caps to check
1485  *
1486  * Checks if the factory can src any possible capability.
1487  *
1488  * Returns: %TRUE if the caps have a common subset.
1489  */
1490 gboolean
gst_element_factory_can_src_any_caps(GstElementFactory * factory,const GstCaps * caps)1491 gst_element_factory_can_src_any_caps (GstElementFactory * factory,
1492     const GstCaps * caps)
1493 {
1494   return gst_element_factory_can_accept_any_caps_in_direction (factory, caps,
1495       GST_PAD_SRC);
1496 }
1497 
1498 /* if return val is true, *direct_child is a caller-owned ref on the direct
1499  * child of ancestor that is part of object's ancestry */
1500 static gboolean
object_has_ancestor(GstObject * object,GstObject * ancestor,GstObject ** direct_child)1501 object_has_ancestor (GstObject * object, GstObject * ancestor,
1502     GstObject ** direct_child)
1503 {
1504   GstObject *child, *parent;
1505 
1506   if (direct_child)
1507     *direct_child = NULL;
1508 
1509   child = gst_object_ref (object);
1510   parent = gst_object_get_parent (object);
1511 
1512   while (parent) {
1513     if (ancestor == parent) {
1514       if (direct_child)
1515         *direct_child = child;
1516       else
1517         gst_object_unref (child);
1518       gst_object_unref (parent);
1519       return TRUE;
1520     }
1521 
1522     gst_object_unref (child);
1523     child = parent;
1524     parent = gst_object_get_parent (parent);
1525   }
1526 
1527   gst_object_unref (child);
1528 
1529   return FALSE;
1530 }
1531 
1532 /* caller owns return */
1533 static GstObject *
find_common_root(GstObject * o1,GstObject * o2)1534 find_common_root (GstObject * o1, GstObject * o2)
1535 {
1536   GstObject *top = o1;
1537   GstObject *kid1, *kid2;
1538   GstObject *root = NULL;
1539 
1540   while (GST_OBJECT_PARENT (top))
1541     top = GST_OBJECT_PARENT (top);
1542 
1543   /* the itsy-bitsy spider... */
1544 
1545   if (!object_has_ancestor (o2, top, &kid2))
1546     return NULL;
1547 
1548   root = gst_object_ref (top);
1549   while (TRUE) {
1550     if (!object_has_ancestor (o1, kid2, &kid1)) {
1551       gst_object_unref (kid2);
1552       return root;
1553     }
1554     gst_object_unref (root);
1555     root = kid2;
1556     if (!object_has_ancestor (o2, kid1, &kid2)) {
1557       gst_object_unref (kid1);
1558       return root;
1559     }
1560     gst_object_unref (root);
1561     root = kid1;
1562   }
1563 }
1564 
1565 /* caller does not own return */
1566 static GstPad *
ghost_up(GstElement * e,GstPad * pad)1567 ghost_up (GstElement * e, GstPad * pad)
1568 {
1569   static gint ghost_pad_index = 0;
1570   GstPad *gpad;
1571   gchar *name;
1572   GstState current;
1573   GstState next;
1574   GstObject *parent = GST_OBJECT_PARENT (e);
1575 
1576   name = g_strdup_printf ("ghost%d", ghost_pad_index++);
1577   gpad = gst_ghost_pad_new (name, pad);
1578   g_free (name);
1579 
1580   GST_STATE_LOCK (parent);
1581   gst_element_get_state (GST_ELEMENT (parent), &current, &next, 0);
1582 
1583   if (current > GST_STATE_READY || next >= GST_STATE_PAUSED)
1584     gst_pad_set_active (gpad, TRUE);
1585 
1586   if (!gst_element_add_pad ((GstElement *) parent, gpad)) {
1587     g_warning ("Pad named %s already exists in element %s\n",
1588         GST_OBJECT_NAME (gpad), GST_OBJECT_NAME (parent));
1589     GST_STATE_UNLOCK (parent);
1590     return NULL;
1591   }
1592   GST_STATE_UNLOCK (parent);
1593 
1594   return gpad;
1595 }
1596 
1597 static void
remove_pad(gpointer ppad,gpointer unused)1598 remove_pad (gpointer ppad, gpointer unused)
1599 {
1600   GstPad *pad = ppad;
1601 
1602   if (!gst_element_remove_pad ((GstElement *) GST_OBJECT_PARENT (pad), pad))
1603     g_warning ("Couldn't remove pad %s from element %s",
1604         GST_OBJECT_NAME (pad), GST_OBJECT_NAME (GST_OBJECT_PARENT (pad)));
1605 }
1606 
1607 static gboolean
prepare_link_maybe_ghosting(GstPad ** src,GstPad ** sink,GSList ** pads_created)1608 prepare_link_maybe_ghosting (GstPad ** src, GstPad ** sink,
1609     GSList ** pads_created)
1610 {
1611   GstObject *root;
1612   GstObject *e1, *e2;
1613   GSList *pads_created_local = NULL;
1614 
1615   g_assert (pads_created);
1616 
1617   e1 = GST_OBJECT_PARENT (*src);
1618   e2 = GST_OBJECT_PARENT (*sink);
1619 
1620   if (G_UNLIKELY (e1 == NULL)) {
1621     GST_WARNING ("Trying to ghost a pad that doesn't have a parent: %"
1622         GST_PTR_FORMAT, *src);
1623     return FALSE;
1624   }
1625   if (G_UNLIKELY (e2 == NULL)) {
1626     GST_WARNING ("Trying to ghost a pad that doesn't have a parent: %"
1627         GST_PTR_FORMAT, *sink);
1628     return FALSE;
1629   }
1630 
1631   if (GST_OBJECT_PARENT (e1) == GST_OBJECT_PARENT (e2)) {
1632     GST_CAT_INFO (GST_CAT_PADS, "%s and %s in same bin, no need for ghost pads",
1633         GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2));
1634     return TRUE;
1635   }
1636 
1637   GST_CAT_INFO (GST_CAT_PADS, "%s and %s not in same bin, making ghost pads",
1638       GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2));
1639 
1640   /* we need to setup some ghost pads */
1641   root = find_common_root (e1, e2);
1642   if (!root) {
1643     if (GST_OBJECT_PARENT (e1) == NULL)
1644       g_warning ("Trying to link elements %s and %s that don't share a common "
1645           "ancestor: %s hasn't been added to a bin or pipeline, but %s is in %s",
1646           GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2),
1647           GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2),
1648           GST_ELEMENT_NAME (GST_OBJECT_PARENT (e2)));
1649     else if (GST_OBJECT_PARENT (e2) == NULL)
1650       g_warning ("Trying to link elements %s and %s that don't share a common "
1651           "ancestor: %s hasn't been added to a bin or pipeline, and %s is in %s",
1652           GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2),
1653           GST_ELEMENT_NAME (e2), GST_ELEMENT_NAME (e1),
1654           GST_ELEMENT_NAME (GST_OBJECT_PARENT (e1)));
1655     else
1656       g_warning ("Trying to link elements %s and %s that don't share a common "
1657           "ancestor: %s is in %s, and %s is in %s",
1658           GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2),
1659           GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (GST_OBJECT_PARENT (e1)),
1660           GST_ELEMENT_NAME (e2), GST_ELEMENT_NAME (GST_OBJECT_PARENT (e2)));
1661     return FALSE;
1662   }
1663 
1664   while (GST_OBJECT_PARENT (e1) != root) {
1665     *src = ghost_up ((GstElement *) e1, *src);
1666     if (!*src)
1667       goto cleanup_fail;
1668     e1 = GST_OBJECT_PARENT (*src);
1669     pads_created_local = g_slist_prepend (pads_created_local, *src);
1670   }
1671   while (GST_OBJECT_PARENT (e2) != root) {
1672     *sink = ghost_up ((GstElement *) e2, *sink);
1673     if (!*sink)
1674       goto cleanup_fail;
1675     e2 = GST_OBJECT_PARENT (*sink);
1676     pads_created_local = g_slist_prepend (pads_created_local, *sink);
1677   }
1678 
1679   gst_object_unref (root);
1680   *pads_created = g_slist_concat (*pads_created, pads_created_local);
1681   return TRUE;
1682 
1683 cleanup_fail:
1684   gst_object_unref (root);
1685   g_slist_foreach (pads_created_local, remove_pad, NULL);
1686   g_slist_free (pads_created_local);
1687   return FALSE;
1688 }
1689 
1690 static gboolean
pad_link_maybe_ghosting(GstPad * src,GstPad * sink,GstPadLinkCheck flags)1691 pad_link_maybe_ghosting (GstPad * src, GstPad * sink, GstPadLinkCheck flags)
1692 {
1693   GSList *pads_created = NULL;
1694   gboolean ret;
1695 
1696   if (!prepare_link_maybe_ghosting (&src, &sink, &pads_created)) {
1697     ret = FALSE;
1698   } else {
1699     ret = (gst_pad_link_full (src, sink, flags) == GST_PAD_LINK_OK);
1700   }
1701 
1702   if (!ret) {
1703     g_slist_foreach (pads_created, remove_pad, NULL);
1704   }
1705   g_slist_free (pads_created);
1706 
1707   return ret;
1708 }
1709 
1710 /**
1711  * gst_pad_link_maybe_ghosting_full:
1712  * @src: a #GstPad
1713  * @sink: a #GstPad
1714  * @flags: some #GstPadLinkCheck flags
1715  *
1716  * Links @src to @sink, creating any #GstGhostPad's in between as necessary.
1717  *
1718  * This is a convenience function to save having to create and add intermediate
1719  * #GstGhostPad's as required for linking across #GstBin boundaries.
1720  *
1721  * If @src or @sink pads don't have parent elements or do not share a common
1722  * ancestor, the link will fail.
1723  *
1724  * Calling gst_pad_link_maybe_ghosting_full() with
1725  * @flags == %GST_PAD_LINK_CHECK_DEFAULT is the recommended way of linking
1726  * pads with safety checks applied.
1727  *
1728  * Returns: whether the link succeeded.
1729  *
1730  * Since: 1.10
1731  */
1732 gboolean
gst_pad_link_maybe_ghosting_full(GstPad * src,GstPad * sink,GstPadLinkCheck flags)1733 gst_pad_link_maybe_ghosting_full (GstPad * src, GstPad * sink,
1734     GstPadLinkCheck flags)
1735 {
1736   g_return_val_if_fail (GST_IS_PAD (src), FALSE);
1737   g_return_val_if_fail (GST_IS_PAD (sink), FALSE);
1738 
1739   return pad_link_maybe_ghosting (src, sink, flags);
1740 }
1741 
1742 /**
1743  * gst_pad_link_maybe_ghosting:
1744  * @src: a #GstPad
1745  * @sink: a #GstPad
1746  *
1747  * Links @src to @sink, creating any #GstGhostPad's in between as necessary.
1748  *
1749  * This is a convenience function to save having to create and add intermediate
1750  * #GstGhostPad's as required for linking across #GstBin boundaries.
1751  *
1752  * If @src or @sink pads don't have parent elements or do not share a common
1753  * ancestor, the link will fail.
1754  *
1755  * Returns: whether the link succeeded.
1756  *
1757  * Since: 1.10
1758  */
1759 gboolean
gst_pad_link_maybe_ghosting(GstPad * src,GstPad * sink)1760 gst_pad_link_maybe_ghosting (GstPad * src, GstPad * sink)
1761 {
1762   g_return_val_if_fail (GST_IS_PAD (src), FALSE);
1763   g_return_val_if_fail (GST_IS_PAD (sink), FALSE);
1764 
1765   return gst_pad_link_maybe_ghosting_full (src, sink,
1766       GST_PAD_LINK_CHECK_DEFAULT);
1767 }
1768 
1769 static void
release_and_unref_pad(GstElement * element,GstPad * pad,gboolean requestpad)1770 release_and_unref_pad (GstElement * element, GstPad * pad, gboolean requestpad)
1771 {
1772   if (pad) {
1773     if (requestpad)
1774       gst_element_release_request_pad (element, pad);
1775     gst_object_unref (pad);
1776   }
1777 }
1778 
1779 /**
1780  * gst_element_link_pads_full:
1781  * @src: a #GstElement containing the source pad.
1782  * @srcpadname: (allow-none): the name of the #GstPad in source element
1783  *     or %NULL for any pad.
1784  * @dest: (transfer none): the #GstElement containing the destination pad.
1785  * @destpadname: (allow-none): the name of the #GstPad in destination element,
1786  * or %NULL for any pad.
1787  * @flags: the #GstPadLinkCheck to be performed when linking pads.
1788  *
1789  * Links the two named pads of the source and destination elements.
1790  * Side effect is that if one of the pads has no parent, it becomes a
1791  * child of the parent of the other element.  If they have different
1792  * parents, the link fails.
1793  *
1794  * Calling gst_element_link_pads_full() with @flags == %GST_PAD_LINK_CHECK_DEFAULT
1795  * is the same as calling gst_element_link_pads() and the recommended way of
1796  * linking pads with safety checks applied.
1797  *
1798  * This is a convenience function for gst_pad_link_full().
1799  *
1800  * Returns: %TRUE if the pads could be linked, %FALSE otherwise.
1801  */
1802 gboolean
gst_element_link_pads_full(GstElement * src,const gchar * srcpadname,GstElement * dest,const gchar * destpadname,GstPadLinkCheck flags)1803 gst_element_link_pads_full (GstElement * src, const gchar * srcpadname,
1804     GstElement * dest, const gchar * destpadname, GstPadLinkCheck flags)
1805 {
1806   const GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1807   GstPad *srcpad, *destpad;
1808   GstPadTemplate *srctempl, *desttempl;
1809   GstElementClass *srcclass, *destclass;
1810   gboolean srcrequest, destrequest;
1811 
1812   /* checks */
1813   g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1814   g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1815 
1816   GST_CAT_INFO (GST_CAT_ELEMENT_PADS,
1817       "trying to link element %s:%s to element %s:%s", GST_ELEMENT_NAME (src),
1818       srcpadname ? srcpadname : "(any)", GST_ELEMENT_NAME (dest),
1819       destpadname ? destpadname : "(any)");
1820 
1821   srcrequest = FALSE;
1822   destrequest = FALSE;
1823 
1824   /* get a src pad */
1825   if (srcpadname) {
1826     /* name specified, look it up */
1827     if (!(srcpad = gst_element_get_static_pad (src, srcpadname))) {
1828       if ((srcpad = gst_element_request_pad_simple (src, srcpadname)))
1829         srcrequest = TRUE;
1830     }
1831     if (!srcpad) {
1832       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
1833           GST_ELEMENT_NAME (src), srcpadname);
1834       return FALSE;
1835     } else {
1836       if (!(GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC)) {
1837         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no src pad",
1838             GST_DEBUG_PAD_NAME (srcpad));
1839         release_and_unref_pad (src, srcpad, srcrequest);
1840         return FALSE;
1841       }
1842       if (GST_PAD_PEER (srcpad) != NULL) {
1843         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1844             "pad %s:%s is already linked to %s:%s", GST_DEBUG_PAD_NAME (srcpad),
1845             GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad)));
1846         /* already linked request pads look like static pads, so the request pad
1847          * was never requested a second time above, so no need to release it */
1848         gst_object_unref (srcpad);
1849         return FALSE;
1850       }
1851     }
1852     srcpads = NULL;
1853   } else {
1854     /* no name given, get the first available pad */
1855     GST_OBJECT_LOCK (src);
1856     srcpads = GST_ELEMENT_PADS (src);
1857     srcpad = srcpads ? GST_PAD_CAST (srcpads->data) : NULL;
1858     if (srcpad)
1859       gst_object_ref (srcpad);
1860     GST_OBJECT_UNLOCK (src);
1861   }
1862 
1863   /* get a destination pad */
1864   if (destpadname) {
1865     /* name specified, look it up */
1866     if (!(destpad = gst_element_get_static_pad (dest, destpadname))) {
1867       if ((destpad = gst_element_request_pad_simple (dest, destpadname)))
1868         destrequest = TRUE;
1869     }
1870     if (!destpad) {
1871       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
1872           GST_ELEMENT_NAME (dest), destpadname);
1873       release_and_unref_pad (src, srcpad, srcrequest);
1874       return FALSE;
1875     } else {
1876       if (!(GST_PAD_DIRECTION (destpad) == GST_PAD_SINK)) {
1877         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no sink pad",
1878             GST_DEBUG_PAD_NAME (destpad));
1879         release_and_unref_pad (src, srcpad, srcrequest);
1880         release_and_unref_pad (dest, destpad, destrequest);
1881         return FALSE;
1882       }
1883       if (GST_PAD_PEER (destpad) != NULL) {
1884         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1885             "pad %s:%s is already linked to %s:%s",
1886             GST_DEBUG_PAD_NAME (destpad),
1887             GST_DEBUG_PAD_NAME (GST_PAD_PEER (destpad)));
1888         release_and_unref_pad (src, srcpad, srcrequest);
1889         /* already linked request pads look like static pads, so the request pad
1890          * was never requested a second time above, so no need to release it */
1891         gst_object_unref (destpad);
1892         return FALSE;
1893       }
1894     }
1895     destpads = NULL;
1896   } else {
1897     /* no name given, get the first available pad */
1898     GST_OBJECT_LOCK (dest);
1899     destpads = GST_ELEMENT_PADS (dest);
1900     destpad = destpads ? GST_PAD_CAST (destpads->data) : NULL;
1901     if (destpad)
1902       gst_object_ref (destpad);
1903     GST_OBJECT_UNLOCK (dest);
1904   }
1905 
1906   if (srcpadname && destpadname) {
1907     gboolean result;
1908 
1909     /* two explicitly specified pads */
1910     result = pad_link_maybe_ghosting (srcpad, destpad, flags);
1911 
1912     if (result) {
1913       gst_object_unref (srcpad);
1914       gst_object_unref (destpad);
1915     } else {
1916       release_and_unref_pad (src, srcpad, srcrequest);
1917       release_and_unref_pad (dest, destpad, destrequest);
1918     }
1919     return result;
1920   }
1921 
1922   if (srcpad) {
1923     /* loop through the allowed pads in the source, trying to find a
1924      * compatible destination pad */
1925     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1926         "looping through allowed src and dest pads");
1927     do {
1928       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying src pad %s:%s",
1929           GST_DEBUG_PAD_NAME (srcpad));
1930       if ((GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1931           (GST_PAD_PEER (srcpad) == NULL)) {
1932         gboolean temprequest = FALSE;
1933         GstPad *temp;
1934 
1935         if (destpadname) {
1936           temp = destpad;
1937           gst_object_ref (temp);
1938         } else {
1939           temp = gst_element_get_compatible_pad (dest, srcpad, NULL);
1940           if (temp && GST_PAD_PAD_TEMPLATE (temp)
1941               && GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (temp)) ==
1942               GST_PAD_REQUEST) {
1943             temprequest = TRUE;
1944           }
1945         }
1946 
1947         if (temp && pad_link_maybe_ghosting (srcpad, temp, flags)) {
1948           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
1949               GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (temp));
1950           if (destpad)
1951             gst_object_unref (destpad);
1952           gst_object_unref (srcpad);
1953           gst_object_unref (temp);
1954           return TRUE;
1955         }
1956 
1957         if (temp) {
1958           if (temprequest)
1959             gst_element_release_request_pad (dest, temp);
1960           gst_object_unref (temp);
1961         }
1962       }
1963       /* find a better way for this mess */
1964       if (srcpads) {
1965         srcpads = g_list_next (srcpads);
1966         if (srcpads) {
1967           gst_object_unref (srcpad);
1968           srcpad = GST_PAD_CAST (srcpads->data);
1969           gst_object_ref (srcpad);
1970         }
1971       }
1972     } while (srcpads);
1973   }
1974   if (srcpadname) {
1975     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s:%s to %s",
1976         GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (dest));
1977     /* no need to release any request pad as both src- and destpadname must be
1978      * set to end up here, but this case has already been taken care of above */
1979     if (destpad)
1980       gst_object_unref (destpad);
1981     destpad = NULL;
1982   }
1983   if (srcpad) {
1984     release_and_unref_pad (src, srcpad, srcrequest);
1985     srcpad = NULL;
1986   }
1987 
1988   if (destpad) {
1989     /* loop through the existing pads in the destination */
1990     do {
1991       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying dest pad %s:%s",
1992           GST_DEBUG_PAD_NAME (destpad));
1993       if ((GST_PAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1994           (GST_PAD_PEER (destpad) == NULL)) {
1995         GstPad *temp = gst_element_get_compatible_pad (src, destpad, NULL);
1996         gboolean temprequest = FALSE;
1997 
1998         if (temp && GST_PAD_PAD_TEMPLATE (temp)
1999             && GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (temp)) ==
2000             GST_PAD_REQUEST) {
2001           temprequest = TRUE;
2002         }
2003 
2004         if (temp && pad_link_maybe_ghosting (temp, destpad, flags)) {
2005           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
2006               GST_DEBUG_PAD_NAME (temp), GST_DEBUG_PAD_NAME (destpad));
2007           gst_object_unref (temp);
2008           gst_object_unref (destpad);
2009           return TRUE;
2010         }
2011 
2012         release_and_unref_pad (src, temp, temprequest);
2013       }
2014       if (destpads) {
2015         destpads = g_list_next (destpads);
2016         if (destpads) {
2017           gst_object_unref (destpad);
2018           destpad = GST_PAD_CAST (destpads->data);
2019           gst_object_ref (destpad);
2020         }
2021       }
2022     } while (destpads);
2023   }
2024 
2025   if (destpadname) {
2026     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s:%s",
2027         GST_ELEMENT_NAME (src), GST_DEBUG_PAD_NAME (destpad));
2028     release_and_unref_pad (dest, destpad, destrequest);
2029     return FALSE;
2030   } else {
2031     /* no need to release any request pad as the case of unset destpatname and
2032      * destpad being a request pad has already been taken care of when looking
2033      * though the destination pads above */
2034     if (destpad) {
2035       gst_object_unref (destpad);
2036     }
2037     destpad = NULL;
2038   }
2039 
2040   srcclass = GST_ELEMENT_GET_CLASS (src);
2041   destclass = GST_ELEMENT_GET_CLASS (dest);
2042 
2043   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
2044       "we might have request pads on both sides, checking...");
2045   srctempls = gst_element_class_get_pad_template_list (srcclass);
2046   desttempls = gst_element_class_get_pad_template_list (destclass);
2047 
2048   if (srctempls && desttempls) {
2049     while (srctempls) {
2050       srctempl = (GstPadTemplate *) srctempls->data;
2051       if (srctempl->presence == GST_PAD_REQUEST) {
2052         for (l = desttempls; l; l = l->next) {
2053           desttempl = (GstPadTemplate *) l->data;
2054           if (desttempl->presence == GST_PAD_REQUEST &&
2055               desttempl->direction != srctempl->direction) {
2056             GstCaps *srccaps, *destcaps;
2057 
2058             srccaps = gst_pad_template_get_caps (srctempl);
2059             destcaps = gst_pad_template_get_caps (desttempl);
2060             if (gst_caps_is_always_compatible (srccaps, destcaps)) {
2061               srcpad =
2062                   gst_element_request_pad (src, srctempl,
2063                   srctempl->name_template, NULL);
2064               destpad =
2065                   gst_element_request_pad (dest, desttempl,
2066                   desttempl->name_template, NULL);
2067               if (srcpad && destpad
2068                   && pad_link_maybe_ghosting (srcpad, destpad, flags)) {
2069                 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
2070                     "linked pad %s:%s to pad %s:%s",
2071                     GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
2072                 gst_object_unref (srcpad);
2073                 gst_object_unref (destpad);
2074                 gst_caps_unref (srccaps);
2075                 gst_caps_unref (destcaps);
2076                 return TRUE;
2077               }
2078               /* it failed, so we release the request pads */
2079               if (srcpad) {
2080                 gst_element_release_request_pad (src, srcpad);
2081                 gst_object_unref (srcpad);
2082               }
2083               if (destpad) {
2084                 gst_element_release_request_pad (dest, destpad);
2085                 gst_object_unref (destpad);
2086               }
2087             }
2088             gst_caps_unref (srccaps);
2089             gst_caps_unref (destcaps);
2090           }
2091         }
2092       }
2093       srctempls = srctempls->next;
2094     }
2095   }
2096 
2097   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s",
2098       GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
2099   return FALSE;
2100 }
2101 
2102 /**
2103  * gst_element_link_pads:
2104  * @src: a #GstElement containing the source pad.
2105  * @srcpadname: (allow-none): the name of the #GstPad in source element
2106  *     or %NULL for any pad.
2107  * @dest: (transfer none): the #GstElement containing the destination pad.
2108  * @destpadname: (allow-none): the name of the #GstPad in destination element,
2109  * or %NULL for any pad.
2110  *
2111  * Links the two named pads of the source and destination elements.
2112  * Side effect is that if one of the pads has no parent, it becomes a
2113  * child of the parent of the other element.  If they have different
2114  * parents, the link fails.
2115  *
2116  * Returns: %TRUE if the pads could be linked, %FALSE otherwise.
2117  */
2118 gboolean
gst_element_link_pads(GstElement * src,const gchar * srcpadname,GstElement * dest,const gchar * destpadname)2119 gst_element_link_pads (GstElement * src, const gchar * srcpadname,
2120     GstElement * dest, const gchar * destpadname)
2121 {
2122   return gst_element_link_pads_full (src, srcpadname, dest, destpadname,
2123       GST_PAD_LINK_CHECK_DEFAULT);
2124 }
2125 
2126 /**
2127  * gst_element_link_pads_filtered:
2128  * @src: a #GstElement containing the source pad.
2129  * @srcpadname: (allow-none): the name of the #GstPad in source element
2130  *     or %NULL for any pad.
2131  * @dest: (transfer none): the #GstElement containing the destination pad.
2132  * @destpadname: (allow-none): the name of the #GstPad in destination element
2133  *     or %NULL for any pad.
2134  * @filter: (transfer none) (allow-none): the #GstCaps to filter the link,
2135  *     or %NULL for no filter.
2136  *
2137  * Links the two named pads of the source and destination elements. Side effect
2138  * is that if one of the pads has no parent, it becomes a child of the parent of
2139  * the other element. If they have different parents, the link fails. If @caps
2140  * is not %NULL, makes sure that the caps of the link is a subset of @caps.
2141  *
2142  * Returns: %TRUE if the pads could be linked, %FALSE otherwise.
2143  */
2144 gboolean
gst_element_link_pads_filtered(GstElement * src,const gchar * srcpadname,GstElement * dest,const gchar * destpadname,GstCaps * filter)2145 gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname,
2146     GstElement * dest, const gchar * destpadname, GstCaps * filter)
2147 {
2148   /* checks */
2149   g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
2150   g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
2151   g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), FALSE);
2152 
2153   if (filter) {
2154     GstElement *capsfilter;
2155     GstObject *parent;
2156     GstState state, pending;
2157     gboolean lr1, lr2;
2158 
2159     capsfilter = gst_element_factory_make ("capsfilter", NULL);
2160     if (!capsfilter) {
2161       GST_ERROR ("Could not make a capsfilter");
2162       return FALSE;
2163     }
2164 
2165     parent = gst_object_get_parent (GST_OBJECT (src));
2166     g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
2167 
2168     gst_element_get_state (GST_ELEMENT_CAST (parent), &state, &pending, 0);
2169 
2170     if (!gst_bin_add (GST_BIN (parent), capsfilter)) {
2171       GST_ERROR ("Could not add capsfilter");
2172       gst_object_unref (parent);
2173       return FALSE;
2174     }
2175 
2176     if (pending != GST_STATE_VOID_PENDING)
2177       state = pending;
2178 
2179     gst_element_set_state (capsfilter, state);
2180 
2181     gst_object_unref (parent);
2182 
2183     g_object_set (capsfilter, "caps", filter, NULL);
2184 
2185     lr1 = gst_element_link_pads (src, srcpadname, capsfilter, "sink");
2186     lr2 = gst_element_link_pads (capsfilter, "src", dest, destpadname);
2187     if (lr1 && lr2) {
2188       return TRUE;
2189     } else {
2190       if (!lr1) {
2191         GST_INFO ("Could not link pads: %s:%s - capsfilter:sink",
2192             GST_ELEMENT_NAME (src), srcpadname);
2193       } else {
2194         GST_INFO ("Could not link pads: capsfilter:src - %s:%s",
2195             GST_ELEMENT_NAME (dest), destpadname);
2196       }
2197       gst_element_set_state (capsfilter, GST_STATE_NULL);
2198       /* this will unlink and unref as appropriate */
2199       gst_bin_remove (GST_BIN (GST_OBJECT_PARENT (capsfilter)), capsfilter);
2200       return FALSE;
2201     }
2202   } else {
2203     if (gst_element_link_pads (src, srcpadname, dest, destpadname)) {
2204       return TRUE;
2205     } else {
2206       GST_INFO ("Could not link pads: %s:%s - %s:%s", GST_ELEMENT_NAME (src),
2207           srcpadname, GST_ELEMENT_NAME (dest), destpadname);
2208       return FALSE;
2209     }
2210   }
2211 }
2212 
2213 /**
2214  * gst_element_link:
2215  * @src: (transfer none): a #GstElement containing the source pad.
2216  * @dest: (transfer none): the #GstElement containing the destination pad.
2217  *
2218  * Links @src to @dest. The link must be from source to
2219  * destination; the other direction will not be tried. The function looks for
2220  * existing pads that aren't linked yet. It will request new pads if necessary.
2221  * Such pads need to be released manually when unlinking.
2222  * If multiple links are possible, only one is established.
2223  *
2224  * Make sure you have added your elements to a bin or pipeline with
2225  * gst_bin_add() before trying to link them.
2226  *
2227  * Returns: %TRUE if the elements could be linked, %FALSE otherwise.
2228  */
2229 gboolean
gst_element_link(GstElement * src,GstElement * dest)2230 gst_element_link (GstElement * src, GstElement * dest)
2231 {
2232   return gst_element_link_pads (src, NULL, dest, NULL);
2233 }
2234 
2235 /**
2236  * gst_element_link_many:
2237  * @element_1: (transfer none): the first #GstElement in the link chain.
2238  * @element_2: (transfer none): the second #GstElement in the link chain.
2239  * @...: the %NULL-terminated list of elements to link in order.
2240  *
2241  * Chain together a series of elements. Uses gst_element_link().
2242  * Make sure you have added your elements to a bin or pipeline with
2243  * gst_bin_add() before trying to link them.
2244  *
2245  * Returns: %TRUE on success, %FALSE otherwise.
2246  */
2247 gboolean
gst_element_link_many(GstElement * element_1,GstElement * element_2,...)2248 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
2249 {
2250   gboolean res = TRUE;
2251   va_list args;
2252 
2253   g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
2254   g_return_val_if_fail (GST_IS_ELEMENT (element_2), FALSE);
2255 
2256   va_start (args, element_2);
2257 
2258   while (element_2) {
2259     if (!gst_element_link (element_1, element_2)) {
2260       res = FALSE;
2261       break;
2262     }
2263 
2264     element_1 = element_2;
2265     element_2 = va_arg (args, GstElement *);
2266   }
2267 
2268   va_end (args);
2269 
2270   return res;
2271 }
2272 
2273 /**
2274  * gst_element_link_filtered:
2275  * @src: a #GstElement containing the source pad.
2276  * @dest: (transfer none): the #GstElement containing the destination pad.
2277  * @filter: (transfer none) (allow-none): the #GstCaps to filter the link,
2278  *     or %NULL for no filter.
2279  *
2280  * Links @src to @dest using the given caps as filtercaps.
2281  * The link must be from source to
2282  * destination; the other direction will not be tried. The function looks for
2283  * existing pads that aren't linked yet. It will request new pads if necessary.
2284  * If multiple links are possible, only one is established.
2285  *
2286  * Make sure you have added your elements to a bin or pipeline with
2287  * gst_bin_add() before trying to link them.
2288  *
2289  * Returns: %TRUE if the pads could be linked, %FALSE otherwise.
2290  */
2291 gboolean
gst_element_link_filtered(GstElement * src,GstElement * dest,GstCaps * filter)2292 gst_element_link_filtered (GstElement * src, GstElement * dest,
2293     GstCaps * filter)
2294 {
2295   return gst_element_link_pads_filtered (src, NULL, dest, NULL, filter);
2296 }
2297 
2298 /**
2299  * gst_element_unlink_pads:
2300  * @src: a (transfer none): #GstElement containing the source pad.
2301  * @srcpadname: the name of the #GstPad in source element.
2302  * @dest: (transfer none): a #GstElement containing the destination pad.
2303  * @destpadname: the name of the #GstPad in destination element.
2304  *
2305  * Unlinks the two named pads of the source and destination elements.
2306  *
2307  * This is a convenience function for gst_pad_unlink().
2308  */
2309 void
gst_element_unlink_pads(GstElement * src,const gchar * srcpadname,GstElement * dest,const gchar * destpadname)2310 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
2311     GstElement * dest, const gchar * destpadname)
2312 {
2313   GstPad *srcpad, *destpad;
2314   gboolean srcrequest, destrequest;
2315 
2316   srcrequest = destrequest = FALSE;
2317 
2318   g_return_if_fail (src != NULL);
2319   g_return_if_fail (GST_IS_ELEMENT (src));
2320   g_return_if_fail (srcpadname != NULL);
2321   g_return_if_fail (dest != NULL);
2322   g_return_if_fail (GST_IS_ELEMENT (dest));
2323   g_return_if_fail (destpadname != NULL);
2324 
2325   /* obtain the pads requested */
2326   if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
2327     if ((srcpad = gst_element_request_pad_simple (src, srcpadname)))
2328       srcrequest = TRUE;
2329   if (srcpad == NULL) {
2330     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
2331     return;
2332   }
2333   if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
2334     if ((destpad = gst_element_request_pad_simple (dest, destpadname)))
2335       destrequest = TRUE;
2336   if (destpad == NULL) {
2337     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
2338         destpadname);
2339     goto free_src;
2340   }
2341 
2342   /* we're satisfied they can be unlinked, let's do it */
2343   gst_pad_unlink (srcpad, destpad);
2344 
2345   if (destrequest)
2346     gst_element_release_request_pad (dest, destpad);
2347   gst_object_unref (destpad);
2348 
2349 free_src:
2350   if (srcrequest)
2351     gst_element_release_request_pad (src, srcpad);
2352   gst_object_unref (srcpad);
2353 }
2354 
2355 /**
2356  * gst_element_unlink_many:
2357  * @element_1: (transfer none): the first #GstElement in the link chain.
2358  * @element_2: (transfer none): the second #GstElement in the link chain.
2359  * @...: the %NULL-terminated list of elements to unlink in order.
2360  *
2361  * Unlinks a series of elements. Uses gst_element_unlink().
2362  */
2363 void
gst_element_unlink_many(GstElement * element_1,GstElement * element_2,...)2364 gst_element_unlink_many (GstElement * element_1, GstElement * element_2, ...)
2365 {
2366   va_list args;
2367 
2368   g_return_if_fail (element_1 != NULL && element_2 != NULL);
2369   g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
2370 
2371   va_start (args, element_2);
2372 
2373   while (element_2) {
2374     gst_element_unlink (element_1, element_2);
2375 
2376     element_1 = element_2;
2377     element_2 = va_arg (args, GstElement *);
2378   }
2379 
2380   va_end (args);
2381 }
2382 
2383 /**
2384  * gst_element_unlink:
2385  * @src: (transfer none): the source #GstElement to unlink.
2386  * @dest: (transfer none): the sink #GstElement to unlink.
2387  *
2388  * Unlinks all source pads of the source element with all sink pads
2389  * of the sink element to which they are linked.
2390  *
2391  * If the link has been made using gst_element_link(), it could have created an
2392  * requestpad, which has to be released using gst_element_release_request_pad().
2393  */
2394 void
gst_element_unlink(GstElement * src,GstElement * dest)2395 gst_element_unlink (GstElement * src, GstElement * dest)
2396 {
2397   GstIterator *pads;
2398   gboolean done = FALSE;
2399   GValue data = { 0, };
2400 
2401   g_return_if_fail (GST_IS_ELEMENT (src));
2402   g_return_if_fail (GST_IS_ELEMENT (dest));
2403 
2404   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unlinking \"%s\" and \"%s\"",
2405       GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
2406 
2407   pads = gst_element_iterate_pads (src);
2408   while (!done) {
2409     switch (gst_iterator_next (pads, &data)) {
2410       case GST_ITERATOR_OK:
2411       {
2412         GstPad *pad = g_value_get_object (&data);
2413 
2414         if (GST_PAD_IS_SRC (pad)) {
2415           GstPad *peerpad = gst_pad_get_peer (pad);
2416 
2417           /* see if the pad is linked and is really a pad of dest */
2418           if (peerpad) {
2419             GstElement *peerelem;
2420 
2421             peerelem = gst_pad_get_parent_element (peerpad);
2422 
2423             if (peerelem == dest) {
2424               gst_pad_unlink (pad, peerpad);
2425             }
2426             if (peerelem)
2427               gst_object_unref (peerelem);
2428 
2429             gst_object_unref (peerpad);
2430           }
2431         }
2432         g_value_reset (&data);
2433         break;
2434       }
2435       case GST_ITERATOR_RESYNC:
2436         gst_iterator_resync (pads);
2437         break;
2438       case GST_ITERATOR_DONE:
2439         done = TRUE;
2440         break;
2441       default:
2442         g_assert_not_reached ();
2443         break;
2444     }
2445   }
2446   g_value_unset (&data);
2447   gst_iterator_free (pads);
2448 }
2449 
2450 /**
2451  * gst_element_query_position:
2452  * @element: a #GstElement to invoke the position query on.
2453  * @format: the #GstFormat requested
2454  * @cur: (out) (allow-none): a location in which to store the current
2455  *     position, or %NULL.
2456  *
2457  * Queries an element (usually top-level pipeline or playbin element) for the
2458  * stream position in nanoseconds. This will be a value between 0 and the
2459  * stream duration (if the stream duration is known). This query will usually
2460  * only work once the pipeline is prerolled (i.e. reached PAUSED or PLAYING
2461  * state). The application will receive an ASYNC_DONE message on the pipeline
2462  * bus when that is the case.
2463  *
2464  * If one repeatedly calls this function one can also create a query and reuse
2465  * it in gst_element_query().
2466  *
2467  * Returns: %TRUE if the query could be performed.
2468  */
2469 gboolean
gst_element_query_position(GstElement * element,GstFormat format,gint64 * cur)2470 gst_element_query_position (GstElement * element, GstFormat format,
2471     gint64 * cur)
2472 {
2473   GstQuery *query;
2474   gboolean ret;
2475 
2476   if (cur != NULL)
2477     *cur = GST_CLOCK_TIME_NONE;
2478 
2479   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2480   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
2481 
2482   query = gst_query_new_position (format);
2483   ret = gst_element_query (element, query);
2484 
2485   if (ret)
2486     gst_query_parse_position (query, NULL, cur);
2487 
2488   gst_query_unref (query);
2489 
2490   return ret;
2491 }
2492 
2493 /**
2494  * gst_element_query_duration:
2495  * @element: a #GstElement to invoke the duration query on.
2496  * @format: the #GstFormat requested
2497  * @duration: (out) (allow-none): A location in which to store the total duration, or %NULL.
2498  *
2499  * Queries an element (usually top-level pipeline or playbin element) for the
2500  * total stream duration in nanoseconds. This query will only work once the
2501  * pipeline is prerolled (i.e. reached PAUSED or PLAYING state). The application
2502  * will receive an ASYNC_DONE message on the pipeline bus when that is the case.
2503  *
2504  * If the duration changes for some reason, you will get a DURATION_CHANGED
2505  * message on the pipeline bus, in which case you should re-query the duration
2506  * using this function.
2507  *
2508  * Returns: %TRUE if the query could be performed.
2509  */
2510 gboolean
gst_element_query_duration(GstElement * element,GstFormat format,gint64 * duration)2511 gst_element_query_duration (GstElement * element, GstFormat format,
2512     gint64 * duration)
2513 {
2514   GstQuery *query;
2515   gboolean ret;
2516 
2517   if (duration != NULL)
2518     *duration = GST_CLOCK_TIME_NONE;
2519 
2520   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2521   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
2522 
2523   query = gst_query_new_duration (format);
2524   ret = gst_element_query (element, query);
2525 
2526   if (ret)
2527     gst_query_parse_duration (query, NULL, duration);
2528 
2529   gst_query_unref (query);
2530 
2531   return ret;
2532 }
2533 
2534 /**
2535  * gst_element_query_convert:
2536  * @element: a #GstElement to invoke the convert query on.
2537  * @src_format: a #GstFormat to convert from.
2538  * @src_val: a value to convert.
2539  * @dest_format: the #GstFormat to convert to.
2540  * @dest_val: (out): a pointer to the result.
2541  *
2542  * Queries an element to convert @src_val in @src_format to @dest_format.
2543  *
2544  * Returns: %TRUE if the query could be performed.
2545  */
2546 gboolean
gst_element_query_convert(GstElement * element,GstFormat src_format,gint64 src_val,GstFormat dest_format,gint64 * dest_val)2547 gst_element_query_convert (GstElement * element, GstFormat src_format,
2548     gint64 src_val, GstFormat dest_format, gint64 * dest_val)
2549 {
2550   GstQuery *query;
2551   gboolean ret;
2552 
2553   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2554   g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE);
2555   g_return_val_if_fail (dest_val != NULL, FALSE);
2556 
2557   if (dest_format == src_format || src_val == -1) {
2558     *dest_val = src_val;
2559     return TRUE;
2560   }
2561 
2562   query = gst_query_new_convert (src_format, src_val, dest_format);
2563   ret = gst_element_query (element, query);
2564 
2565   if (ret)
2566     gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
2567 
2568   gst_query_unref (query);
2569 
2570   return ret;
2571 }
2572 
2573 /**
2574  * gst_element_seek_simple:
2575  * @element: a #GstElement to seek on
2576  * @format: a #GstFormat to execute the seek in, such as #GST_FORMAT_TIME
2577  * @seek_flags: seek options; playback applications will usually want to use
2578  *            GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT here
2579  * @seek_pos: position to seek to (relative to the start); if you are doing
2580  *            a seek in #GST_FORMAT_TIME this value is in nanoseconds -
2581  *            multiply with #GST_SECOND to convert seconds to nanoseconds or
2582  *            with #GST_MSECOND to convert milliseconds to nanoseconds.
2583  *
2584  * Simple API to perform a seek on the given element, meaning it just seeks
2585  * to the given position relative to the start of the stream. For more complex
2586  * operations like segment seeks (e.g. for looping) or changing the playback
2587  * rate or seeking relative to the last configured playback segment you should
2588  * use gst_element_seek().
2589  *
2590  * In a completely prerolled PAUSED or PLAYING pipeline, seeking is always
2591  * guaranteed to return %TRUE on a seekable media type or %FALSE when the media
2592  * type is certainly not seekable (such as a live stream).
2593  *
2594  * Some elements allow for seeking in the READY state, in this
2595  * case they will store the seek event and execute it when they are put to
2596  * PAUSED. If the element supports seek in READY, it will always return %TRUE when
2597  * it receives the event in the READY state.
2598  *
2599  * Returns: %TRUE if the seek operation succeeded. Flushing seeks will trigger a
2600  * preroll, which will emit %GST_MESSAGE_ASYNC_DONE.
2601  */
2602 gboolean
gst_element_seek_simple(GstElement * element,GstFormat format,GstSeekFlags seek_flags,gint64 seek_pos)2603 gst_element_seek_simple (GstElement * element, GstFormat format,
2604     GstSeekFlags seek_flags, gint64 seek_pos)
2605 {
2606   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2607   g_return_val_if_fail (seek_pos >= 0, FALSE);
2608 
2609   return gst_element_seek (element, 1.0, format, seek_flags,
2610       GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
2611 }
2612 
2613 /**
2614  * gst_pad_use_fixed_caps:
2615  * @pad: the pad to use
2616  *
2617  * A helper function you can use that sets the FIXED_CAPS flag
2618  * This way the default CAPS query will always return the negotiated caps
2619  * or in case the pad is not negotiated, the padtemplate caps.
2620  *
2621  * The negotiated caps are the caps of the last CAPS event that passed on the
2622  * pad. Use this function on a pad that, once it negotiated to a CAPS, cannot
2623  * be renegotiated to something else.
2624  */
2625 void
gst_pad_use_fixed_caps(GstPad * pad)2626 gst_pad_use_fixed_caps (GstPad * pad)
2627 {
2628   GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FIXED_CAPS);
2629 }
2630 
2631 /**
2632  * gst_pad_get_parent_element:
2633  * @pad: a pad
2634  *
2635  * Gets the parent of @pad, cast to a #GstElement. If a @pad has no parent or
2636  * its parent is not an element, return %NULL.
2637  *
2638  * Returns: (transfer full) (nullable): the parent of the pad. The
2639  * caller has a reference on the parent, so unref when you're finished
2640  * with it.
2641  *
2642  * MT safe.
2643  */
2644 GstElement *
gst_pad_get_parent_element(GstPad * pad)2645 gst_pad_get_parent_element (GstPad * pad)
2646 {
2647   GstObject *p;
2648 
2649   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2650 
2651   p = gst_object_get_parent (GST_OBJECT_CAST (pad));
2652 
2653   if (p && !GST_IS_ELEMENT (p)) {
2654     gst_object_unref (p);
2655     p = NULL;
2656   }
2657   return GST_ELEMENT_CAST (p);
2658 }
2659 
2660 /**
2661  * gst_object_default_error:
2662  * @source: the #GstObject that initiated the error.
2663  * @error: (in): the GError.
2664  * @debug: (in) (allow-none): an additional debug information string, or %NULL
2665  *
2666  * A default error function that uses g_printerr() to display the error message
2667  * and the optional debug string..
2668  *
2669  * The default handler will simply print the error string using g_print.
2670  */
2671 void
gst_object_default_error(GstObject * source,const GError * error,const gchar * debug)2672 gst_object_default_error (GstObject * source, const GError * error,
2673     const gchar * debug)
2674 {
2675   gchar *name = gst_object_get_path_string (source);
2676 
2677   g_printerr (_("ERROR: from element %s: %s\n"), name, error->message);
2678   if (debug)
2679     g_printerr (_("Additional debug info:\n%s\n"), debug);
2680 
2681   g_free (name);
2682 }
2683 
2684 /**
2685  * gst_bin_add_many: (skip)
2686  * @bin: a #GstBin
2687  * @element_1: (transfer floating): the #GstElement element to add to the bin
2688  * @...: additional elements to add to the bin
2689  *
2690  * Adds a %NULL-terminated list of elements to a bin.  This function is
2691  * equivalent to calling gst_bin_add() for each member of the list. The return
2692  * value of each gst_bin_add() is ignored.
2693  */
2694 void
gst_bin_add_many(GstBin * bin,GstElement * element_1,...)2695 gst_bin_add_many (GstBin * bin, GstElement * element_1, ...)
2696 {
2697   va_list args;
2698 
2699   g_return_if_fail (GST_IS_BIN (bin));
2700   g_return_if_fail (GST_IS_ELEMENT (element_1));
2701 
2702   va_start (args, element_1);
2703 
2704   while (element_1) {
2705     gst_bin_add (bin, element_1);
2706 
2707     element_1 = va_arg (args, GstElement *);
2708   }
2709 
2710   va_end (args);
2711 }
2712 
2713 /**
2714  * gst_bin_remove_many: (skip)
2715  * @bin: a #GstBin
2716  * @element_1: (transfer none): the first #GstElement to remove from the bin
2717  * @...: (transfer none): %NULL-terminated list of elements to remove from the bin
2718  *
2719  * Removes a list of elements from a bin. This function is equivalent
2720  * to calling gst_bin_remove() with each member of the list.
2721  */
2722 void
gst_bin_remove_many(GstBin * bin,GstElement * element_1,...)2723 gst_bin_remove_many (GstBin * bin, GstElement * element_1, ...)
2724 {
2725   va_list args;
2726 
2727   g_return_if_fail (GST_IS_BIN (bin));
2728   g_return_if_fail (GST_IS_ELEMENT (element_1));
2729 
2730   va_start (args, element_1);
2731 
2732   while (element_1) {
2733     gst_bin_remove (bin, element_1);
2734 
2735     element_1 = va_arg (args, GstElement *);
2736   }
2737 
2738   va_end (args);
2739 }
2740 
2741 typedef struct
2742 {
2743   GstQuery *query;
2744   gboolean ret;
2745 } QueryAcceptCapsData;
2746 
2747 static gboolean
query_accept_caps_func(GstPad * pad,QueryAcceptCapsData * data)2748 query_accept_caps_func (GstPad * pad, QueryAcceptCapsData * data)
2749 {
2750   if (G_LIKELY (gst_pad_peer_query (pad, data->query))) {
2751     gboolean result;
2752 
2753     gst_query_parse_accept_caps_result (data->query, &result);
2754     data->ret &= result;
2755   }
2756   return FALSE;
2757 }
2758 
2759 /**
2760  * gst_pad_proxy_query_accept_caps:
2761  * @pad: a #GstPad to proxy.
2762  * @query: an ACCEPT_CAPS #GstQuery.
2763  *
2764  * Checks if all internally linked pads of @pad accepts the caps in @query and
2765  * returns the intersection of the results.
2766  *
2767  * This function is useful as a default accept caps query function for an element
2768  * that can handle any stream format, but requires caps that are acceptable for
2769  * all opposite pads.
2770  *
2771  * Returns: %TRUE if @query could be executed
2772  */
2773 gboolean
gst_pad_proxy_query_accept_caps(GstPad * pad,GstQuery * query)2774 gst_pad_proxy_query_accept_caps (GstPad * pad, GstQuery * query)
2775 {
2776   QueryAcceptCapsData data;
2777 
2778   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2779   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
2780   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS, FALSE);
2781 
2782   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
2783       "proxying accept caps query for %s:%s", GST_DEBUG_PAD_NAME (pad));
2784 
2785   data.query = query;
2786   /* value to hold the return, by default it holds TRUE */
2787   /* FIXME: TRUE is wrong when there are no pads */
2788   data.ret = TRUE;
2789 
2790   gst_pad_forward (pad, (GstPadForwardFunction) query_accept_caps_func, &data);
2791   gst_query_set_accept_caps_result (query, data.ret);
2792 
2793   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "proxying accept caps query: %d",
2794       data.ret);
2795 
2796   return data.ret;
2797 }
2798 
2799 typedef struct
2800 {
2801   GstQuery *query;
2802   GstCaps *ret;
2803 } QueryCapsData;
2804 
2805 static gboolean
query_caps_func(GstPad * pad,QueryCapsData * data)2806 query_caps_func (GstPad * pad, QueryCapsData * data)
2807 {
2808   gboolean empty = FALSE;
2809 
2810   if (G_LIKELY (gst_pad_peer_query (pad, data->query))) {
2811     GstCaps *peercaps, *intersection;
2812 
2813     gst_query_parse_caps_result (data->query, &peercaps);
2814     GST_DEBUG_OBJECT (pad, "intersect with result %" GST_PTR_FORMAT, peercaps);
2815     intersection = gst_caps_intersect (data->ret, peercaps);
2816     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, intersection);
2817 
2818     gst_caps_unref (data->ret);
2819     data->ret = intersection;
2820 
2821     /* stop when empty */
2822     empty = gst_caps_is_empty (intersection);
2823   }
2824   return empty;
2825 }
2826 
2827 /**
2828  * gst_pad_proxy_query_caps:
2829  * @pad: a #GstPad to proxy.
2830  * @query: a CAPS #GstQuery.
2831  *
2832  * Calls gst_pad_query_caps() for all internally linked pads of @pad and returns
2833  * the intersection of the results.
2834  *
2835  * This function is useful as a default caps query function for an element
2836  * that can handle any stream format, but requires all its pads to have
2837  * the same caps.  Two such elements are tee and adder.
2838  *
2839  * Returns: %TRUE if @query could be executed
2840  */
2841 gboolean
gst_pad_proxy_query_caps(GstPad * pad,GstQuery * query)2842 gst_pad_proxy_query_caps (GstPad * pad, GstQuery * query)
2843 {
2844   GstCaps *filter, *templ, *result;
2845   QueryCapsData data;
2846 
2847   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2848   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
2849   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS, FALSE);
2850 
2851   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "proxying caps query for %s:%s",
2852       GST_DEBUG_PAD_NAME (pad));
2853 
2854   data.query = query;
2855 
2856   /* value to hold the return, by default it holds the filter or ANY */
2857   gst_query_parse_caps (query, &filter);
2858   data.ret = filter ? gst_caps_ref (filter) : gst_caps_new_any ();
2859 
2860   gst_pad_forward (pad, (GstPadForwardFunction) query_caps_func, &data);
2861 
2862   templ = gst_pad_get_pad_template_caps (pad);
2863   result = gst_caps_intersect (data.ret, templ);
2864   gst_caps_unref (data.ret);
2865   gst_caps_unref (templ);
2866 
2867   gst_query_set_caps_result (query, result);
2868   gst_caps_unref (result);
2869 
2870   /* FIXME: return something depending on the processing */
2871   return TRUE;
2872 }
2873 
2874 /**
2875  * gst_pad_query_position:
2876  * @pad: a #GstPad to invoke the position query on.
2877  * @format: the #GstFormat requested
2878  * @cur: (out) (allow-none): A location in which to store the current position, or %NULL.
2879  *
2880  * Queries a pad for the stream position.
2881  *
2882  * Returns: %TRUE if the query could be performed.
2883  */
2884 gboolean
gst_pad_query_position(GstPad * pad,GstFormat format,gint64 * cur)2885 gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur)
2886 {
2887   GstQuery *query;
2888   gboolean ret;
2889 
2890   if (cur != NULL)
2891     *cur = GST_CLOCK_TIME_NONE;
2892 
2893   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2894   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
2895 
2896   query = gst_query_new_position (format);
2897   if ((ret = gst_pad_query (pad, query)))
2898     gst_query_parse_position (query, NULL, cur);
2899   gst_query_unref (query);
2900 
2901   return ret;
2902 }
2903 
2904 /**
2905  * gst_pad_peer_query_position:
2906  * @pad: a #GstPad on whose peer to invoke the position query on.
2907  *       Must be a sink pad.
2908  * @format: the #GstFormat requested
2909  * @cur: (out) (allow-none): a location in which to store the current
2910  *     position, or %NULL.
2911  *
2912  * Queries the peer of a given sink pad for the stream position.
2913  *
2914  * Returns: %TRUE if the query could be performed.
2915  */
2916 gboolean
gst_pad_peer_query_position(GstPad * pad,GstFormat format,gint64 * cur)2917 gst_pad_peer_query_position (GstPad * pad, GstFormat format, gint64 * cur)
2918 {
2919   GstQuery *query;
2920   gboolean ret = FALSE;
2921 
2922   if (cur != NULL)
2923     *cur = GST_CLOCK_TIME_NONE;
2924 
2925   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2926   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
2927 
2928   query = gst_query_new_position (format);
2929   if ((ret = gst_pad_peer_query (pad, query)))
2930     gst_query_parse_position (query, NULL, cur);
2931   gst_query_unref (query);
2932 
2933   return ret;
2934 }
2935 
2936 /**
2937  * gst_pad_query_duration:
2938  * @pad: a #GstPad to invoke the duration query on.
2939  * @format: the #GstFormat requested
2940  * @duration: (out) (allow-none): a location in which to store the total
2941  *     duration, or %NULL.
2942  *
2943  * Queries a pad for the total stream duration.
2944  *
2945  * Returns: %TRUE if the query could be performed.
2946  */
2947 gboolean
gst_pad_query_duration(GstPad * pad,GstFormat format,gint64 * duration)2948 gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
2949 {
2950   GstQuery *query;
2951   gboolean ret;
2952 
2953   if (duration != NULL)
2954     *duration = GST_CLOCK_TIME_NONE;
2955 
2956   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2957   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
2958 
2959   query = gst_query_new_duration (format);
2960   if ((ret = gst_pad_query (pad, query)))
2961     gst_query_parse_duration (query, NULL, duration);
2962   gst_query_unref (query);
2963 
2964   return ret;
2965 }
2966 
2967 /**
2968  * gst_pad_peer_query_duration:
2969  * @pad: a #GstPad on whose peer pad to invoke the duration query on.
2970  *       Must be a sink pad.
2971  * @format: the #GstFormat requested
2972  * @duration: (out) (allow-none): a location in which to store the total
2973  *     duration, or %NULL.
2974  *
2975  * Queries the peer pad of a given sink pad for the total stream duration.
2976  *
2977  * Returns: %TRUE if the query could be performed.
2978  */
2979 gboolean
gst_pad_peer_query_duration(GstPad * pad,GstFormat format,gint64 * duration)2980 gst_pad_peer_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
2981 {
2982   GstQuery *query;
2983   gboolean ret = FALSE;
2984 
2985   if (duration != NULL)
2986     *duration = GST_CLOCK_TIME_NONE;
2987 
2988   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2989   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
2990   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
2991 
2992   query = gst_query_new_duration (format);
2993   if ((ret = gst_pad_peer_query (pad, query)))
2994     gst_query_parse_duration (query, NULL, duration);
2995   gst_query_unref (query);
2996 
2997   return ret;
2998 }
2999 
3000 /**
3001  * gst_pad_query_convert:
3002  * @pad: a #GstPad to invoke the convert query on.
3003  * @src_format: a #GstFormat to convert from.
3004  * @src_val: a value to convert.
3005  * @dest_format: the #GstFormat to convert to.
3006  * @dest_val: (out): a pointer to the result.
3007  *
3008  * Queries a pad to convert @src_val in @src_format to @dest_format.
3009  *
3010  * Returns: %TRUE if the query could be performed.
3011  */
3012 gboolean
gst_pad_query_convert(GstPad * pad,GstFormat src_format,gint64 src_val,GstFormat dest_format,gint64 * dest_val)3013 gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
3014     GstFormat dest_format, gint64 * dest_val)
3015 {
3016   GstQuery *query;
3017   gboolean ret;
3018 
3019   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
3020   g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE);
3021   g_return_val_if_fail (dest_val != NULL, FALSE);
3022 
3023   if (dest_format == src_format || src_val == -1) {
3024     *dest_val = src_val;
3025     return TRUE;
3026   }
3027 
3028   query = gst_query_new_convert (src_format, src_val, dest_format);
3029   if ((ret = gst_pad_query (pad, query)))
3030     gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
3031   gst_query_unref (query);
3032 
3033   return ret;
3034 }
3035 
3036 /**
3037  * gst_pad_peer_query_convert:
3038  * @pad: a #GstPad, on whose peer pad to invoke the convert query on.
3039  *       Must be a sink pad.
3040  * @src_format: a #GstFormat to convert from.
3041  * @src_val: a value to convert.
3042  * @dest_format: the #GstFormat to convert to.
3043  * @dest_val: (out): a pointer to the result.
3044  *
3045  * Queries the peer pad of a given sink pad to convert @src_val in @src_format
3046  * to @dest_format.
3047  *
3048  * Returns: %TRUE if the query could be performed.
3049  */
3050 gboolean
gst_pad_peer_query_convert(GstPad * pad,GstFormat src_format,gint64 src_val,GstFormat dest_format,gint64 * dest_val)3051 gst_pad_peer_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
3052     GstFormat dest_format, gint64 * dest_val)
3053 {
3054   GstQuery *query;
3055   gboolean ret = FALSE;
3056 
3057   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
3058   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
3059   g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE);
3060   g_return_val_if_fail (dest_val != NULL, FALSE);
3061 
3062   query = gst_query_new_convert (src_format, src_val, dest_format);
3063   if ((ret = gst_pad_peer_query (pad, query)))
3064     gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
3065   gst_query_unref (query);
3066 
3067   return ret;
3068 }
3069 
3070 /**
3071  * gst_pad_query_caps:
3072  * @pad: a  #GstPad to get the capabilities of.
3073  * @filter: (allow-none): suggested #GstCaps, or %NULL
3074  *
3075  * Gets the capabilities this pad can produce or consume.
3076  * Note that this method doesn't necessarily return the caps set by sending a
3077  * gst_event_new_caps() - use gst_pad_get_current_caps() for that instead.
3078  * gst_pad_query_caps returns all possible caps a pad can operate with, using
3079  * the pad's CAPS query function, If the query fails, this function will return
3080  * @filter, if not %NULL, otherwise ANY.
3081  *
3082  * When called on sinkpads @filter contains the caps that
3083  * upstream could produce in the order preferred by upstream. When
3084  * called on srcpads @filter contains the caps accepted by
3085  * downstream in the preferred order. @filter might be %NULL but
3086  * if it is not %NULL the returned caps will be a subset of @filter.
3087  *
3088  * Note that this function does not return writable #GstCaps, use
3089  * gst_caps_make_writable() before modifying the caps.
3090  *
3091  * Returns: (transfer full): the caps of the pad with incremented ref-count.
3092  */
3093 GstCaps *
gst_pad_query_caps(GstPad * pad,GstCaps * filter)3094 gst_pad_query_caps (GstPad * pad, GstCaps * filter)
3095 {
3096   GstCaps *result = NULL;
3097   GstQuery *query;
3098 
3099   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
3100   g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
3101 
3102   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3103       "get pad caps with filter %" GST_PTR_FORMAT, filter);
3104 
3105   query = gst_query_new_caps (filter);
3106   if (gst_pad_query (pad, query)) {
3107     gst_query_parse_caps_result (query, &result);
3108     gst_caps_ref (result);
3109     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3110         "query returned %" GST_PTR_FORMAT, result);
3111   } else if (filter) {
3112     result = gst_caps_ref (filter);
3113   } else {
3114     result = gst_caps_new_any ();
3115   }
3116   gst_query_unref (query);
3117 
3118   return result;
3119 }
3120 
3121 /**
3122  * gst_pad_peer_query_caps:
3123  * @pad: a  #GstPad to get the capabilities of.
3124  * @filter: (allow-none): a #GstCaps filter, or %NULL.
3125  *
3126  * Gets the capabilities of the peer connected to this pad. Similar to
3127  * gst_pad_query_caps().
3128  *
3129  * When called on srcpads @filter contains the caps that
3130  * upstream could produce in the order preferred by upstream. When
3131  * called on sinkpads @filter contains the caps accepted by
3132  * downstream in the preferred order. @filter might be %NULL but
3133  * if it is not %NULL the returned caps will be a subset of @filter.
3134  *
3135  * Returns: (transfer full): the caps of the peer pad with incremented
3136  * ref-count. When there is no peer pad, this function returns @filter or,
3137  * when @filter is %NULL, ANY caps.
3138  */
3139 GstCaps *
gst_pad_peer_query_caps(GstPad * pad,GstCaps * filter)3140 gst_pad_peer_query_caps (GstPad * pad, GstCaps * filter)
3141 {
3142   GstCaps *result = NULL;
3143   GstQuery *query;
3144 
3145   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
3146   g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
3147 
3148   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3149       "get pad peer caps with filter %" GST_PTR_FORMAT, filter);
3150 
3151   query = gst_query_new_caps (filter);
3152   if (gst_pad_peer_query (pad, query)) {
3153     gst_query_parse_caps_result (query, &result);
3154     gst_caps_ref (result);
3155     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3156         "peer query returned %" GST_PTR_FORMAT, result);
3157   } else if (filter) {
3158     result = gst_caps_ref (filter);
3159   } else {
3160     result = gst_caps_new_any ();
3161   }
3162   gst_query_unref (query);
3163 
3164   return result;
3165 }
3166 
3167 /**
3168  * gst_pad_query_accept_caps:
3169  * @pad: a #GstPad to check
3170  * @caps: a #GstCaps to check on the pad
3171  *
3172  * Check if the given pad accepts the caps.
3173  *
3174  * Returns: %TRUE if the pad can accept the caps.
3175  */
3176 gboolean
gst_pad_query_accept_caps(GstPad * pad,GstCaps * caps)3177 gst_pad_query_accept_caps (GstPad * pad, GstCaps * caps)
3178 {
3179   gboolean res = TRUE;
3180   GstQuery *query;
3181 
3182   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
3183   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
3184 
3185   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %"
3186       GST_PTR_FORMAT, caps);
3187 
3188   query = gst_query_new_accept_caps (caps);
3189   if (gst_pad_query (pad, query)) {
3190     gst_query_parse_accept_caps_result (query, &res);
3191     GST_DEBUG_OBJECT (pad, "query returned %d", res);
3192   }
3193   gst_query_unref (query);
3194 
3195   return res;
3196 }
3197 
3198 /**
3199  * gst_pad_peer_query_accept_caps:
3200  * @pad: a  #GstPad to check the peer of
3201  * @caps: a #GstCaps to check on the pad
3202  *
3203  * Check if the peer of @pad accepts @caps. If @pad has no peer, this function
3204  * returns %TRUE.
3205  *
3206  * Returns: %TRUE if the peer of @pad can accept the caps or @pad has no peer.
3207  */
3208 gboolean
gst_pad_peer_query_accept_caps(GstPad * pad,GstCaps * caps)3209 gst_pad_peer_query_accept_caps (GstPad * pad, GstCaps * caps)
3210 {
3211   gboolean res = TRUE;
3212   GstQuery *query;
3213 
3214   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
3215   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
3216 
3217   query = gst_query_new_accept_caps (caps);
3218   if (gst_pad_peer_query (pad, query)) {
3219     gst_query_parse_accept_caps_result (query, &res);
3220     GST_DEBUG_OBJECT (pad, "query returned %d", res);
3221   }
3222   gst_query_unref (query);
3223 
3224   return res;
3225 }
3226 
3227 static GstPad *
element_find_unlinked_pad(GstElement * element,GstPadDirection direction)3228 element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
3229 {
3230   GstIterator *iter;
3231   GstPad *unlinked_pad = NULL;
3232   gboolean done;
3233   GValue data = { 0, };
3234 
3235   switch (direction) {
3236     case GST_PAD_SRC:
3237       iter = gst_element_iterate_src_pads (element);
3238       break;
3239     case GST_PAD_SINK:
3240       iter = gst_element_iterate_sink_pads (element);
3241       break;
3242     default:
3243       g_return_val_if_reached (NULL);
3244   }
3245 
3246   done = FALSE;
3247   while (!done) {
3248     switch (gst_iterator_next (iter, &data)) {
3249       case GST_ITERATOR_OK:{
3250         GstPad *peer;
3251         GstPad *pad = g_value_get_object (&data);
3252 
3253         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
3254             GST_DEBUG_PAD_NAME (pad));
3255 
3256         peer = gst_pad_get_peer (pad);
3257         if (peer == NULL) {
3258           unlinked_pad = gst_object_ref (pad);
3259           done = TRUE;
3260           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
3261               "found existing unlinked pad %s:%s",
3262               GST_DEBUG_PAD_NAME (unlinked_pad));
3263         } else {
3264           gst_object_unref (peer);
3265         }
3266         g_value_reset (&data);
3267         break;
3268       }
3269       case GST_ITERATOR_DONE:
3270         done = TRUE;
3271         break;
3272       case GST_ITERATOR_RESYNC:
3273         gst_iterator_resync (iter);
3274         break;
3275       case GST_ITERATOR_ERROR:
3276         g_return_val_if_reached (NULL);
3277         break;
3278     }
3279   }
3280   g_value_unset (&data);
3281   gst_iterator_free (iter);
3282 
3283   return unlinked_pad;
3284 }
3285 
3286 /**
3287  * gst_bin_find_unlinked_pad:
3288  * @bin: bin in which to look for elements with unlinked pads
3289  * @direction: whether to look for an unlinked source or sink pad
3290  *
3291  * Recursively looks for elements with an unlinked pad of the given
3292  * direction within the specified bin and returns an unlinked pad
3293  * if one is found, or %NULL otherwise. If a pad is found, the caller
3294  * owns a reference to it and should use gst_object_unref() on the
3295  * pad when it is not needed any longer.
3296  *
3297  * Returns: (transfer full) (nullable): unlinked pad of the given
3298  * direction.
3299  */
3300 GstPad *
gst_bin_find_unlinked_pad(GstBin * bin,GstPadDirection direction)3301 gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
3302 {
3303   GstIterator *iter;
3304   gboolean done;
3305   GstPad *pad = NULL;
3306   GValue data = { 0, };
3307 
3308   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
3309   g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
3310 
3311   done = FALSE;
3312   iter = gst_bin_iterate_recurse (bin);
3313   while (!done) {
3314     switch (gst_iterator_next (iter, &data)) {
3315       case GST_ITERATOR_OK:{
3316         GstElement *element = g_value_get_object (&data);
3317 
3318         pad = element_find_unlinked_pad (element, direction);
3319         if (pad != NULL)
3320           done = TRUE;
3321         g_value_reset (&data);
3322         break;
3323       }
3324       case GST_ITERATOR_DONE:
3325         done = TRUE;
3326         break;
3327       case GST_ITERATOR_RESYNC:
3328         gst_iterator_resync (iter);
3329         break;
3330       case GST_ITERATOR_ERROR:
3331         g_return_val_if_reached (NULL);
3332         break;
3333     }
3334   }
3335   g_value_unset (&data);
3336   gst_iterator_free (iter);
3337 
3338   return pad;
3339 }
3340 
3341 static void
gst_bin_sync_children_states_foreach(const GValue * value,gpointer user_data)3342 gst_bin_sync_children_states_foreach (const GValue * value, gpointer user_data)
3343 {
3344   gboolean *success = user_data;
3345   GstElement *element = g_value_get_object (value);
3346 
3347   if (gst_element_is_locked_state (element)) {
3348     *success = TRUE;
3349   } else {
3350     *success = *success && gst_element_sync_state_with_parent (element);
3351 
3352     if (GST_IS_BIN (element))
3353       *success = *success
3354           && gst_bin_sync_children_states (GST_BIN_CAST (element));
3355   }
3356 }
3357 
3358 /**
3359  * gst_bin_sync_children_states:
3360  * @bin: a #GstBin
3361  *
3362  * Synchronizes the state of every child of @bin with the state
3363  * of @bin. See also gst_element_sync_state_with_parent().
3364  *
3365  * Returns: %TRUE if syncing the state was successful for all children,
3366  *  otherwise %FALSE.
3367  *
3368  * Since: 1.6
3369  */
3370 gboolean
gst_bin_sync_children_states(GstBin * bin)3371 gst_bin_sync_children_states (GstBin * bin)
3372 {
3373   GstIterator *it;
3374   GstIteratorResult res = GST_ITERATOR_OK;
3375   gboolean success = TRUE;
3376 
3377   it = gst_bin_iterate_sorted (bin);
3378 
3379   do {
3380     if (res == GST_ITERATOR_RESYNC) {
3381       success = TRUE;
3382       gst_iterator_resync (it);
3383     }
3384     res =
3385         gst_iterator_foreach (it, gst_bin_sync_children_states_foreach,
3386         &success);
3387   } while (res == GST_ITERATOR_RESYNC);
3388   gst_iterator_free (it);
3389 
3390   return success;
3391 }
3392 
3393 /**
3394  * gst_parse_bin_from_description:
3395  * @bin_description: command line describing the bin
3396  * @ghost_unlinked_pads: whether to automatically create ghost pads
3397  *     for unlinked source or sink pads within the bin
3398  * @err: where to store the error message in case of an error, or %NULL
3399  *
3400  * This is a convenience wrapper around gst_parse_launch() to create a
3401  * #GstBin from a gst-launch-style pipeline description. See
3402  * gst_parse_launch() and the gst-launch man page for details about the
3403  * syntax. Ghost pads on the bin for unlinked source or sink pads
3404  * within the bin can automatically be created (but only a maximum of
3405  * one ghost pad for each direction will be created; if you expect
3406  * multiple unlinked source pads or multiple unlinked sink pads
3407  * and want them all ghosted, you will have to create the ghost pads
3408  * yourself).
3409  *
3410  * Returns: (transfer floating) (type Gst.Bin): a
3411  *   newly-created bin, or %NULL if an error occurred.
3412  */
3413 GstElement *
gst_parse_bin_from_description(const gchar * bin_description,gboolean ghost_unlinked_pads,GError ** err)3414 gst_parse_bin_from_description (const gchar * bin_description,
3415     gboolean ghost_unlinked_pads, GError ** err)
3416 {
3417   return gst_parse_bin_from_description_full (bin_description,
3418       ghost_unlinked_pads, NULL, GST_PARSE_FLAG_NONE, err);
3419 }
3420 
3421 /**
3422  * gst_parse_bin_from_description_full:
3423  * @bin_description: command line describing the bin
3424  * @ghost_unlinked_pads: whether to automatically create ghost pads
3425  *     for unlinked source or sink pads within the bin
3426  * @context: (transfer none) (allow-none): a parse context allocated with
3427  *     gst_parse_context_new(), or %NULL
3428  * @flags: parsing options, or #GST_PARSE_FLAG_NONE
3429  * @err: where to store the error message in case of an error, or %NULL
3430  *
3431  * This is a convenience wrapper around gst_parse_launch() to create a
3432  * #GstBin from a gst-launch-style pipeline description. See
3433  * gst_parse_launch() and the gst-launch man page for details about the
3434  * syntax. Ghost pads on the bin for unlinked source or sink pads
3435  * within the bin can automatically be created (but only a maximum of
3436  * one ghost pad for each direction will be created; if you expect
3437  * multiple unlinked source pads or multiple unlinked sink pads
3438  * and want them all ghosted, you will have to create the ghost pads
3439  * yourself).
3440  *
3441  * Returns: (transfer floating) (type Gst.Element): a newly-created
3442  *   element, which is guaranteed to be a bin unless
3443  *   #GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS was passed, or %NULL if an error
3444  *   occurred.
3445  */
3446 GstElement *
gst_parse_bin_from_description_full(const gchar * bin_description,gboolean ghost_unlinked_pads,GstParseContext * context,GstParseFlags flags,GError ** err)3447 gst_parse_bin_from_description_full (const gchar * bin_description,
3448     gboolean ghost_unlinked_pads, GstParseContext * context,
3449     GstParseFlags flags, GError ** err)
3450 {
3451 #ifndef GST_DISABLE_PARSE
3452   GstPad *pad = NULL;
3453   GstElement *element;
3454   GstBin *bin;
3455   gchar *desc;
3456 
3457   g_return_val_if_fail (bin_description != NULL, NULL);
3458   g_return_val_if_fail (err == NULL || *err == NULL, NULL);
3459 
3460   GST_DEBUG ("Making bin from description '%s'", bin_description);
3461 
3462   /* parse the pipeline to a bin */
3463   if (flags & GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS) {
3464     element = gst_parse_launch_full (bin_description, context, flags, err);
3465   } else {
3466     desc = g_strdup_printf ("bin.( %s )", bin_description);
3467     element = gst_parse_launch_full (desc, context, flags, err);
3468     g_free (desc);
3469   }
3470 
3471   if (element == NULL || (err && *err != NULL)) {
3472     if (element)
3473       gst_object_unref (element);
3474     return NULL;
3475   }
3476 
3477   if (GST_IS_BIN (element)) {
3478     bin = GST_BIN (element);
3479   } else {
3480     return element;
3481   }
3482 
3483   /* find pads and ghost them if necessary */
3484   if (ghost_unlinked_pads) {
3485     if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) {
3486       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
3487       gst_object_unref (pad);
3488     }
3489     if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) {
3490       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
3491       gst_object_unref (pad);
3492     }
3493   }
3494 
3495   return GST_ELEMENT (bin);
3496 #else
3497   gchar *msg;
3498 
3499   GST_WARNING ("Disabled API called");
3500 
3501   msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
3502   g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
3503   g_free (msg);
3504 
3505   return NULL;
3506 #endif
3507 }
3508 
3509 /**
3510  * gst_util_get_timestamp:
3511  *
3512  * Get a timestamp as GstClockTime to be used for interval measurements.
3513  * The timestamp should not be interpreted in any other way.
3514  *
3515  * Returns: the timestamp
3516  */
3517 GstClockTime
gst_util_get_timestamp(void)3518 gst_util_get_timestamp (void)
3519 {
3520 #if defined (HAVE_POSIX_TIMERS) && defined(HAVE_MONOTONIC_CLOCK) &&\
3521     defined (HAVE_CLOCK_GETTIME)
3522   struct timespec now;
3523 
3524   clock_gettime (CLOCK_MONOTONIC, &now);
3525   return GST_TIMESPEC_TO_TIME (now);
3526 #else
3527   return g_get_monotonic_time () * 1000;
3528 #endif
3529 }
3530 
3531 /**
3532  * gst_util_array_binary_search:
3533  * @array: the sorted input array
3534  * @num_elements: number of elements in the array
3535  * @element_size: size of every element in bytes
3536  * @search_func: (scope call): function to compare two elements, @search_data will always be passed as second argument
3537  * @mode: search mode that should be used
3538  * @search_data: element that should be found
3539  * @user_data: (closure): data to pass to @search_func
3540  *
3541  * Searches inside @array for @search_data by using the comparison function
3542  * @search_func. @array must be sorted ascending.
3543  *
3544  * As @search_data is always passed as second argument to @search_func it's
3545  * not required that @search_data has the same type as the array elements.
3546  *
3547  * The complexity of this search function is O(log (num_elements)).
3548  *
3549  * Returns: (transfer none) (nullable): The address of the found
3550  * element or %NULL if nothing was found
3551  */
3552 gpointer
gst_util_array_binary_search(gpointer array,guint num_elements,gsize element_size,GCompareDataFunc search_func,GstSearchMode mode,gconstpointer search_data,gpointer user_data)3553 gst_util_array_binary_search (gpointer array, guint num_elements,
3554     gsize element_size, GCompareDataFunc search_func, GstSearchMode mode,
3555     gconstpointer search_data, gpointer user_data)
3556 {
3557   glong left = 0, right = num_elements - 1, m;
3558   gint ret;
3559   guint8 *data = (guint8 *) array;
3560 
3561   g_return_val_if_fail (array != NULL, NULL);
3562   g_return_val_if_fail (element_size > 0, NULL);
3563   g_return_val_if_fail (search_func != NULL, NULL);
3564 
3565   /* 0. No elements => return NULL */
3566   if (num_elements == 0)
3567     return NULL;
3568 
3569   /* 1. If search_data is before the 0th element return the 0th element */
3570   ret = search_func (data, search_data, user_data);
3571   if ((ret >= 0 && mode == GST_SEARCH_MODE_AFTER) || ret == 0)
3572     return data;
3573   else if (ret > 0)
3574     return NULL;
3575 
3576   /* 2. If search_data is after the last element return the last element */
3577   ret =
3578       search_func (data + (num_elements - 1) * element_size, search_data,
3579       user_data);
3580   if ((ret <= 0 && mode == GST_SEARCH_MODE_BEFORE) || ret == 0)
3581     return data + (num_elements - 1) * element_size;
3582   else if (ret < 0)
3583     return NULL;
3584 
3585   /* 3. else binary search */
3586   while (TRUE) {
3587     m = left + (right - left) / 2;
3588 
3589     ret = search_func (data + m * element_size, search_data, user_data);
3590 
3591     if (ret == 0) {
3592       return data + m * element_size;
3593     } else if (ret < 0) {
3594       left = m + 1;
3595     } else {
3596       right = m - 1;
3597     }
3598 
3599     /* No exact match found */
3600     if (right < left) {
3601       if (mode == GST_SEARCH_MODE_EXACT) {
3602         return NULL;
3603       } else if (mode == GST_SEARCH_MODE_AFTER) {
3604         if (ret < 0)
3605           return (m < num_elements) ? data + (m + 1) * element_size : NULL;
3606         else
3607           return data + m * element_size;
3608       } else {
3609         if (ret < 0)
3610           return data + m * element_size;
3611         else
3612           return (m > 0) ? data + (m - 1) * element_size : NULL;
3613       }
3614     }
3615   }
3616 }
3617 
3618 /* Finds the greatest common divisor.
3619  * Returns 1 if none other found.
3620  * This is Euclid's algorithm. */
3621 
3622 /**
3623  * gst_util_greatest_common_divisor:
3624  * @a: First value as #gint
3625  * @b: Second value as #gint
3626  *
3627  * Calculates the greatest common divisor of @a
3628  * and @b.
3629  *
3630  * Returns: Greatest common divisor of @a and @b
3631  */
3632 gint
gst_util_greatest_common_divisor(gint a,gint b)3633 gst_util_greatest_common_divisor (gint a, gint b)
3634 {
3635   while (b != 0) {
3636     int temp = a;
3637 
3638     a = b;
3639     b = temp % b;
3640   }
3641 
3642   return ABS (a);
3643 }
3644 
3645 /**
3646  * gst_util_greatest_common_divisor_int64:
3647  * @a: First value as #gint64
3648  * @b: Second value as #gint64
3649  *
3650  * Calculates the greatest common divisor of @a
3651  * and @b.
3652  *
3653  * Returns: Greatest common divisor of @a and @b
3654  */
3655 gint64
gst_util_greatest_common_divisor_int64(gint64 a,gint64 b)3656 gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b)
3657 {
3658   while (b != 0) {
3659     gint64 temp = a;
3660 
3661     a = b;
3662     b = temp % b;
3663   }
3664 
3665   return ABS (a);
3666 }
3667 
3668 
3669 /**
3670  * gst_util_fraction_to_double:
3671  * @src_n: Fraction numerator as #gint
3672  * @src_d: Fraction denominator #gint
3673  * @dest: (out): pointer to a #gdouble for the result
3674  *
3675  * Transforms a fraction to a #gdouble.
3676  */
3677 void
gst_util_fraction_to_double(gint src_n,gint src_d,gdouble * dest)3678 gst_util_fraction_to_double (gint src_n, gint src_d, gdouble * dest)
3679 {
3680   g_return_if_fail (dest != NULL);
3681   g_return_if_fail (src_d != 0);
3682 
3683   *dest = ((gdouble) src_n) / ((gdouble) src_d);
3684 }
3685 
3686 #define MAX_TERMS       30
3687 #define MIN_DIVISOR     1.0e-10
3688 #define MAX_ERROR       1.0e-20
3689 
3690 /* use continued fractions to transform a double into a fraction,
3691  * see http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac.
3692  * This algorithm takes care of overflows.
3693  */
3694 
3695 /**
3696  * gst_util_double_to_fraction:
3697  * @src: #gdouble to transform
3698  * @dest_n: (out): pointer to a #gint to hold the result numerator
3699  * @dest_d: (out): pointer to a #gint to hold the result denominator
3700  *
3701  * Transforms a #gdouble to a fraction and simplifies
3702  * the result.
3703  */
3704 void
gst_util_double_to_fraction(gdouble src,gint * dest_n,gint * dest_d)3705 gst_util_double_to_fraction (gdouble src, gint * dest_n, gint * dest_d)
3706 {
3707 
3708   gdouble V, F;                 /* double being converted */
3709   gint N, D;                    /* will contain the result */
3710   gint A;                       /* current term in continued fraction */
3711   gint64 N1, D1;                /* numerator, denominator of last approx */
3712   gint64 N2, D2;                /* numerator, denominator of previous approx */
3713   gint i;
3714   gint gcd;
3715   gboolean negative = FALSE;
3716 
3717   g_return_if_fail (dest_n != NULL);
3718   g_return_if_fail (dest_d != NULL);
3719 
3720   /* initialize fraction being converted */
3721   F = src;
3722   if (F < 0.0) {
3723     F = -F;
3724     negative = TRUE;
3725   }
3726 
3727   V = F;
3728   /* initialize fractions with 1/0, 0/1 */
3729   N1 = 1;
3730   D1 = 0;
3731   N2 = 0;
3732   D2 = 1;
3733   N = 1;
3734   D = 1;
3735 
3736   for (i = 0; i < MAX_TERMS; i++) {
3737     /* get next term */
3738     A = (gint) F;               /* no floor() needed, F is always >= 0 */
3739     /* get new divisor */
3740     F = F - A;
3741 
3742     /* calculate new fraction in temp */
3743     N2 = N1 * A + N2;
3744     D2 = D1 * A + D2;
3745 
3746     /* guard against overflow */
3747     if (N2 > G_MAXINT || D2 > G_MAXINT) {
3748       break;
3749     }
3750 
3751     N = N2;
3752     D = D2;
3753 
3754     /* save last two fractions */
3755     N2 = N1;
3756     D2 = D1;
3757     N1 = N;
3758     D1 = D;
3759 
3760     /* quit if dividing by zero or close enough to target */
3761     if (F < MIN_DIVISOR || fabs (V - ((gdouble) N) / D) < MAX_ERROR) {
3762       break;
3763     }
3764 
3765     /* Take reciprocal */
3766     F = 1 / F;
3767   }
3768   /* fix for overflow */
3769   if (D == 0) {
3770     N = G_MAXINT;
3771     D = 1;
3772   }
3773   /* fix for negative */
3774   if (negative)
3775     N = -N;
3776 
3777   /* simplify */
3778   gcd = gst_util_greatest_common_divisor (N, D);
3779   if (gcd) {
3780     N /= gcd;
3781     D /= gcd;
3782   }
3783 
3784   /* set results */
3785   *dest_n = N;
3786   *dest_d = D;
3787 }
3788 
3789 /**
3790  * gst_util_fraction_multiply:
3791  * @a_n: Numerator of first value
3792  * @a_d: Denominator of first value
3793  * @b_n: Numerator of second value
3794  * @b_d: Denominator of second value
3795  * @res_n: (out): Pointer to #gint to hold the result numerator
3796  * @res_d: (out): Pointer to #gint to hold the result denominator
3797  *
3798  * Multiplies the fractions @a_n/@a_d and @b_n/@b_d and stores
3799  * the result in @res_n and @res_d.
3800  *
3801  * Returns: %FALSE on overflow, %TRUE otherwise.
3802  */
3803 gboolean
gst_util_fraction_multiply(gint a_n,gint a_d,gint b_n,gint b_d,gint * res_n,gint * res_d)3804 gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d,
3805     gint * res_n, gint * res_d)
3806 {
3807   gint gcd;
3808 
3809   g_return_val_if_fail (res_n != NULL, FALSE);
3810   g_return_val_if_fail (res_d != NULL, FALSE);
3811   g_return_val_if_fail (a_d != 0, FALSE);
3812   g_return_val_if_fail (b_d != 0, FALSE);
3813 
3814   /* early out if either is 0, as its gcd would be 0 */
3815   if (a_n == 0 || b_n == 0) {
3816     *res_n = 0;
3817     *res_d = 1;
3818     return TRUE;
3819   }
3820 
3821   gcd = gst_util_greatest_common_divisor (a_n, a_d);
3822   a_n /= gcd;
3823   a_d /= gcd;
3824 
3825   gcd = gst_util_greatest_common_divisor (b_n, b_d);
3826   b_n /= gcd;
3827   b_d /= gcd;
3828 
3829   gcd = gst_util_greatest_common_divisor (a_n, b_d);
3830   a_n /= gcd;
3831   b_d /= gcd;
3832 
3833   gcd = gst_util_greatest_common_divisor (a_d, b_n);
3834   a_d /= gcd;
3835   b_n /= gcd;
3836 
3837   /* This would result in overflow */
3838   if (a_n != 0 && G_MAXINT / ABS (a_n) < ABS (b_n))
3839     return FALSE;
3840   if (G_MAXINT / ABS (a_d) < ABS (b_d))
3841     return FALSE;
3842 
3843   *res_n = a_n * b_n;
3844   *res_d = a_d * b_d;
3845 
3846   gcd = gst_util_greatest_common_divisor (*res_n, *res_d);
3847   *res_n /= gcd;
3848   *res_d /= gcd;
3849 
3850   return TRUE;
3851 }
3852 
3853 /**
3854  * gst_util_fraction_add:
3855  * @a_n: Numerator of first value
3856  * @a_d: Denominator of first value
3857  * @b_n: Numerator of second value
3858  * @b_d: Denominator of second value
3859  * @res_n: (out): Pointer to #gint to hold the result numerator
3860  * @res_d: (out): Pointer to #gint to hold the result denominator
3861  *
3862  * Adds the fractions @a_n/@a_d and @b_n/@b_d and stores
3863  * the result in @res_n and @res_d.
3864  *
3865  * Returns: %FALSE on overflow, %TRUE otherwise.
3866  */
3867 gboolean
gst_util_fraction_add(gint a_n,gint a_d,gint b_n,gint b_d,gint * res_n,gint * res_d)3868 gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint * res_n,
3869     gint * res_d)
3870 {
3871   gint gcd;
3872 
3873   g_return_val_if_fail (res_n != NULL, FALSE);
3874   g_return_val_if_fail (res_d != NULL, FALSE);
3875   g_return_val_if_fail (a_d != 0, FALSE);
3876   g_return_val_if_fail (b_d != 0, FALSE);
3877 
3878   gcd = gst_util_greatest_common_divisor (a_n, a_d);
3879   a_n /= gcd;
3880   a_d /= gcd;
3881 
3882   gcd = gst_util_greatest_common_divisor (b_n, b_d);
3883   b_n /= gcd;
3884   b_d /= gcd;
3885 
3886   if (a_n == 0) {
3887     *res_n = b_n;
3888     *res_d = b_d;
3889     return TRUE;
3890   }
3891   if (b_n == 0) {
3892     *res_n = a_n;
3893     *res_d = a_d;
3894     return TRUE;
3895   }
3896 
3897   /* This would result in overflow */
3898   if (G_MAXINT / ABS (a_n) < ABS (b_n))
3899     return FALSE;
3900   if (G_MAXINT / ABS (a_d) < ABS (b_d))
3901     return FALSE;
3902 
3903   *res_n = (a_n * b_d) + (a_d * b_n);
3904   *res_d = a_d * b_d;
3905 
3906   gcd = gst_util_greatest_common_divisor (*res_n, *res_d);
3907   if (gcd) {
3908     *res_n /= gcd;
3909     *res_d /= gcd;
3910   } else {
3911     /* res_n == 0 */
3912     *res_d = 1;
3913   }
3914 
3915   return TRUE;
3916 }
3917 
3918 /**
3919  * gst_util_fraction_compare:
3920  * @a_n: Numerator of first value
3921  * @a_d: Denominator of first value
3922  * @b_n: Numerator of second value
3923  * @b_d: Denominator of second value
3924  *
3925  * Compares the fractions @a_n/@a_d and @b_n/@b_d and returns
3926  * -1 if a < b, 0 if a = b and 1 if a > b.
3927  *
3928  * Returns: -1 if a < b; 0 if a = b; 1 if a > b.
3929  */
3930 gint
gst_util_fraction_compare(gint a_n,gint a_d,gint b_n,gint b_d)3931 gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d)
3932 {
3933   gint64 new_num_1;
3934   gint64 new_num_2;
3935   gint gcd;
3936 
3937   g_return_val_if_fail (a_d != 0 && b_d != 0, 0);
3938 
3939   /* Simplify */
3940   gcd = gst_util_greatest_common_divisor (a_n, a_d);
3941   a_n /= gcd;
3942   a_d /= gcd;
3943 
3944   gcd = gst_util_greatest_common_divisor (b_n, b_d);
3945   b_n /= gcd;
3946   b_d /= gcd;
3947 
3948   /* fractions are reduced when set, so we can quickly see if they're equal */
3949   if (a_n == b_n && a_d == b_d)
3950     return 0;
3951 
3952   /* extend to 64 bits */
3953   new_num_1 = ((gint64) a_n) * b_d;
3954   new_num_2 = ((gint64) b_n) * a_d;
3955   if (new_num_1 < new_num_2)
3956     return -1;
3957   if (new_num_1 > new_num_2)
3958     return 1;
3959 
3960   /* Should not happen because a_d and b_d are not 0 */
3961   g_return_val_if_reached (0);
3962 }
3963 
3964 static gchar *
gst_pad_create_stream_id_internal(GstPad * pad,GstElement * parent,const gchar * stream_id)3965 gst_pad_create_stream_id_internal (GstPad * pad, GstElement * parent,
3966     const gchar * stream_id)
3967 {
3968   GstEvent *upstream_event;
3969   gchar *upstream_stream_id = NULL, *new_stream_id;
3970   GstPad *sinkpad;
3971 
3972   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
3973   g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
3974   g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
3975 
3976   g_return_val_if_fail (parent->numsinkpads <= 1, NULL);
3977 
3978   /* If the element has multiple source pads it must
3979    * provide a stream-id for every source pad, otherwise
3980    * all source pads will have the same and are not
3981    * distinguishable */
3982   g_return_val_if_fail (parent->numsrcpads <= 1 || stream_id, NULL);
3983 
3984   /* First try to get the upstream stream-start stream-id from the sinkpad.
3985    * This will only work for non-source elements */
3986   sinkpad = gst_element_get_static_pad (parent, "sink");
3987   if (sinkpad) {
3988     upstream_event =
3989         gst_pad_get_sticky_event (sinkpad, GST_EVENT_STREAM_START, 0);
3990     if (upstream_event) {
3991       const gchar *tmp;
3992 
3993       gst_event_parse_stream_start (upstream_event, &tmp);
3994       if (tmp)
3995         upstream_stream_id = g_strdup (tmp);
3996       gst_event_unref (upstream_event);
3997     }
3998     gst_object_unref (sinkpad);
3999   }
4000 
4001   /* The only case where we don't have an upstream stream-start event
4002    * here is for source elements */
4003   if (!upstream_stream_id) {
4004     GstQuery *query;
4005     gchar *uri = NULL;
4006 
4007     /* Try to generate one from the URI query and
4008      * if it fails take a random number instead */
4009     query = gst_query_new_uri ();
4010     if (gst_element_query (parent, query)) {
4011       gst_query_parse_uri (query, &uri);
4012     }
4013 
4014     if (uri) {
4015       GChecksum *cs;
4016 
4017       /* And then generate an SHA256 sum of the URI */
4018       cs = g_checksum_new (G_CHECKSUM_SHA256);
4019       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
4020       g_free (uri);
4021       upstream_stream_id = g_strdup (g_checksum_get_string (cs));
4022       g_checksum_free (cs);
4023     } else {
4024       /* Just get some random number if the URI query fails */
4025       GST_FIXME_OBJECT (pad, "Creating random stream-id, consider "
4026           "implementing a deterministic way of creating a stream-id");
4027       upstream_stream_id =
4028           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
4029           g_random_int (), g_random_int ());
4030     }
4031 
4032     gst_query_unref (query);
4033   }
4034 
4035   if (stream_id) {
4036     new_stream_id = g_strconcat (upstream_stream_id, "/", stream_id, NULL);
4037   } else {
4038     new_stream_id = g_strdup (upstream_stream_id);
4039   }
4040 
4041   g_free (upstream_stream_id);
4042 
4043   return new_stream_id;
4044 }
4045 
4046 /**
4047  * gst_pad_create_stream_id_printf_valist:
4048  * @pad: A source #GstPad
4049  * @parent: Parent #GstElement of @pad
4050  * @stream_id: (allow-none): The stream-id
4051  * @var_args: parameters for the @stream_id format string
4052  *
4053  * Creates a stream-id for the source #GstPad @pad by combining the
4054  * upstream information with the optional @stream_id of the stream
4055  * of @pad. @pad must have a parent #GstElement and which must have zero
4056  * or one sinkpad. @stream_id can only be %NULL if the parent element
4057  * of @pad has only a single source pad.
4058  *
4059  * This function generates an unique stream-id by getting the upstream
4060  * stream-start event stream ID and appending @stream_id to it. If the
4061  * element has no sinkpad it will generate an upstream stream-id by
4062  * doing an URI query on the element and in the worst case just uses
4063  * a random number. Source elements that don't implement the URI
4064  * handler interface should ideally generate a unique, deterministic
4065  * stream-id manually instead.
4066  *
4067  * Returns: A stream-id for @pad. g_free() after usage.
4068  */
4069 gchar *
gst_pad_create_stream_id_printf_valist(GstPad * pad,GstElement * parent,const gchar * stream_id,va_list var_args)4070 gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent,
4071     const gchar * stream_id, va_list var_args)
4072 {
4073   gchar *expanded = NULL, *new_stream_id;
4074 
4075   if (stream_id)
4076     expanded = g_strdup_vprintf (stream_id, var_args);
4077 
4078   new_stream_id = gst_pad_create_stream_id_internal (pad, parent, expanded);
4079 
4080   g_free (expanded);
4081 
4082   return new_stream_id;
4083 }
4084 
4085 /**
4086  * gst_pad_create_stream_id_printf:
4087  * @pad: A source #GstPad
4088  * @parent: Parent #GstElement of @pad
4089  * @stream_id: (allow-none): The stream-id
4090  * @...: parameters for the @stream_id format string
4091  *
4092  * Creates a stream-id for the source #GstPad @pad by combining the
4093  * upstream information with the optional @stream_id of the stream
4094  * of @pad. @pad must have a parent #GstElement and which must have zero
4095  * or one sinkpad. @stream_id can only be %NULL if the parent element
4096  * of @pad has only a single source pad.
4097  *
4098  * This function generates an unique stream-id by getting the upstream
4099  * stream-start event stream ID and appending @stream_id to it. If the
4100  * element has no sinkpad it will generate an upstream stream-id by
4101  * doing an URI query on the element and in the worst case just uses
4102  * a random number. Source elements that don't implement the URI
4103  * handler interface should ideally generate a unique, deterministic
4104  * stream-id manually instead.
4105  *
4106  * Returns: A stream-id for @pad. g_free() after usage.
4107  */
4108 gchar *
gst_pad_create_stream_id_printf(GstPad * pad,GstElement * parent,const gchar * stream_id,...)4109 gst_pad_create_stream_id_printf (GstPad * pad, GstElement * parent,
4110     const gchar * stream_id, ...)
4111 {
4112   va_list var_args;
4113   gchar *new_stream_id;
4114 
4115   va_start (var_args, stream_id);
4116   new_stream_id =
4117       gst_pad_create_stream_id_printf_valist (pad, parent, stream_id, var_args);
4118   va_end (var_args);
4119 
4120   return new_stream_id;
4121 }
4122 
4123 /**
4124  * gst_pad_create_stream_id:
4125  * @pad: A source #GstPad
4126  * @parent: Parent #GstElement of @pad
4127  * @stream_id: (allow-none): The stream-id
4128  *
4129  * Creates a stream-id for the source #GstPad @pad by combining the
4130  * upstream information with the optional @stream_id of the stream
4131  * of @pad. @pad must have a parent #GstElement and which must have zero
4132  * or one sinkpad. @stream_id can only be %NULL if the parent element
4133  * of @pad has only a single source pad.
4134  *
4135  * This function generates an unique stream-id by getting the upstream
4136  * stream-start event stream ID and appending @stream_id to it. If the
4137  * element has no sinkpad it will generate an upstream stream-id by
4138  * doing an URI query on the element and in the worst case just uses
4139  * a random number. Source elements that don't implement the URI
4140  * handler interface should ideally generate a unique, deterministic
4141  * stream-id manually instead.
4142  *
4143  * Since stream IDs are sorted alphabetically, any numbers in the
4144  * stream ID should be printed with a fixed number of characters,
4145  * preceded by 0's, such as by using the format \%03u instead of \%u.
4146  *
4147  * Returns: A stream-id for @pad. g_free() after usage.
4148  */
4149 gchar *
gst_pad_create_stream_id(GstPad * pad,GstElement * parent,const gchar * stream_id)4150 gst_pad_create_stream_id (GstPad * pad, GstElement * parent,
4151     const gchar * stream_id)
4152 {
4153   return gst_pad_create_stream_id_internal (pad, parent, stream_id);
4154 }
4155 
4156 /**
4157  * gst_pad_get_stream_id:
4158  * @pad: A source #GstPad
4159  *
4160  * Returns the current stream-id for the @pad, or %NULL if none has been
4161  * set yet, i.e. the pad has not received a stream-start event yet.
4162  *
4163  * This is a convenience wrapper around gst_pad_get_sticky_event() and
4164  * gst_event_parse_stream_start().
4165  *
4166  * The returned stream-id string should be treated as an opaque string, its
4167  * contents should not be interpreted.
4168  *
4169  * Returns: (nullable): a newly-allocated copy of the stream-id for
4170  *     @pad, or %NULL.  g_free() the returned string when no longer
4171  *     needed.
4172  *
4173  * Since: 1.2
4174  */
4175 gchar *
gst_pad_get_stream_id(GstPad * pad)4176 gst_pad_get_stream_id (GstPad * pad)
4177 {
4178   const gchar *stream_id = NULL;
4179   GstEvent *event;
4180   gchar *ret = NULL;
4181 
4182   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
4183 
4184   event = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0);
4185   if (event != NULL) {
4186     gst_event_parse_stream_start (event, &stream_id);
4187     ret = g_strdup (stream_id);
4188     gst_event_unref (event);
4189     GST_LOG_OBJECT (pad, "pad has stream-id '%s'", ret);
4190   } else {
4191     GST_DEBUG_OBJECT (pad, "pad has not received a stream-start event yet");
4192   }
4193 
4194   return ret;
4195 }
4196 
4197 /**
4198  * gst_pad_get_stream:
4199  * @pad: A source #GstPad
4200  *
4201  * Returns the current #GstStream for the @pad, or %NULL if none has been
4202  * set yet, i.e. the pad has not received a stream-start event yet.
4203  *
4204  * This is a convenience wrapper around gst_pad_get_sticky_event() and
4205  * gst_event_parse_stream().
4206  *
4207  * Returns: (nullable) (transfer full): the current #GstStream for @pad, or %NULL.
4208  *     unref the returned stream when no longer needed.
4209  *
4210  * Since: 1.10
4211  */
4212 GstStream *
gst_pad_get_stream(GstPad * pad)4213 gst_pad_get_stream (GstPad * pad)
4214 {
4215   GstStream *stream = NULL;
4216   GstEvent *event;
4217 
4218   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
4219 
4220   event = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0);
4221   if (event != NULL) {
4222     gst_event_parse_stream (event, &stream);
4223     gst_event_unref (event);
4224     GST_LOG_OBJECT (pad, "pad has stream object %p", stream);
4225   } else {
4226     GST_DEBUG_OBJECT (pad, "pad has not received a stream-start event yet");
4227   }
4228 
4229   return stream;
4230 }
4231 
4232 /**
4233  * gst_util_group_id_next:
4234  *
4235  * Return a constantly incrementing group id.
4236  *
4237  * This function is used to generate a new group-id for the
4238  * stream-start event.
4239  *
4240  * This function never returns %GST_GROUP_ID_INVALID (which is 0)
4241  *
4242  * Returns: A constantly incrementing unsigned integer, which might
4243  * overflow back to 0 at some point.
4244  */
4245 guint
gst_util_group_id_next(void)4246 gst_util_group_id_next (void)
4247 {
4248   static gint counter = 1;
4249   gint ret = g_atomic_int_add (&counter, 1);
4250 
4251   /* Make sure we don't return GST_GROUP_ID_INVALID */
4252   if (G_UNLIKELY (ret == GST_GROUP_ID_INVALID))
4253     ret = g_atomic_int_add (&counter, 1);
4254 
4255   return ret;
4256 }
4257 
4258 /* Compute log2 of the passed 64-bit number by finding the highest set bit */
4259 static guint
gst_log2(GstClockTime in)4260 gst_log2 (GstClockTime in)
4261 {
4262   const guint64 b[] =
4263       { 0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000LL };
4264   const guint64 S[] = { 1, 2, 4, 8, 16, 32 };
4265   int i;
4266 
4267   guint count = 0;
4268   for (i = 5; i >= 0; i--) {
4269     if (in & b[i]) {
4270       in >>= S[i];
4271       count |= S[i];
4272     }
4273   }
4274 
4275   return count;
4276 }
4277 
4278 /**
4279  * gst_calculate_linear_regression: (skip)
4280  * @xy: Pairs of (x,y) values
4281  * @temp: Temporary scratch space used by the function
4282  * @n: number of (x,y) pairs
4283  * @m_num: (out): numerator of calculated slope
4284  * @m_denom: (out): denominator of calculated slope
4285  * @b: (out): Offset at Y-axis
4286  * @xbase: (out): Offset at X-axis
4287  * @r_squared: (out): R-squared
4288  *
4289  * Calculates the linear regression of the values @xy and places the
4290  * result in @m_num, @m_denom, @b and @xbase, representing the function
4291  *   y(x) = m_num/m_denom * (x - xbase) + b
4292  * that has the least-square distance from all points @x and @y.
4293  *
4294  * @r_squared will contain the remaining error.
4295  *
4296  * If @temp is not %NULL, it will be used as temporary space for the function,
4297  * in which case the function works without any allocation at all. If @temp is
4298  * %NULL, an allocation will take place. @temp should have at least the same
4299  * amount of memory allocated as @xy, i.e. 2*n*sizeof(GstClockTime).
4300  *
4301  * > This function assumes (x,y) values with reasonable large differences
4302  * > between them. It will not calculate the exact results if the differences
4303  * > between neighbouring values are too small due to not being able to
4304  * > represent sub-integer values during the calculations.
4305  *
4306  * Returns: %TRUE if the linear regression was successfully calculated
4307  *
4308  * Since: 1.12
4309  */
4310 /* http://mathworld.wolfram.com/LeastSquaresFitting.html
4311  * with SLAVE_LOCK
4312  */
4313 gboolean
gst_calculate_linear_regression(const GstClockTime * xy,GstClockTime * temp,guint n,GstClockTime * m_num,GstClockTime * m_denom,GstClockTime * b,GstClockTime * xbase,gdouble * r_squared)4314 gst_calculate_linear_regression (const GstClockTime * xy,
4315     GstClockTime * temp, guint n,
4316     GstClockTime * m_num, GstClockTime * m_denom,
4317     GstClockTime * b, GstClockTime * xbase, gdouble * r_squared)
4318 {
4319   const GstClockTime *x, *y;
4320   GstClockTime *newx, *newy;
4321   GstClockTime xmin, ymin, xbar, ybar, xbar4, ybar4;
4322   GstClockTime xmax, ymax;
4323   GstClockTimeDiff sxx, sxy, syy;
4324   gint i, j;
4325   gint pshift = 0;
4326   gint max_bits;
4327 
4328   g_return_val_if_fail (xy != NULL, FALSE);
4329   g_return_val_if_fail (m_num != NULL, FALSE);
4330   g_return_val_if_fail (m_denom != NULL, FALSE);
4331   g_return_val_if_fail (b != NULL, FALSE);
4332   g_return_val_if_fail (xbase != NULL, FALSE);
4333   g_return_val_if_fail (r_squared != NULL, FALSE);
4334 
4335   x = xy;
4336   y = xy + 1;
4337 
4338   xbar = ybar = sxx = syy = sxy = 0;
4339 
4340   xmin = ymin = G_MAXUINT64;
4341   xmax = ymax = 0;
4342   for (i = j = 0; i < n; i++, j += 2) {
4343     xmin = MIN (xmin, x[j]);
4344     ymin = MIN (ymin, y[j]);
4345 
4346     xmax = MAX (xmax, x[j]);
4347     ymax = MAX (ymax, y[j]);
4348   }
4349 
4350   if (temp == NULL) {
4351     /* Allocate up to 1kb on the stack, otherwise heap */
4352     newx = n > 64 ? g_new (GstClockTime, 2 * n) : g_newa (GstClockTime, 2 * n);
4353     newy = newx + 1;
4354   } else {
4355     newx = temp;
4356     newy = temp + 1;
4357   }
4358 
4359   /* strip off unnecessary bits of precision */
4360   for (i = j = 0; i < n; i++, j += 2) {
4361     newx[j] = x[j] - xmin;
4362     newy[j] = y[j] - ymin;
4363   }
4364 
4365 #ifdef DEBUGGING_ENABLED
4366   GST_CAT_DEBUG (GST_CAT_CLOCK, "reduced numbers:");
4367   for (i = j = 0; i < n; i++, j += 2)
4368     GST_CAT_DEBUG (GST_CAT_CLOCK,
4369         "  %" G_GUINT64_FORMAT "  %" G_GUINT64_FORMAT, newx[j], newy[j]);
4370 #endif
4371 
4372   /* have to do this precisely otherwise the results are pretty much useless.
4373    * should guarantee that none of these accumulators can overflow */
4374 
4375   /* quantities on the order of 1e10 to 1e13 -> 30-35 bits;
4376    * window size a max of 2^10, so
4377    this addition could end up around 2^45 or so -- ample headroom */
4378   for (i = j = 0; i < n; i++, j += 2) {
4379     /* Just in case assumptions about headroom prove false, let's check */
4380     if ((newx[j] > 0 && G_MAXUINT64 - xbar <= newx[j]) ||
4381         (newy[j] > 0 && G_MAXUINT64 - ybar <= newy[j])) {
4382       GST_CAT_WARNING (GST_CAT_CLOCK,
4383           "Regression overflowed in clock slaving! xbar %"
4384           G_GUINT64_FORMAT " newx[j] %" G_GUINT64_FORMAT " ybar %"
4385           G_GUINT64_FORMAT " newy[j] %" G_GUINT64_FORMAT, xbar, newx[j], ybar,
4386           newy[j]);
4387       if (temp == NULL && n > 64)
4388         g_free (newx);
4389       return FALSE;
4390     }
4391 
4392     xbar += newx[j];
4393     ybar += newy[j];
4394   }
4395   xbar /= n;
4396   ybar /= n;
4397 
4398   /* multiplying directly would give quantities on the order of 1e20-1e26 ->
4399    * 60 bits to 70 bits times the window size that's 80 which is too much.
4400    * Instead we (1) subtract off the xbar*ybar in the loop instead of after,
4401    * to avoid accumulation; (2) shift off some estimated number of bits from
4402    * each multiplicand to limit the expected ceiling. For strange
4403    * distributions of input values, things can still overflow, in which
4404    * case we drop precision and retry - at most a few times, in practice rarely
4405    */
4406 
4407   /* Guess how many bits we might need for the usual distribution of input,
4408    * with a fallback loop that drops precision if things go pear-shaped */
4409   max_bits = gst_log2 (MAX (xmax - xmin, ymax - ymin)) * 7 / 8 + gst_log2 (n);
4410   if (max_bits > 64)
4411     pshift = max_bits - 64;
4412 
4413   i = 0;
4414   do {
4415 #ifdef DEBUGGING_ENABLED
4416     GST_CAT_DEBUG (GST_CAT_CLOCK,
4417         "Restarting regression with precision shift %u", pshift);
4418 #endif
4419 
4420     xbar4 = xbar >> pshift;
4421     ybar4 = ybar >> pshift;
4422     sxx = syy = sxy = 0;
4423     for (i = j = 0; i < n; i++, j += 2) {
4424       GstClockTime newx4, newy4;
4425       GstClockTimeDiff tmp;
4426 
4427       newx4 = newx[j] >> pshift;
4428       newy4 = newy[j] >> pshift;
4429 
4430       tmp = (newx4 + xbar4) * (newx4 - xbar4);
4431       if (G_UNLIKELY (tmp > 0 && sxx > 0 && (G_MAXINT64 - sxx <= tmp))) {
4432         do {
4433           /* Drop some precision and restart */
4434           pshift++;
4435           sxx /= 4;
4436           tmp /= 4;
4437         } while (G_MAXINT64 - sxx <= tmp);
4438         break;
4439       } else if (G_UNLIKELY (tmp < 0 && sxx < 0 && (G_MININT64 - sxx >= tmp))) {
4440         do {
4441           /* Drop some precision and restart */
4442           pshift++;
4443           sxx /= 4;
4444           tmp /= 4;
4445         } while (G_MININT64 - sxx >= tmp);
4446         break;
4447       }
4448       sxx += tmp;
4449 
4450       tmp = newy4 * newy4 - ybar4 * ybar4;
4451       if (G_UNLIKELY (tmp > 0 && syy > 0 && (G_MAXINT64 - syy <= tmp))) {
4452         do {
4453           pshift++;
4454           syy /= 4;
4455           tmp /= 4;
4456         } while (G_MAXINT64 - syy <= tmp);
4457         break;
4458       } else if (G_UNLIKELY (tmp < 0 && syy < 0 && (G_MININT64 - syy >= tmp))) {
4459         do {
4460           pshift++;
4461           syy /= 4;
4462           tmp /= 4;
4463         } while (G_MININT64 - syy >= tmp);
4464         break;
4465       }
4466       syy += tmp;
4467 
4468       tmp = newx4 * newy4 - xbar4 * ybar4;
4469       if (G_UNLIKELY (tmp > 0 && sxy > 0 && (G_MAXINT64 - sxy <= tmp))) {
4470         do {
4471           pshift++;
4472           sxy /= 4;
4473           tmp /= 4;
4474         } while (G_MAXINT64 - sxy <= tmp);
4475         break;
4476       } else if (G_UNLIKELY (tmp < 0 && sxy < 0 && (G_MININT64 - sxy >= tmp))) {
4477         do {
4478           pshift++;
4479           sxy /= 4;
4480           tmp /= 4;
4481         } while (G_MININT64 - sxy >= tmp);
4482         break;
4483       }
4484       sxy += tmp;
4485     }
4486   } while (i < n);
4487 
4488   if (G_UNLIKELY (sxx == 0))
4489     goto invalid;
4490 
4491   *m_num = sxy;
4492   *m_denom = sxx;
4493   *b = (ymin + ybar) - gst_util_uint64_scale_round (xbar, *m_num, *m_denom);
4494   /* Report base starting from the most recent observation */
4495   *xbase = xmax;
4496   *b += gst_util_uint64_scale_round (xmax - xmin, *m_num, *m_denom);
4497 
4498   *r_squared = ((double) sxy * (double) sxy) / ((double) sxx * (double) syy);
4499 
4500 #ifdef DEBUGGING_ENABLED
4501   GST_CAT_DEBUG (GST_CAT_CLOCK, "  m      = %g", ((double) *m_num) / *m_denom);
4502   GST_CAT_DEBUG (GST_CAT_CLOCK, "  b      = %" G_GUINT64_FORMAT, *b);
4503   GST_CAT_DEBUG (GST_CAT_CLOCK, "  xbase  = %" G_GUINT64_FORMAT, *xbase);
4504   GST_CAT_DEBUG (GST_CAT_CLOCK, "  r2     = %g", *r_squared);
4505 #endif
4506 
4507   if (temp == NULL && n > 64)
4508     g_free (newx);
4509 
4510   return TRUE;
4511 
4512 invalid:
4513   {
4514     GST_CAT_DEBUG (GST_CAT_CLOCK, "sxx == 0, regression failed");
4515     if (temp == NULL && n > 64)
4516       g_free (newx);
4517     return FALSE;
4518   }
4519 }
4520 
4521 /**
4522  * gst_type_mark_as_plugin_api:
4523  * @type: a GType
4524  * @flags: a set of #GstPluginAPIFlags to further inform cache generation.
4525  *
4526  * Marks @type as plugin API. This should be called in `class_init` of
4527  * elements that expose new types (i.e. enums, flags or internal GObjects) via
4528  * properties, signals or pad templates.
4529  *
4530  * Types exposed by plugins are not automatically added to the documentation
4531  * as they might originate from another library and should in that case be
4532  * documented via that library instead.
4533  *
4534  * By marking a type as plugin API it will be included in the documentation of
4535  * the plugin that defines it.
4536  *
4537  * Since: 1.18
4538  */
4539 void
gst_type_mark_as_plugin_api(GType type,GstPluginAPIFlags flags)4540 gst_type_mark_as_plugin_api (GType type, GstPluginAPIFlags flags)
4541 {
4542   g_type_set_qdata (type, GST_QUARK (PLUGIN_API), GINT_TO_POINTER (TRUE));
4543   g_type_set_qdata (type, GST_QUARK (PLUGIN_API_FLAGS),
4544       GINT_TO_POINTER (flags));
4545 }
4546 
4547 /**
4548  * gst_type_is_plugin_api:
4549  * @type: a GType
4550  * @flags: (out) (nullable): What #GstPluginAPIFlags the plugin was marked with
4551  *
4552  * Checks if @type is plugin API. See gst_type_mark_as_plugin_api() for
4553  * details.
4554  *
4555  * Returns: %TRUE if @type is plugin API or %FALSE otherwise.
4556  *
4557  * Since: 1.18
4558  */
4559 gboolean
gst_type_is_plugin_api(GType type,GstPluginAPIFlags * flags)4560 gst_type_is_plugin_api (GType type, GstPluginAPIFlags * flags)
4561 {
4562   gboolean ret =
4563       ! !GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API)));
4564 
4565   if (ret && flags) {
4566     *flags =
4567         GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API_FLAGS)));
4568   }
4569 
4570   return ret;
4571 }
4572