/**
* SECTION:gstutils
+ * @title: GstUtils
* @short_description: Various utility functions
*
*/
+/* 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>
/**
* 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.
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:
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
*
* 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;
}
/**
}
}
+/**
+ * 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 *
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;
}
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);
if (!gst_bin_add (GST_BIN (parent), capsfilter)) {
GST_ERROR ("Could not add capsfilter");
- gst_object_unref (capsfilter);
gst_object_unref (parent);
return FALSE;
}
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);
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);
* @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.
*/
}
/**
- * 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
}
/**
- * 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
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);
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);
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);
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);
* 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.
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
}
* 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 */
}
/**
- * 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
* %NULL, an allocation will take place. @temp should have at least the same
* amount of memory allocated as @xy, i.e. 2*n*sizeof(GstClockTime).
*
- * <note>This function assumes (x,y) values with reasonable large differences
- * between them. It will not calculate the exact results if the differences
- * between neighbouring values are too small due to not being able to
- * represent sub-integer values during the calculations.</note>
+ * > This function assumes (x,y) values with reasonable large differences
+ * > between them. It will not calculate the exact results if the differences
+ * > between neighbouring values are too small due to not being able to
+ * > represent sub-integer values during the calculations.
*
* Returns: %TRUE if the linear regression was successfully calculated
*
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;
}
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++;
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;