tee: Check for the removed pad flag also in the slow pushing path
[platform/upstream/gstreamer.git] / gst / gstutils.c
index 31a23c8..e41399e 100644 (file)
  *
  */
 
+/* FIXME 2.0: suppress warnings for deprecated API such as GValueArray
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
 #include "gst_private.h"
 #include <stdio.h>
 #include <string.h>
@@ -46,7 +50,7 @@
 
 /**
  * gst_util_dump_mem:
- * @mem: a pointer to the memory to dump
+ * @mem: (array length=size): a pointer to the memory to dump
  * @size: the size of the memory block to dump
  *
  * Dumps the memory block into a hex representation. Useful for debugging.
@@ -82,6 +86,24 @@ gst_util_dump_mem (const guchar * mem, guint size)
   g_string_free (chars, TRUE);
 }
 
+/**
+ * gst_util_dump_buffer:
+ * @buf: a #GstBuffer whose memory to dump
+ *
+ * Dumps the buffer memory into a hex representation. Useful for debugging.
+ *
+ * Since: 1.14
+ */
+void
+gst_util_dump_buffer (GstBuffer * buf)
+{
+  GstMapInfo map;
+
+  if (gst_buffer_map (buf, &map, GST_MAP_READ)) {
+    gst_util_dump_mem (map.data, map.size);
+    gst_buffer_unmap (buf, &map);
+  }
+}
 
 /**
  * gst_util_set_value_from_string:
@@ -167,6 +189,75 @@ done:
   g_value_unset (&v);
 }
 
+/**
+ * gst_util_set_object_array:
+ * @object: the object to set the array to
+ * @name: the name of the property to set
+ * @array: a #GValueArray containing the values
+ *
+ * Transfer a #GValueArray to %GST_TYPE_ARRAY and set this value on the
+ * specified property name. This allow language bindings to set GST_TYPE_ARRAY
+ * properties which are otherwise not an accessible type.
+ *
+ * Since: 1.12
+ */
+gboolean
+gst_util_set_object_array (GObject * object, const gchar * name,
+    const GValueArray * array)
+{
+  GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
+  gboolean ret = FALSE;
+
+  g_value_init (&v1, G_TYPE_VALUE_ARRAY);
+  g_value_init (&v2, GST_TYPE_ARRAY);
+
+  g_value_set_static_boxed (&v1, array);
+
+  if (g_value_transform (&v1, &v2)) {
+    g_object_set_property (object, name, &v2);
+    ret = TRUE;
+  }
+
+  g_value_unset (&v1);
+  g_value_unset (&v2);
+
+  return ret;
+}
+
+/**
+ * gst_util_get_object_array:
+ * @object: the object to set the array to
+ * @name: the name of the property to set
+ * @array: (out): a return #GValueArray
+ *
+ * Get a property of type %GST_TYPE_ARRAY and transform it into a
+ * #GValueArray. This allow language bindings to get GST_TYPE_ARRAY
+ * properties which are otherwise not an accessible type.
+ *
+ * Since: 1.12
+ */
+gboolean
+gst_util_get_object_array (GObject * object, const gchar * name,
+    GValueArray ** array)
+{
+  GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
+  gboolean ret = FALSE;
+
+  g_value_init (&v1, G_TYPE_VALUE_ARRAY);
+  g_value_init (&v2, GST_TYPE_ARRAY);
+
+  g_object_get_property (object, name, &v2);
+
+  if (g_value_transform (&v2, &v1)) {
+    *array = g_value_get_boxed (&v1);
+    ret = TRUE;
+  }
+
+  g_value_unset (&v2);
+
+  return ret;
+}
+
 /* work around error C2520: conversion from unsigned __int64 to double
  * not implemented, use signed __int64
  *
@@ -697,15 +788,23 @@ gst_util_uint64_scale_int_ceil (guint64 val, gint num, gint denom)
  * on a segment-done message to be the same as that of the last seek event, to
  * indicate that event and the message correspond to the same segment.
  *
+ * This function never returns %GST_SEQNUM_INVALID (which is 0).
+ *
  * Returns: A constantly incrementing 32-bit unsigned integer, which might
- * overflow back to 0 at some point. Use gst_util_seqnum_compare() to make sure
+ * overflow at some point. Use gst_util_seqnum_compare() to make sure
  * you handle wraparound correctly.
  */
 guint32
 gst_util_seqnum_next (void)
 {
-  static gint counter = 0;
-  return g_atomic_int_add (&counter, 1);
+  static gint counter = 1;
+  gint ret = g_atomic_int_add (&counter, 1);
+
+  /* Make sure we don't return 0 */
+  if (G_UNLIKELY (ret == GST_SEQNUM_INVALID))
+    ret = g_atomic_int_add (&counter, 1);
+
+  return ret;
 }
 
 /**
@@ -1184,6 +1283,46 @@ gst_element_state_change_return_get_name (GstStateChangeReturn state_ret)
   }
 }
 
+/**
+ * gst_state_change_get_name:
+ * @transition: a #GstStateChange to get the name of.
+ *
+ * Gets a string representing the given state transition.
+ *
+ * Returns: (transfer none): a string with the name of the state
+ *    result.
+ *
+ * Since: 1.14
+ */
+const gchar *
+gst_state_change_get_name (GstStateChange transition)
+{
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      return "NULL->READY";
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      return "READY->PAUSED";
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      return "PAUSED->PLAYING";
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      return "PLAYING->PAUSED";
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      return "PAUSED->READY";
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      return "READY->NULL";
+    case GST_STATE_CHANGE_NULL_TO_NULL:
+      return "NULL->NULL";
+    case GST_STATE_CHANGE_READY_TO_READY:
+      return "READY->READY";
+    case GST_STATE_CHANGE_PAUSED_TO_PAUSED:
+      return "PAUSED->PAUSED";
+    case GST_STATE_CHANGE_PLAYING_TO_PLAYING:
+      return "PLAYING->PLAYING";
+  }
+
+  return "Unknown state return";
+}
+
 
 static gboolean
 gst_element_factory_can_accept_all_caps_in_direction (GstElementFactory *
@@ -1402,7 +1541,6 @@ ghost_up (GstElement * e, GstPad * pad)
   if (!gst_element_add_pad ((GstElement *) parent, gpad)) {
     g_warning ("Pad named %s already exists in element %s\n",
         GST_OBJECT_NAME (gpad), GST_OBJECT_NAME (parent));
-    gst_object_unref ((GstObject *) gpad);
     GST_STATE_UNLOCK (parent);
     return NULL;
   }
@@ -1846,7 +1984,7 @@ gst_element_link_pads_full (GstElement * src, const gchar * srcpadname,
     return FALSE;
   } else {
     /* no need to release any request pad as the case of unset destpatname and
-     * destpad being a requst pad has already been taken care of when looking
+     * destpad being a request pad has already been taken care of when looking
      * though the destination pads above */
     if (destpad) {
       gst_object_unref (destpad);
@@ -1986,7 +2124,6 @@ gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname,
 
     if (!gst_bin_add (GST_BIN (parent), capsfilter)) {
       GST_ERROR ("Could not add capsfilter");
-      gst_object_unref (capsfilter);
       gst_object_unref (parent);
       return FALSE;
     }
@@ -2291,6 +2428,9 @@ gst_element_query_position (GstElement * element, GstFormat format,
   GstQuery *query;
   gboolean ret;
 
+  if (cur != NULL)
+    *cur = GST_CLOCK_TIME_NONE;
+
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
@@ -2329,6 +2469,9 @@ gst_element_query_duration (GstElement * element, GstFormat format,
   GstQuery *query;
   gboolean ret;
 
+  if (duration != NULL)
+    *duration = GST_CLOCK_TIME_NONE;
+
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
@@ -2476,7 +2619,7 @@ gst_pad_get_parent_element (GstPad * pad)
  * @debug: (in) (allow-none): an additional debug information string, or %NULL
  *
  * A default error function that uses g_printerr() to display the error message
- * and the optional debug sting..
+ * and the optional debug string..
  *
  * The default handler will simply print the error string using g_print.
  */
@@ -2494,10 +2637,10 @@ gst_object_default_error (GstObject * source, const GError * error,
 }
 
 /**
- * gst_bin_add_many:
+ * gst_bin_add_many: (skip)
  * @bin: a #GstBin
- * @element_1: (transfer full): the #GstElement element to add to the bin
- * @...: (transfer full): additional elements to add to the bin
+ * @element_1: (transfer floating): the #GstElement element to add to the bin
+ * @...: additional elements to add to the bin
  *
  * Adds a %NULL-terminated list of elements to a bin.  This function is
  * equivalent to calling gst_bin_add() for each member of the list. The return
@@ -2523,7 +2666,7 @@ gst_bin_add_many (GstBin * bin, GstElement * element_1, ...)
 }
 
 /**
- * gst_bin_remove_many:
+ * gst_bin_remove_many: (skip)
  * @bin: a #GstBin
  * @element_1: (transfer none): the first #GstElement to remove from the bin
  * @...: (transfer none): %NULL-terminated list of elements to remove from the bin
@@ -2699,6 +2842,9 @@ gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur)
   GstQuery *query;
   gboolean ret;
 
+  if (cur != NULL)
+    *cur = GST_CLOCK_TIME_NONE;
+
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
@@ -2728,6 +2874,9 @@ gst_pad_peer_query_position (GstPad * pad, GstFormat format, gint64 * cur)
   GstQuery *query;
   gboolean ret = FALSE;
 
+  if (cur != NULL)
+    *cur = GST_CLOCK_TIME_NONE;
+
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
@@ -2756,6 +2905,9 @@ gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
   GstQuery *query;
   gboolean ret;
 
+  if (duration != NULL)
+    *duration = GST_CLOCK_TIME_NONE;
+
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
@@ -2785,6 +2937,9 @@ gst_pad_peer_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
   GstQuery *query;
   gboolean ret = FALSE;
 
+  if (duration != NULL)
+    *duration = GST_CLOCK_TIME_NONE;
+
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
   g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
@@ -3238,7 +3393,7 @@ gst_parse_bin_from_description (const gchar * bin_description,
  * and want them all ghosted, you will have to create the ghost pads
  * yourself).
  *
- * Returns: (transfer floating) (type Gst.Element): a newly-created
+ * Returns: (transfer floating) (type Gst.Element) (nullable): a newly-created
  *   element, which is guaranteed to be a bin unless
  *   GST_FLAG_NO_SINGLE_ELEMENT_BINS was passed, or %NULL if an error
  *   occurred.
@@ -3324,10 +3479,7 @@ gst_util_get_timestamp (void)
   clock_gettime (CLOCK_MONOTONIC, &now);
   return GST_TIMESPEC_TO_TIME (now);
 #else
-  GTimeVal now;
-
-  g_get_current_time (&now);
-  return GST_TIMEVAL_TO_TIME (now);
+  return g_get_monotonic_time () * 1000;
 #endif
 }
 
@@ -4040,14 +4192,22 @@ gst_pad_get_stream (GstPad * pad)
  * This function is used to generate a new group-id for the
  * stream-start event.
  *
+ * This function never returns %GST_GROUP_ID_INVALID (which is 0)
+ *
  * Returns: A constantly incrementing unsigned integer, which might
  * overflow back to 0 at some point.
  */
 guint
 gst_util_group_id_next (void)
 {
-  static gint counter = 0;
-  return g_atomic_int_add (&counter, 1);
+  static gint counter = 1;
+  gint ret = g_atomic_int_add (&counter, 1);
+
+  /* Make sure we don't return GST_GROUP_ID_INVALID */
+  if (G_UNLIKELY (ret == GST_GROUP_ID_INVALID))
+    ret = g_atomic_int_add (&counter, 1);
+
+  return ret;
 }
 
 /* Compute log2 of the passed 64-bit number by finding the highest set bit */
@@ -4071,7 +4231,7 @@ gst_log2 (GstClockTime in)
 }
 
 /**
- * gst_calculate_linear_regression:
+ * gst_calculate_linear_regression: (skip)
  * @xy: Pairs of (x,y) values
  * @temp: Temporary scratch space used by the function
  * @n: number of (x,y) pairs
@@ -4179,6 +4339,8 @@ gst_calculate_linear_regression (const GstClockTime * xy,
           G_GUINT64_FORMAT " newx[j] %" G_GUINT64_FORMAT " ybar %"
           G_GUINT64_FORMAT " newy[j] %" G_GUINT64_FORMAT, xbar, newx[j], ybar,
           newy[j]);
+      if (temp == NULL && n > 64)
+        g_free (newx);
       return FALSE;
     }
 
@@ -4229,7 +4391,7 @@ gst_calculate_linear_regression (const GstClockTime * xy,
           tmp /= 4;
         } while (G_MAXINT64 - sxx <= tmp);
         break;
-      } else if (G_UNLIKELY (tmp < 0 && sxx < 0 && (G_MAXINT64 - sxx >= tmp))) {
+      } else if (G_UNLIKELY (tmp < 0 && sxx < 0 && (G_MININT64 - sxx >= tmp))) {
         do {
           /* Drop some precision and restart */
           pshift++;
@@ -4248,7 +4410,7 @@ gst_calculate_linear_regression (const GstClockTime * xy,
           tmp /= 4;
         } while (G_MAXINT64 - syy <= tmp);
         break;
-      } else if (G_UNLIKELY (tmp < 0 && syy < 0 && (G_MAXINT64 - syy >= tmp))) {
+      } else if (G_UNLIKELY (tmp < 0 && syy < 0 && (G_MININT64 - syy >= tmp))) {
         do {
           pshift++;
           syy /= 4;