From 39533f4364b7f3fd8b54f87039acebc705d68c3a Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 30 Nov 2011 14:45:12 +0000 Subject: [PATCH] gstvalue: add stepped ranges int and int64 ranges can now have an optional step (defaulting to 1). Members of the range are those values within the min and max bounds which are a multiple of this step. https://bugzilla.gnome.org/show_bug.cgi?id=665294 --- gst/gststructure.c | 73 +++-- gst/gstvalue.c | 726 +++++++++++++++++++++++++++++++++++------- gst/gstvalue.h | 13 + win32/common/libgstreamer.def | 6 + 4 files changed, 673 insertions(+), 145 deletions(-) diff --git a/gst/gststructure.c b/gst/gststructure.c index a484c0d..5310092 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -1900,8 +1900,9 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value, { GValue value1 = { 0 }; GValue value2 = { 0 }; + GValue value3 = { 0 }; GType range_type; - gboolean ret; + gboolean ret, have_step = FALSE; if (*s != '[') return FALSE; @@ -1928,12 +1929,34 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value, while (g_ascii_isspace (*s)) s++; + /* optional step for int and int64 */ + if (G_VALUE_TYPE (&value1) == G_TYPE_INT + || G_VALUE_TYPE (&value1) == G_TYPE_INT64) { + if (*s == ',') { + s++; + + while (g_ascii_isspace (*s)) + s++; + + ret = gst_structure_parse_value (s, &s, &value3, type); + if (ret == FALSE) + return FALSE; + + while (g_ascii_isspace (*s)) + s++; + + have_step = TRUE; + } + } + if (*s != ']') return FALSE; s++; if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2)) return FALSE; + if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3)) + return FALSE; if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) { range_type = GST_TYPE_DOUBLE_RANGE; @@ -1944,13 +1967,26 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value, } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) { range_type = GST_TYPE_INT_RANGE; g_value_init (value, range_type); - gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1), - gst_g_value_get_int_unchecked (&value2)); + if (have_step) + gst_value_set_int_range_step (value, + gst_g_value_get_int_unchecked (&value1), + gst_g_value_get_int_unchecked (&value2), + gst_g_value_get_int_unchecked (&value3)); + else + gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1), + gst_g_value_get_int_unchecked (&value2)); } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) { range_type = GST_TYPE_INT64_RANGE; g_value_init (value, range_type); - gst_value_set_int64_range (value, gst_g_value_get_int64_unchecked (&value1), - gst_g_value_get_int64_unchecked (&value2)); + if (have_step) + gst_value_set_int64_range_step (value, + gst_g_value_get_int64_unchecked (&value1), + gst_g_value_get_int64_unchecked (&value2), + gst_g_value_get_int64_unchecked (&value3)); + else + gst_value_set_int64_range (value, + gst_g_value_get_int64_unchecked (&value1), + gst_g_value_get_int64_unchecked (&value2)); } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) { range_type = GST_TYPE_FRACTION_RANGE; g_value_init (value, range_type); @@ -3132,32 +3168,7 @@ gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value, if (comparison != GST_VALUE_UNORDERED) return FALSE; - /* - * 1 - [1,2] = empty - * -> !subset - * - * [1,2] - 1 = 2 - * -> 1 - [1,2] = empty - * -> subset - * - * [1,3] - [1,2] = 3 - * -> [1,2] - [1,3] = empty - * -> subset - * - * {1,2} - {1,3} = 2 - * -> {1,3} - {1,2} = 3 - * -> !subset - * - * First caps subtraction needs to return a non-empty set, second - * subtractions needs to give en empty set. - * Both substractions are switched below, as it's faster that way. - */ - if (!gst_value_subtract (NULL, value, other)) { - if (gst_value_subtract (NULL, other, value)) { - return TRUE; - } - } - return FALSE; + return gst_value_is_subset (value, other); } /** diff --git a/gst/gstvalue.c b/gst/gstvalue.c index ef99e92..75a5362 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -778,26 +778,56 @@ gst_value_deserialize_array (GValue * dest, const gchar * s) /************* * int range * + * + * Values in the range are defined as any value greater or equal + * to min*step, AND lesser or equal to max*step. + * For step == 1, this falls back to the traditional range semantics. *************/ +#define INT_RANGE_MIN(v) (((gint *)((v)->data[0].v_pointer))[0]) +#define INT_RANGE_MAX(v) (((gint *)((v)->data[0].v_pointer))[1]) +#define INT_RANGE_STEP(v) (((gint *)((v)->data[0].v_pointer))[2]) + static void gst_value_init_int_range (GValue * value) { - value->data[0].v_int = 0; - value->data[1].v_int = 0; + gint *vals = g_slice_alloc0 (3 * sizeof (gint)); + value->data[0].v_pointer = vals; + INT_RANGE_MIN (value) = 0; + INT_RANGE_MAX (value) = 0; + INT_RANGE_STEP (value) = 1; +} + +static void +gst_value_free_int_range (GValue * value) +{ + g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value)); + g_slice_free1 (3 * sizeof (gint), value->data[0].v_pointer); + value->data[0].v_pointer = NULL; } static void gst_value_copy_int_range (const GValue * src_value, GValue * dest_value) { - dest_value->data[0].v_int = src_value->data[0].v_int; - dest_value->data[1].v_int = src_value->data[1].v_int; + gint *vals = (gint *) dest_value->data[0].v_pointer; + gint *src_vals = (gint *) src_value->data[0].v_pointer; + + if (vals == NULL) { + gst_value_init_int_range (dest_value); + } + if (src_vals != NULL) { + INT_RANGE_MIN (dest_value) = INT_RANGE_MIN (src_value); + INT_RANGE_MAX (dest_value) = INT_RANGE_MAX (src_value); + INT_RANGE_STEP (dest_value) = INT_RANGE_STEP (src_value); + } } static gchar * gst_value_collect_int_range (GValue * value, guint n_collect_values, GTypeCValue * collect_values, guint collect_flags) { + gint *vals = value->data[0].v_pointer; + if (n_collect_values != 2) return g_strdup_printf ("not enough value locations for `%s' passed", G_VALUE_TYPE_NAME (value)); @@ -805,8 +835,12 @@ gst_value_collect_int_range (GValue * value, guint n_collect_values, return g_strdup_printf ("range start is not smaller than end for `%s'", G_VALUE_TYPE_NAME (value)); - value->data[0].v_int = collect_values[0].v_int; - value->data[1].v_int = collect_values[1].v_int; + if (vals == NULL) { + gst_value_init_int_range (value); + } + + gst_value_set_int_range_step (value, collect_values[0].v_int, + collect_values[1].v_int, 1); return NULL; } @@ -817,6 +851,8 @@ gst_value_lcopy_int_range (const GValue * value, guint n_collect_values, { guint32 *int_range_start = collect_values[0].v_pointer; guint32 *int_range_end = collect_values[1].v_pointer; + guint32 *int_range_step = collect_values[2].v_pointer; + gint *vals = (gint *) value->data[0].v_pointer; if (!int_range_start) return g_strdup_printf ("start value location for `%s' passed as NULL", @@ -824,29 +860,57 @@ gst_value_lcopy_int_range (const GValue * value, guint n_collect_values, if (!int_range_end) return g_strdup_printf ("end value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + if (!int_range_step) + return g_strdup_printf ("step value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + if (G_UNLIKELY (vals == NULL)) { + return g_strdup_printf ("Uninitialised `%s' passed", + G_VALUE_TYPE_NAME (value)); + } - *int_range_start = value->data[0].v_int; - *int_range_end = value->data[1].v_int; + *int_range_start = INT_RANGE_MIN (value); + *int_range_end = INT_RANGE_MAX (value); + *int_range_step = INT_RANGE_STEP (value); return NULL; } /** - * gst_value_set_int_range: + * gst_value_set_int_range_step: * @value: a GValue initialized to GST_TYPE_INT_RANGE * @start: the start of the range * @end: the end of the range + * @step: the step of the range * - * Sets @value to the range specified by @start and @end. + * Sets @value to the range specified by @start, @end and @step. */ void -gst_value_set_int_range (GValue * value, gint start, gint end) +gst_value_set_int_range_step (GValue * value, gint start, gint end, gint step) { g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value)); g_return_if_fail (start < end); + g_return_if_fail (step > 0); + g_return_if_fail (start % step == 0); + g_return_if_fail (end % step == 0); + + INT_RANGE_MIN (value) = start / step; + INT_RANGE_MAX (value) = end / step; + INT_RANGE_STEP (value) = step; +} - value->data[0].v_int = start; - value->data[1].v_int = end; +/** + * gst_value_set_int_range: + * @value: a GValue initialized to GST_TYPE_INT_RANGE + * @start: the start of the range + * @end: the end of the range + * + * Sets @value to the range specified by @start and @end. + */ +void +gst_value_set_int_range (GValue * value, gint start, gint end) +{ + gst_value_set_int_range_step (value, start, end, 1); } /** @@ -862,7 +926,7 @@ gst_value_get_int_range_min (const GValue * value) { g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); - return value->data[0].v_int; + return INT_RANGE_MIN (value) * INT_RANGE_STEP (value); } /** @@ -878,31 +942,81 @@ gst_value_get_int_range_max (const GValue * value) { g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); - return value->data[1].v_int; + return INT_RANGE_MAX (value) * INT_RANGE_STEP (value); +} + +/** + * gst_value_get_int_range_step: + * @value: a GValue initialized to GST_TYPE_INT_RANGE + * + * Gets the step of the range specified by @value. + * + * Returns: the step of the range + */ +gint +gst_value_get_int_range_step (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); + + return INT_RANGE_STEP (value); } static void gst_value_transform_int_range_string (const GValue * src_value, GValue * dest_value) { - dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]", - (int) src_value->data[0].v_int, (int) src_value->data[1].v_int); + if (INT_RANGE_STEP (src_value) == 1) + dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]", + INT_RANGE_MIN (src_value), INT_RANGE_MAX (src_value)); + else + dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d,%d]", + INT_RANGE_MIN (src_value) * INT_RANGE_STEP (src_value), + INT_RANGE_MAX (src_value) * INT_RANGE_STEP (src_value), + INT_RANGE_STEP (src_value)); } static gint gst_value_compare_int_range (const GValue * value1, const GValue * value2) { - if (value2->data[0].v_int == value1->data[0].v_int && - value2->data[1].v_int == value1->data[1].v_int) + /* calculate the number of values in each range */ + gint n1 = INT_RANGE_MAX (value1) - INT_RANGE_MIN (value1) + 1; + gint n2 = INT_RANGE_MAX (value2) - INT_RANGE_MIN (value2) + 1; + + /* they must be equal */ + if (n1 != n2) + return GST_VALUE_UNORDERED; + + /* if empty, equal */ + if (n1 == 0) return GST_VALUE_EQUAL; - return GST_VALUE_UNORDERED; + + /* if more than one value, then it is only equal if the step is equal + and bounds lie on the same value */ + if (n1 > 1) { + if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) && + INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) && + INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2)) { + return GST_VALUE_EQUAL; + } + return GST_VALUE_UNORDERED; + } else { + /* if just one, only if the value is equal */ + if (INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2)) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; + } } static gchar * gst_value_serialize_int_range (const GValue * value) { - return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int, - value->data[1].v_int); + if (INT_RANGE_STEP (value) == 1) + return g_strdup_printf ("[ %d, %d ]", INT_RANGE_MIN (value), + INT_RANGE_MAX (value)); + else + return g_strdup_printf ("[ %d, %d, %d ]", + INT_RANGE_MIN (value) * INT_RANGE_STEP (value), + INT_RANGE_MAX (value) * INT_RANGE_STEP (value), INT_RANGE_STEP (value)); } static gboolean @@ -914,26 +1028,57 @@ gst_value_deserialize_int_range (GValue * dest, const gchar * s) /*************** * int64 range * + * + * Values in the range are defined as any value greater or equal + * to min*step, AND lesser or equal to max*step. + * For step == 1, this falls back to the traditional range semantics. ***************/ +#define INT64_RANGE_MIN(v) (((gint64 *)((v)->data[0].v_pointer))[0]) +#define INT64_RANGE_MAX(v) (((gint64 *)((v)->data[0].v_pointer))[1]) +#define INT64_RANGE_STEP(v) (((gint64 *)((v)->data[0].v_pointer))[2]) + static void gst_value_init_int64_range (GValue * value) { - value->data[0].v_int64 = 0; - value->data[1].v_int64 = 0; + gint64 *vals = g_slice_alloc0 (3 * sizeof (gint64)); + value->data[0].v_pointer = vals; + INT64_RANGE_MIN (value) = 0; + INT64_RANGE_MAX (value) = 0; + INT64_RANGE_STEP (value) = 1; +} + +static void +gst_value_free_int64_range (GValue * value) +{ + g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value)); + g_slice_free1 (3 * sizeof (gint64), value->data[0].v_pointer); + value->data[0].v_pointer = NULL; } static void gst_value_copy_int64_range (const GValue * src_value, GValue * dest_value) { - dest_value->data[0].v_int64 = src_value->data[0].v_int64; - dest_value->data[1].v_int64 = src_value->data[1].v_int64; + gint64 *vals = (gint64 *) dest_value->data[0].v_pointer; + gint64 *src_vals = (gint64 *) src_value->data[0].v_pointer; + + if (vals == NULL) { + gst_value_init_int64_range (dest_value); + vals = (gint64 *) dest_value->data[0].v_pointer; + } + if (src_vals != NULL) { + INT64_RANGE_MIN (dest_value) = INT64_RANGE_MIN (src_value); + INT64_RANGE_MAX (dest_value) = INT64_RANGE_MAX (src_value); + INT64_RANGE_STEP (dest_value) = INT64_RANGE_STEP (src_value); + } } static gchar * gst_value_collect_int64_range (GValue * value, guint n_collect_values, GTypeCValue * collect_values, guint collect_flags) { + gint64 *vals = value->data[0].v_pointer; + if (n_collect_values != 2) return g_strdup_printf ("not enough value locations for `%s' passed", G_VALUE_TYPE_NAME (value)); @@ -941,8 +1086,12 @@ gst_value_collect_int64_range (GValue * value, guint n_collect_values, return g_strdup_printf ("range start is not smaller than end for `%s'", G_VALUE_TYPE_NAME (value)); - value->data[0].v_int64 = collect_values[0].v_int64; - value->data[1].v_int64 = collect_values[1].v_int64; + if (vals == NULL) { + gst_value_init_int64_range (value); + } + + gst_value_set_int64_range_step (value, collect_values[0].v_int64, + collect_values[1].v_int64, 1); return NULL; } @@ -953,6 +1102,8 @@ gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values, { guint64 *int_range_start = collect_values[0].v_pointer; guint64 *int_range_end = collect_values[1].v_pointer; + guint64 *int_range_step = collect_values[2].v_pointer; + gint64 *vals = (gint64 *) value->data[0].v_pointer; if (!int_range_start) return g_strdup_printf ("start value location for `%s' passed as NULL", @@ -960,14 +1111,49 @@ gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values, if (!int_range_end) return g_strdup_printf ("end value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + if (!int_range_step) + return g_strdup_printf ("step value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); - *int_range_start = value->data[0].v_int64; - *int_range_end = value->data[1].v_int64; + if (G_UNLIKELY (vals == NULL)) { + return g_strdup_printf ("Uninitialised `%s' passed", + G_VALUE_TYPE_NAME (value)); + } + + *int_range_start = INT64_RANGE_MIN (value); + *int_range_end = INT64_RANGE_MAX (value); + *int_range_step = INT64_RANGE_STEP (value); return NULL; } /** + * gst_value_set_int64_range_step: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * @start: the start of the range + * @end: the end of the range + * @step: the step of the range + * + * Sets @value to the range specified by @start, @end and @step. + * + * Since: 0.11.0 + */ +void +gst_value_set_int64_range_step (GValue * value, gint64 start, gint64 end, + gint64 step) +{ + g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value)); + g_return_if_fail (start < end); + g_return_if_fail (step > 0); + g_return_if_fail (start % step == 0); + g_return_if_fail (end % step == 0); + + INT64_RANGE_MIN (value) = start / step; + INT64_RANGE_MAX (value) = end / step; + INT64_RANGE_STEP (value) = step; +} + +/** * gst_value_set_int64_range: * @value: a GValue initialized to GST_TYPE_INT64_RANGE * @start: the start of the range @@ -980,11 +1166,7 @@ gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values, void gst_value_set_int64_range (GValue * value, gint64 start, gint64 end) { - g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value)); - g_return_if_fail (start < end); - - value->data[0].v_int64 = start; - value->data[1].v_int64 = end; + gst_value_set_int64_range_step (value, start, end, 1); } /** @@ -1002,7 +1184,7 @@ gst_value_get_int64_range_min (const GValue * value) { g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0); - return value->data[0].v_int64; + return INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value); } /** @@ -1020,32 +1202,88 @@ gst_value_get_int64_range_max (const GValue * value) { g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0); - return value->data[1].v_int64; + return INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value); +} + +/** + * gst_value_get_int64_range_step: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * + * Gets the step of the range specified by @value. + * + * Returns: the step of the range + * + * Since: 0.11.0 + */ +gint64 +gst_value_get_int64_range_step (const GValue * value) +{ + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0); + + return INT64_RANGE_STEP (value); } static void gst_value_transform_int64_range_string (const GValue * src_value, GValue * dest_value) { - dest_value->data[0].v_pointer = - g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]", - src_value->data[0].v_int64, src_value->data[1].v_int64); + if (INT64_RANGE_STEP (src_value) == 1) + dest_value->data[0].v_pointer = + g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]", + INT64_RANGE_MIN (src_value), INT64_RANGE_MAX (src_value)); + else + dest_value->data[0].v_pointer = + g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT + ",%" G_GINT64_FORMAT "]", + INT64_RANGE_MIN (src_value) * INT64_RANGE_STEP (src_value), + INT64_RANGE_MAX (src_value) * INT64_RANGE_STEP (src_value), + INT64_RANGE_STEP (src_value)); } static gint gst_value_compare_int64_range (const GValue * value1, const GValue * value2) { - if (value2->data[0].v_int64 == value1->data[0].v_int64 && - value2->data[1].v_int64 == value1->data[1].v_int64) + /* calculate the number of values in each range */ + gint64 n1 = INT64_RANGE_MAX (value1) - INT64_RANGE_MIN (value1) + 1; + gint64 n2 = INT64_RANGE_MAX (value2) - INT64_RANGE_MIN (value2) + 1; + + /* they must be equal */ + if (n1 != n2) + return GST_VALUE_UNORDERED; + + /* if empty, equal */ + if (n1 == 0) return GST_VALUE_EQUAL; - return GST_VALUE_UNORDERED; + + /* if more than one value, then it is only equal if the step is equal + and bounds lie on the same value */ + if (n1 > 1) { + if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) && + INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) && + INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2)) { + return GST_VALUE_EQUAL; + } + return GST_VALUE_UNORDERED; + } else { + /* if just one, only if the value is equal */ + if (INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2)) + return GST_VALUE_EQUAL; + return GST_VALUE_UNORDERED; + } } static gchar * gst_value_serialize_int64_range (const GValue * value) { - return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]", - value->data[0].v_int64, value->data[1].v_int64); + if (INT64_RANGE_STEP (value) == 1) + return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]", + INT64_RANGE_MIN (value), INT64_RANGE_MAX (value)); + else + return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ", %" + G_GINT64_FORMAT " ]", + INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value), + INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value), + INT64_RANGE_STEP (value)); } static gboolean @@ -2491,6 +2729,114 @@ gst_value_deserialize_flags (GValue * dest, const gchar * s) return TRUE; } +/**************** + * subset * + ****************/ + +static gboolean +gst_value_is_subset_int_range_int_range (const GValue * value1, + const GValue * value2) +{ + gint gcd; + + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value2), FALSE); + + if (INT_RANGE_MIN (value1) * INT_RANGE_STEP (value1) < + INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) + return FALSE; + if (INT_RANGE_MAX (value1) * INT_RANGE_STEP (value1) > + INT_RANGE_MAX (value2) * INT_RANGE_STEP (value2)) + return FALSE; + + if (INT_RANGE_MIN (value2) == INT_RANGE_MAX (value2)) { + if ((INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) % + INT_RANGE_STEP (value1)) + return FALSE; + return TRUE; + } + + gcd = + gst_util_greatest_common_divisor (INT_RANGE_STEP (value1), + INT_RANGE_STEP (value2)); + if (gcd != MIN (INT_RANGE_STEP (value1), INT_RANGE_STEP (value2))) + return FALSE; + + return TRUE; +} + +static gboolean +gst_value_is_subset_int64_range_int64_range (const GValue * value1, + const GValue * value2) +{ + gint64 gcd; + + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value1), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value2), FALSE); + + if (INT64_RANGE_MIN (value1) < INT64_RANGE_MIN (value2)) + return FALSE; + if (INT64_RANGE_MAX (value1) > INT64_RANGE_MAX (value2)) + return FALSE; + + if (INT64_RANGE_MIN (value2) == INT64_RANGE_MAX (value2)) { + if ((INT64_RANGE_MIN (value2) * INT64_RANGE_STEP (value2)) % + INT64_RANGE_STEP (value1)) + return FALSE; + return TRUE; + } + + gcd = + gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (value1), + INT64_RANGE_STEP (value2)); + if (gcd != MIN (INT64_RANGE_STEP (value1), INT64_RANGE_STEP (value2))) + return FALSE; + + return TRUE; +} + +gboolean +gst_value_is_subset (const GValue * value1, const GValue * value2) +{ + /* special case for int/int64 ranges, since we cannot compute + the difference for those when they have different steps, + and it's actually a lot simpler to compute whether a range + is a subset of another. */ + if (GST_VALUE_HOLDS_INT_RANGE (value1) && GST_VALUE_HOLDS_INT_RANGE (value2)) { + return gst_value_is_subset_int_range_int_range (value1, value2); + } else if (GST_VALUE_HOLDS_INT64_RANGE (value1) + && GST_VALUE_HOLDS_INT64_RANGE (value2)) { + return gst_value_is_subset_int64_range_int64_range (value1, value2); + } + + /* + * 1 - [1,2] = empty + * -> !subset + * + * [1,2] - 1 = 2 + * -> 1 - [1,2] = empty + * -> subset + * + * [1,3] - [1,2] = 3 + * -> [1,2] - [1,3] = empty + * -> subset + * + * {1,2} - {1,3} = 2 + * -> {1,3} - {1,2} = 3 + * -> !subset + * + * First caps subtraction needs to return a non-empty set, second + * subtractions needs to give en empty set. + * Both substractions are switched below, as it's faster that way. + */ + if (!gst_value_subtract (NULL, value1, value2)) { + if (gst_value_subtract (NULL, value2, value1)) { + return TRUE; + } + } + return FALSE; +} + /********* * union * *********/ @@ -2499,11 +2845,33 @@ static gboolean gst_value_union_int_int_range (GValue * dest, const GValue * src1, const GValue * src2) { - if (src2->data[0].v_int <= src1->data[0].v_int && - src2->data[1].v_int >= src1->data[0].v_int) { - gst_value_init_and_copy (dest, src2); + gint v = src1->data[0].v_int; + + /* check if it's already in the range */ + if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= v && + INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= v && + v % INT_RANGE_STEP (src2) == 0) { + if (dest) + gst_value_init_and_copy (dest, src2); return TRUE; } + + /* check if it extends the range */ + if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) { + if (dest) { + gst_value_init_and_copy (dest, src2); + --INT_RANGE_MIN (src2); + } + return TRUE; + } + if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) { + if (dest) { + gst_value_init_and_copy (dest, src2); + ++INT_RANGE_MAX (src2); + } + return TRUE; + } + return FALSE; } @@ -2511,20 +2879,77 @@ static gboolean gst_value_union_int_range_int_range (GValue * dest, const GValue * src1, const GValue * src2) { - gint min; - gint max; + /* We can union in several special cases: + 1 - one is a subset of another + 2 - same step and not disjoint + 3 - different step, at least one with one value which matches a 'next' or 'previous' + - anything else ? + */ - min = MAX (src1->data[0].v_int, src2->data[0].v_int); - max = MIN (src1->data[1].v_int, src2->data[1].v_int); - - if (min <= max) { - g_value_init (dest, GST_TYPE_INT_RANGE); - gst_value_set_int_range (dest, - MIN (src1->data[0].v_int, src2->data[0].v_int), - MAX (src1->data[1].v_int, src2->data[1].v_int)); + /* 1 - subset */ + if (gst_value_is_subset_int_range_int_range (src1, src2)) { + if (dest) + gst_value_init_and_copy (dest, src2); + return TRUE; + } + if (gst_value_is_subset_int_range_int_range (src2, src1)) { + if (dest) + gst_value_init_and_copy (dest, src1); return TRUE; } + /* 2 - same step and not disjoint */ + if (INT_RANGE_STEP (src1) == INT_RANGE_STEP (src2)) { + if ((INT_RANGE_MIN (src1) <= INT_RANGE_MAX (src2) + 1 && + INT_RANGE_MAX (src1) >= INT_RANGE_MIN (src2) - 1) || + (INT_RANGE_MIN (src2) <= INT_RANGE_MAX (src1) + 1 && + INT_RANGE_MAX (src2) >= INT_RANGE_MIN (src1) - 1)) { + if (dest) { + gint step = INT_RANGE_STEP (src1); + gint min = step * MIN (INT_RANGE_MIN (src1), INT_RANGE_MIN (src2)); + gint max = step * MAX (INT_RANGE_MAX (src1), INT_RANGE_MAX (src2)); + g_value_init (dest, GST_TYPE_INT_RANGE); + gst_value_set_int_range_step (dest, min, max, step); + } + return TRUE; + } + } + + /* 3 - single value matches next or previous */ + if (INT_RANGE_STEP (src1) != INT_RANGE_STEP (src2)) { + gint n1 = INT_RANGE_MAX (src1) - INT_RANGE_MIN (src1) + 1; + gint n2 = INT_RANGE_MAX (src2) - INT_RANGE_MIN (src2) + 1; + if (n1 == 1 || n2 == 1) { + const GValue *range_value = NULL; + gint scalar = 0; + if (n1 == 1) { + range_value = src2; + scalar = INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1); + } else if (n2 == 1) { + range_value = src1; + scalar = INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2); + } + + if (scalar == + (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) { + if (dest) { + gst_value_init_and_copy (dest, range_value); + --INT_RANGE_MIN (range_value); + } + return TRUE; + } else if (scalar == + (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) { + if (dest) { + gst_value_init_and_copy (dest, range_value); + ++INT_RANGE_MIN (range_value); + } + return TRUE; + } + } + } + + /* If we get there, we did not find a way to make a union that can be + represented with our simplistic model. */ return FALSE; } @@ -2536,8 +2961,9 @@ static gboolean gst_value_intersect_int_int_range (GValue * dest, const GValue * src1, const GValue * src2) { - if (src2->data[0].v_int <= src1->data[0].v_int && - src2->data[1].v_int >= src1->data[0].v_int) { + if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= src1->data[0].v_int && + INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= src1->data[0].v_int && + src1->data[0].v_int % INT_RANGE_STEP (src2) == 0) { if (dest) gst_value_init_and_copy (dest, src1); return TRUE; @@ -2552,14 +2978,29 @@ gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1, { gint min; gint max; + gint step; - min = MAX (src1->data[0].v_int, src2->data[0].v_int); - max = MIN (src1->data[1].v_int, src2->data[1].v_int); + step = + INT_RANGE_STEP (src1) / + gst_util_greatest_common_divisor (INT_RANGE_STEP (src1), + INT_RANGE_STEP (src2)); + if (G_MAXINT32 / INT_RANGE_STEP (src2) < step) + return FALSE; + step *= INT_RANGE_STEP (src2); + + min = + MAX (INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1), + INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2)); + min = (min + step - 1) / step * step; + max = + MIN (INT_RANGE_MAX (src1) * INT_RANGE_STEP (src1), + INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2)); + max = max / step * step; if (min < max) { if (dest) { g_value_init (dest, GST_TYPE_INT_RANGE); - gst_value_set_int_range (dest, min, max); + gst_value_set_int_range_step (dest, min, max, step); } return TRUE; } @@ -2578,8 +3019,9 @@ static gboolean gst_value_intersect_int64_int64_range (GValue * dest, const GValue * src1, const GValue * src2) { - if (src2->data[0].v_int64 <= src1->data[0].v_int64 && - src2->data[1].v_int64 >= src1->data[0].v_int64) { + if (INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2) <= src1->data[0].v_int && + INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2) >= src1->data[0].v_int && + src1->data[0].v_int % INT64_RANGE_STEP (src2) == 0) { if (dest) gst_value_init_and_copy (dest, src1); return TRUE; @@ -2594,14 +3036,29 @@ gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1, { gint64 min; gint64 max; + gint64 step; + + step = + INT64_RANGE_STEP (src1) / + gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (src1), + INT64_RANGE_STEP (src2)); + if (G_MAXINT64 / INT64_RANGE_STEP (src2) < step) + return FALSE; + step *= INT64_RANGE_STEP (src2); - min = MAX (src1->data[0].v_int64, src2->data[0].v_int64); - max = MIN (src1->data[1].v_int64, src2->data[1].v_int64); + min = + MAX (INT64_RANGE_MIN (src1) * INT64_RANGE_STEP (src1), + INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2)); + min = (min + step - 1) / step * step; + max = + MIN (INT64_RANGE_MAX (src1) * INT64_RANGE_STEP (src1), + INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2)); + max = max / step * step; if (min < max) { if (dest) { g_value_init (dest, GST_TYPE_INT64_RANGE); - gst_value_set_int64_range (dest, min, max); + gst_value_set_int64_range_step (dest, min, max, step); } return TRUE; } @@ -2830,11 +3287,12 @@ gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend, { gint min = gst_value_get_int_range_min (subtrahend); gint max = gst_value_get_int_range_max (subtrahend); + gint step = gst_value_get_int_range_step (subtrahend); gint val = g_value_get_int (minuend); /* subtracting a range from an int only works if the int is not in the * range */ - if (val < min || val > max) { + if (val < min || val > max || val % step) { /* and the result is the int */ if (dest) gst_value_init_and_copy (dest, minuend); @@ -2847,12 +3305,18 @@ gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend, */ static gboolean gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2, - gint max2) + gint max2, gint step) { GValue v1 = { 0, }; GValue v2 = { 0, }; GValue *pv1, *pv2; /* yeah, hungarian! */ + g_return_val_if_fail (step > 0, FALSE); + g_return_val_if_fail (min1 % step == 0, FALSE); + g_return_val_if_fail (max1 % step == 0, FALSE); + g_return_val_if_fail (min2 % step == 0, FALSE); + g_return_val_if_fail (max2 % step == 0, FALSE); + if (min1 <= max1 && min2 <= max2) { pv1 = &v1; pv2 = &v2; @@ -2871,14 +3335,14 @@ gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2, if (min1 < max1) { g_value_init (pv1, GST_TYPE_INT_RANGE); - gst_value_set_int_range (pv1, min1, max1); + gst_value_set_int_range_step (pv1, min1, max1, step); } else if (min1 == max1) { g_value_init (pv1, G_TYPE_INT); g_value_set_int (pv1, min1); } if (min2 < max2) { g_value_init (pv2, GST_TYPE_INT_RANGE); - gst_value_set_int_range (pv2, min2, max2); + gst_value_set_int_range_step (pv2, min2, max2, step); } else if (min2 == max2) { g_value_init (pv2, G_TYPE_INT); g_value_set_int (pv2, min2); @@ -2898,28 +3362,29 @@ gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend, { gint min = gst_value_get_int_range_min (minuend); gint max = gst_value_get_int_range_max (minuend); + gint step = gst_value_get_int_range_step (minuend); gint val = g_value_get_int (subtrahend); g_return_val_if_fail (min < max, FALSE); /* value is outside of the range, return range unchanged */ - if (val < min || val > max) { + if (val < min || val > max || val % step) { if (dest) gst_value_init_and_copy (dest, minuend); return TRUE; } else { /* max must be MAXINT too as val <= max */ - if (val == G_MAXINT) { - max--; - val--; + if (val >= G_MAXINT - step + 1) { + max -= step; + val -= step; } /* min must be MININT too as val >= max */ - if (val == G_MININT) { - min++; - val++; + if (val <= G_MININT + step - 1) { + min += step; + val += step; } if (dest) - gst_value_create_new_range (dest, min, val - 1, val + 1, max); + gst_value_create_new_range (dest, min, val - step, val + step, max, step); } return TRUE; } @@ -2930,18 +3395,30 @@ gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend, { gint min1 = gst_value_get_int_range_min (minuend); gint max1 = gst_value_get_int_range_max (minuend); + gint step1 = gst_value_get_int_range_step (minuend); gint min2 = gst_value_get_int_range_min (subtrahend); gint max2 = gst_value_get_int_range_max (subtrahend); + gint step2 = gst_value_get_int_range_step (subtrahend); + gint step; - if (max2 == G_MAXINT && min2 == G_MININT) { + if (step1 != step2) { + /* ENOIMPL */ + g_assert (FALSE); return FALSE; - } else if (max2 == G_MAXINT) { - return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), 1, 0); - } else if (min2 == G_MININT) { - return gst_value_create_new_range (dest, MAX (max2 + 1, min1), max1, 1, 0); + } + step = step1; + + if (max2 >= max1 && min2 <= min1) { + return FALSE; + } else if (max2 >= max1) { + return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1), + step, 0, step); + } else if (min2 <= min1) { + return gst_value_create_new_range (dest, MAX (max2 + step, min1), max1, + step, 0, step); } else { - return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), - MAX (max2 + 1, min1), max1); + return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1), + MAX (max2 + step, min1), max1, step); } } @@ -2951,11 +3428,12 @@ gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend, { gint64 min = gst_value_get_int64_range_min (subtrahend); gint64 max = gst_value_get_int64_range_max (subtrahend); + gint64 step = gst_value_get_int64_range_step (subtrahend); gint64 val = g_value_get_int64 (minuend); /* subtracting a range from an int64 only works if the int64 is not in the * range */ - if (val < min || val > max) { + if (val < min || val > max || val % step) { /* and the result is the int64 */ if (dest) gst_value_init_and_copy (dest, minuend); @@ -2968,12 +3446,18 @@ gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend, */ static gboolean gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1, - gint64 min2, gint64 max2) + gint64 min2, gint64 max2, gint64 step) { GValue v1 = { 0, }; GValue v2 = { 0, }; GValue *pv1, *pv2; /* yeah, hungarian! */ + g_return_val_if_fail (step > 0, FALSE); + g_return_val_if_fail (min1 % step == 0, FALSE); + g_return_val_if_fail (max1 % step == 0, FALSE); + g_return_val_if_fail (min2 % step == 0, FALSE); + g_return_val_if_fail (max2 % step == 0, FALSE); + if (min1 <= max1 && min2 <= max2) { pv1 = &v1; pv2 = &v2; @@ -2992,14 +3476,14 @@ gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1, if (min1 < max1) { g_value_init (pv1, GST_TYPE_INT64_RANGE); - gst_value_set_int64_range (pv1, min1, max1); + gst_value_set_int64_range_step (pv1, min1, max1, step); } else if (min1 == max1) { g_value_init (pv1, G_TYPE_INT64); g_value_set_int64 (pv1, min1); } if (min2 < max2) { g_value_init (pv2, GST_TYPE_INT64_RANGE); - gst_value_set_int64_range (pv2, min2, max2); + gst_value_set_int64_range_step (pv2, min2, max2, step); } else if (min2 == max2) { g_value_init (pv2, G_TYPE_INT64); g_value_set_int64 (pv2, min2); @@ -3019,28 +3503,30 @@ gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend, { gint64 min = gst_value_get_int64_range_min (minuend); gint64 max = gst_value_get_int64_range_max (minuend); + gint64 step = gst_value_get_int64_range_step (minuend); gint64 val = g_value_get_int64 (subtrahend); g_return_val_if_fail (min < max, FALSE); /* value is outside of the range, return range unchanged */ - if (val < min || val > max) { + if (val < min || val > max || val % step) { if (dest) gst_value_init_and_copy (dest, minuend); return TRUE; } else { /* max must be MAXINT64 too as val <= max */ - if (val == G_MAXINT64) { - max--; - val--; + if (val >= G_MAXINT64 - step + 1) { + max -= step; + val -= step; } /* min must be MININT64 too as val >= max */ - if (val == G_MININT64) { - min++; - val++; + if (val <= G_MININT64 + step - 1) { + min += step; + val += step; } if (dest) - gst_value_create_new_int64_range (dest, min, val - 1, val + 1, max); + gst_value_create_new_int64_range (dest, min, val - step, val + step, max, + step); } return TRUE; } @@ -3051,20 +3537,30 @@ gst_value_subtract_int64_range_int64_range (GValue * dest, { gint64 min1 = gst_value_get_int64_range_min (minuend); gint64 max1 = gst_value_get_int64_range_max (minuend); + gint64 step1 = gst_value_get_int64_range_step (minuend); gint64 min2 = gst_value_get_int64_range_min (subtrahend); gint64 max2 = gst_value_get_int64_range_max (subtrahend); + gint64 step2 = gst_value_get_int64_range_step (subtrahend); + gint64 step; - if (max2 == G_MAXINT64 && min2 == G_MININT64) { + if (step1 != step2) { + /* ENOIMPL */ + g_assert (FALSE); return FALSE; - } else if (max2 == G_MAXINT64) { - return gst_value_create_new_int64_range (dest, min1, MIN (min2 - 1, max1), - 1, 0); - } else if (min2 == G_MININT64) { - return gst_value_create_new_int64_range (dest, MAX (max2 + 1, min1), max1, - 1, 0); + } + step = step1; + + if (max2 >= max1 && min2 <= min1) { + return FALSE; + } else if (max2 >= max1) { + return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step, + max1), step, 0, step); + } else if (min2 <= min1) { + return gst_value_create_new_int64_range (dest, MAX (max2 + step, min1), + max1, step, 0, step); } else { - return gst_value_create_new_int64_range (dest, min1, MIN (min2 - 1, max1), - MAX (max2 + 1, min1), max1); + return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step, + max1), MAX (max2 + step, min1), max1, step); } } @@ -3407,14 +3903,15 @@ gst_value_list_equals_range (const GValue * list, const GValue * value) if (CHECK_TYPES (INT, G)) { const gint rmin = gst_value_get_int_range_min (value); const gint rmax = gst_value_get_int_range_max (value); + const gint rstep = gst_value_get_int_range_step (value); /* note: this will overflow for min 0 and max INT_MAX, but this would only be equal to a list of INT_MAX elements, which seems very unlikely */ - if (list_size != rmax - rmin + 1) + if (list_size != rmax / rstep - rmin / rstep + 1) return FALSE; for (n = 0; n < list_size; ++n) { gint v = g_value_get_int (VALUE_LIST_GET_VALUE (list, n)); - if (v < rmin || v > rmax) { + if (v < rmin || v > rmax || v % rstep) { return FALSE; } } @@ -3422,12 +3919,13 @@ gst_value_list_equals_range (const GValue * list, const GValue * value) } else if (CHECK_TYPES (INT64, G)) { const gint64 rmin = gst_value_get_int64_range_min (value); const gint64 rmax = gst_value_get_int64_range_max (value); + const gint64 rstep = gst_value_get_int64_range_step (value); GST_DEBUG ("List/range of int64s"); - if (list_size != rmax - rmin + 1) + if (list_size != rmax / rstep - rmin / rstep + 1) return FALSE; for (n = 0; n < list_size; ++n) { gint64 v = g_value_get_int64 (VALUE_LIST_GET_VALUE (list, n)); - if (v < rmin || v > rmax) + if (v < rmin || v > rmax || v % rstep) return FALSE; } return TRUE; @@ -4919,7 +5417,7 @@ GType gst_ ## type ## _get_type (void) \ static const GTypeValueTable _gst_int_range_value_table = { gst_value_init_int_range, - NULL, + gst_value_free_int_range, gst_value_copy_int_range, NULL, (char *) "ii", @@ -4932,7 +5430,7 @@ FUNC_VALUE_GET_TYPE (int_range, "GstIntRange"); static const GTypeValueTable _gst_int64_range_value_table = { gst_value_init_int64_range, - NULL, + gst_value_free_int64_range, gst_value_copy_int64_range, NULL, (char *) "qq", diff --git a/gst/gstvalue.h b/gst/gstvalue.h index dcf9e24..1fe64c4 100644 --- a/gst/gstvalue.h +++ b/gst/gstvalue.h @@ -476,15 +476,25 @@ const GValue * gst_value_array_get_value (const GValue *value, void gst_value_set_int_range (GValue *value, gint start, gint end); +void gst_value_set_int_range_step (GValue *value, + gint start, + gint end, + gint step); gint gst_value_get_int_range_min (const GValue *value); gint gst_value_get_int_range_max (const GValue *value); +gint gst_value_get_int_range_step (const GValue *value); /* int64 range */ void gst_value_set_int64_range (GValue *value, gint64 start, gint64 end); +void gst_value_set_int64_range_step (GValue *value, + gint64 start, + gint64 end, + gint64 step); gint64 gst_value_get_int64_range_min (const GValue *value); gint64 gst_value_get_int64_range_max (const GValue *value); +gint64 gst_value_get_int64_range_step (const GValue *value); /* double range */ void gst_value_set_double_range (GValue *value, @@ -539,6 +549,9 @@ gint gst_value_compare (const GValue *value1, const GValue *value2); gboolean gst_value_can_compare (const GValue *value1, const GValue *value2); +gboolean gst_value_is_subset (const GValue *value1, + const GValue *value2); + /* union */ gboolean gst_value_union (GValue *dest, const GValue *value1, diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 6127ff3..e2ae902 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -1155,6 +1155,7 @@ EXPORTS gst_util_gdouble_to_guint64 gst_util_get_timestamp gst_util_greatest_common_divisor + gst_util_greatest_common_divisor_int64 gst_util_guint64_to_gdouble gst_util_seqnum_compare gst_util_seqnum_next @@ -1190,12 +1191,15 @@ EXPORTS gst_value_get_fraction_range_min gst_value_get_int64_range_max gst_value_get_int64_range_min + gst_value_get_int64_range_step gst_value_get_int_range_max gst_value_get_int_range_min + gst_value_get_int_range_step gst_value_get_structure gst_value_init_and_copy gst_value_intersect gst_value_is_fixed + gst_value_is_subset gst_value_list_append_value gst_value_list_concat gst_value_list_get_size @@ -1215,7 +1219,9 @@ EXPORTS gst_value_set_fraction_range gst_value_set_fraction_range_full gst_value_set_int64_range + gst_value_set_int64_range_step gst_value_set_int_range + gst_value_set_int_range_step gst_value_set_structure gst_value_subtract gst_value_union -- 2.7.4